From ef7f29f78f4e65a4f00557fb20d68a53cf805b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 10 Jan 2025 14:54:52 +0100 Subject: [PATCH 1/3] Remove empty issuers field during form render. --- src/IssuersField.php | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/IssuersField.php b/src/IssuersField.php index 46f7d6b..11aa4a5 100644 --- a/src/IssuersField.php +++ b/src/IssuersField.php @@ -60,6 +60,15 @@ public function __construct( $properties = [] ) { add_action( 'gform_editor_js_set_default_values', [ __CLASS__, 'editor_js_set_default_values' ] ); } + // Filters. + if ( ! has_filter( 'gform_pre_render', [ $this, 'maybe_remove_empty_issuers_field' ] ) ) { + \add_filter( 'gform_pre_render', [ $this, 'maybe_remove_empty_issuers_field' ] ); + } + + if ( ! has_filter( 'gform_field_validation', [ $this, 'maybe_validate_empty_issuers_field' ] ) ) { + \add_filter( 'gform_field_validation', [ $this, 'maybe_validate_empty_issuers_field' ], 10, 4 ); + } + if ( ! isset( $this->formId ) && @@ -673,4 +682,47 @@ public static function editor_js_set_default_values() { break; $field ) { + if ( self::TYPE !== $field['type'] ) { + continue; + } + + if ( 0 !== count( $field['choices'] ) ) { + continue; + } + + unset( $form['fields'][ $key ] ); + } + + return $form; + } + + /** + * Skip validation for issuers fields without any choices. + * + * @param array $result Validation result. + * @param mixed $value Field value. + * @param array $form Form. + * @param array $field Field. + * @return array + */ + public function maybe_validate_empty_issuers_field( $result, $value, $form, $field ) { + if ( self::TYPE !== $field['type'] ) { + return $result; + } + + if ( 0 === count( $field['choices'] ) ) { + $result['is_valid'] = true; + } + + return $result; + } } From 9f853ecabe6d4b76cacfbe93279d27da52ed7dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 13 Jan 2025 12:01:24 +0100 Subject: [PATCH 2/3] Revert "Remove empty issuers field during form render." This reverts commit ef7f29f78f4e65a4f00557fb20d68a53cf805b49. --- src/IssuersField.php | 52 -------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/src/IssuersField.php b/src/IssuersField.php index 11aa4a5..46f7d6b 100644 --- a/src/IssuersField.php +++ b/src/IssuersField.php @@ -60,15 +60,6 @@ public function __construct( $properties = [] ) { add_action( 'gform_editor_js_set_default_values', [ __CLASS__, 'editor_js_set_default_values' ] ); } - // Filters. - if ( ! has_filter( 'gform_pre_render', [ $this, 'maybe_remove_empty_issuers_field' ] ) ) { - \add_filter( 'gform_pre_render', [ $this, 'maybe_remove_empty_issuers_field' ] ); - } - - if ( ! has_filter( 'gform_field_validation', [ $this, 'maybe_validate_empty_issuers_field' ] ) ) { - \add_filter( 'gform_field_validation', [ $this, 'maybe_validate_empty_issuers_field' ], 10, 4 ); - } - if ( ! isset( $this->formId ) && @@ -682,47 +673,4 @@ public static function editor_js_set_default_values() { break; $field ) { - if ( self::TYPE !== $field['type'] ) { - continue; - } - - if ( 0 !== count( $field['choices'] ) ) { - continue; - } - - unset( $form['fields'][ $key ] ); - } - - return $form; - } - - /** - * Skip validation for issuers fields without any choices. - * - * @param array $result Validation result. - * @param mixed $value Field value. - * @param array $form Form. - * @param array $field Field. - * @return array - */ - public function maybe_validate_empty_issuers_field( $result, $value, $form, $field ) { - if ( self::TYPE !== $field['type'] ) { - return $result; - } - - if ( 0 === count( $field['choices'] ) ) { - $result['is_valid'] = true; - } - - return $result; - } } From 17f30a4e4a335e738c8333fc891bab656bd43e45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 13 Jan 2025 14:48:18 +0100 Subject: [PATCH 3/3] Use iDEAL issuer service for fallback options in issuers field. --- src/IssuersField.php | 175 +++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/src/IssuersField.php b/src/IssuersField.php index 46f7d6b..14f039d 100644 --- a/src/IssuersField.php +++ b/src/IssuersField.php @@ -13,9 +13,9 @@ use GF_Field_Select; use Pronamic\IDealIssuers\IDealIssuerCode; use Pronamic\IDealIssuers\IDealIssuerService; -use Pronamic\WordPress\Pay\Core\Gateway; -use Pronamic\WordPress\Pay\Fields\IDealIssuerSelectField; use Pronamic\WordPress\Pay\Core\PaymentMethods; +use Pronamic\WordPress\Pay\Fields\IDealIssuerSelectField; +use Pronamic\WordPress\Pay\Fields\SelectFieldOption; use Pronamic\WordPress\Pay\Plugin; /** @@ -132,124 +132,121 @@ public function get_form_editor_field_icon() { } /** - * Get the iDEAL gateway for this field. + * Set the issuer choices for this issuers field. * - * @return null|Gateway + * @param int $form_id Gravity Forms form ID. */ - private function get_gateway() { - $gateway = null; + private function set_choices( $form_id ) { + $this->choices = []; - if ( isset( $this->pronamicPayConfigId ) && ! empty( $this->pronamicPayConfigId ) ) { - $gateway = Plugin::get_gateway( $this->pronamicPayConfigId ); + // Prevent HTTP requests in forms list. + if ( \doing_filter( 'gform_form_actions' ) ) { + return; } - if ( ! $gateway ) { - $feeds = FeedsDB::get_feeds_by_form_id( $this->formId ); + $options = $this->get_ideal_issuer_select_field_options(); - foreach ( $feeds as $feed ) { - // Check if feed is active. - if ( '0' === get_post_meta( $feed->id, '_pronamic_pay_gf_feed_active', true ) ) { - continue; - } - - $gateway = Plugin::get_gateway( $feed->config_id ); + if ( null === $options ) { + /* + * When an issuers field is marked as required and there are no choices, + * validation of the form submission will fail. However, a hosted payment + * page of the payment gateway might still be able to process the payment. + * Therefore, we fall back to a static list of iDEAL issuers in these cases. + * + * @link https://github.com/pronamic/wp-pronamic-pay-gravityforms/issues/47 + */ + $ideal_issuer_service = new IDealIssuerService(); - if ( null === $gateway ) { - continue; - } + $issuers = $ideal_issuer_service->get_issuers(); - // Always use iDEAL payment method for issuer field. - $issuer_field = $gateway->first_payment_method_field( PaymentMethods::IDEAL, IDealIssuerSelectField::class ); + $options = []; - if ( null === $issuer_field ) { - continue; - } + foreach ( $issuers as $issuer ) { + $options[] = new SelectFieldOption( $issuer->code, $issuer->name ); + } + } - /** - * The iDEAL issuer field options can be requested from the - * gateway and that can result in exceptions. In this case, - * that's no problem and we'll move on to the next - * feed/gateway. - * - * @link https://github.com/pronamic/wp-pronamic-pay-gravityforms/issues/10 - */ - try { - $options = $issuer_field->get_options(); - } catch ( \Exception $e ) { - continue; - } + foreach ( $options as $option ) { + /** + * Gravity Forms automatically fills an empty value with the label. + * For a first empty choice option, Gravity Forms works with a + * `placeholder` property. + * + * @link https://github.com/pronamic/wp-pronamic-pay-gravityforms/issues/19 + */ + if ( '' === $option->value ) { + $this->placeholder = $option->label; - return $gateway; + continue; } - } - return $gateway; + $this->choices[] = [ + 'value' => $option->value, + 'text' => $option->label, + ]; + } } /** - * Set the issuer choices for this issuers field. + * Get the iDEAL issuer select field options from gateway for this field. * - * @param int $form_id Gravity Forms form ID. + * @return SelectFieldOption[]|null */ - private function set_choices( $form_id ) { - $this->choices = []; + private function get_ideal_issuer_select_field_options() { + $config_ids = null; - // Prevent HTTP requests in forms list. - if ( \doing_filter( 'gform_form_actions' ) ) { - return; + if ( isset( $this->pronamicPayConfigId ) && ! empty( $this->pronamicPayConfigId ) ) { + $config_ids = [ + $this->pronamicPayConfigId, + ]; } - $gateway = $this->get_gateway(); + if ( null === $config_ids ) { + $feeds = \array_filter( + FeedsDB::get_feeds_by_form_id( $this->formId ), + function ( $feed ) { + // Check if feed is active. + return '0' !== \get_post_meta( $feed->id, '_pronamic_pay_gf_feed_active', true ); + } + ); - if ( ! $gateway ) { - return; + $config_ids = \wp_list_pluck( $feeds, 'config_id' ); } - // Always use iDEAL payment method for issuer field. - $issuer_field = $gateway->first_payment_method_field( PaymentMethods::IDEAL, IDealIssuerSelectField::class ); + foreach ( $config_ids as $config_id ) { + $gateway = Plugin::get_gateway( $config_id ); - if ( null === $issuer_field ) { - return; - } + if ( null === $gateway ) { + continue; + } + + $issuer_field = $gateway->first_payment_method_field( PaymentMethods::IDEAL, IDealIssuerSelectField::class ); + + if ( null === $issuer_field ) { + continue; + } - /** - * The iDEAL issuer field options can be requested from the - * gateway and that can result in exceptions. In this case, - * that's no problem and we'll move on to the next - * feed/gateway. - * - * @link https://github.com/pronamic/wp-pronamic-pay-gravityforms/issues/10 - */ - try { /** - * Gravity Forms has no support for elements. + * Exceptions can occur when requesting iDEAL issuer field options, + * but we'll just move on to the next feed/gateway. * - * @link https://github.com/pronamic/wp-pronamic-pay/issues/154#issuecomment-1183309350 + * @link https://github.com/pronamic/wp-pronamic-pay-gravityforms/issues/10 */ - $options = $issuer_field->get_flat_options(); - - foreach ( $options as $option ) { + try { /** - * Gravity Forms automatically fills an empty value with the label. - * For a first empty choice option, Gravity Forms works with a - * `placeholder` property. + * Gravity Forms has no support for elements. * - * @link https://github.com/pronamic/wp-pronamic-pay-gravityforms/issues/19 + * @link https://github.com/pronamic/wp-pronamic-pay/issues/154#issuecomment-1183309350 */ - if ( '' === $option->value ) { - $this->placeholder = $option->label; - - continue; - } - - $this->choices[] = [ - 'value' => $option->value, - 'text' => $option->label, - ]; + $options = $issuer_field->get_flat_options(); + } catch ( \Exception $e ) { + continue; } - } catch ( \Exception $e ) { - return; + + return $options; } + + return null; } /** @@ -596,8 +593,10 @@ public function get_field_input( $form, $value = '', $entry = null ) { $input = $link . $input; } - if ( ! empty( $feeds ) && empty( $this->choices ) ) { - // If there are feeds and no choices it's very likely this field is no supported by the gateway. + $options = $this->get_ideal_issuer_select_field_options(); + + if ( ! empty( $feeds ) && null === $options ) { + // If there are feeds but no gateway issuer options, it's very likely this field is not supported by the gateway. $error = sprintf( '

%s
%s

', __( 'This field is not supported by your payment gateway.', 'pronamic_ideal' ),