diff --git a/inc/admin-pages/class-checkout-form-edit-admin-page.php b/inc/admin-pages/class-checkout-form-edit-admin-page.php index 9a237bdb6..a33b68bdf 100644 --- a/inc/admin-pages/class-checkout-form-edit-admin-page.php +++ b/inc/admin-pages/class-checkout-form-edit-admin-page.php @@ -525,7 +525,15 @@ public function get_create_field_fields($attributes = []) { foreach ($field_types as $field_type) { $_fields = call_user_func($field_type['fields'], $attributes); - $additional_fields = array_merge($additional_fields, $_fields); + foreach ($_fields as $field_slug => $field) { + if (isset($additional_fields[ $field_slug ])) { + $additional_fields[ $field_slug ] = $this->merge_duplicate_field_type_field($additional_fields[ $field_slug ], $field); + + continue; + } + + $additional_fields[ $field_slug ] = $field; + } } $default_fields = \WP_Ultimo\Checkout\Signup_Fields\Base_Signup_Field::fields_list(); @@ -583,6 +591,33 @@ public function get_create_field_fields($attributes = []) { return $fields; } + /** + * Merges editor fields that use the same attribute key across field types. + * + * Add-ons can register field types with editor attributes that collide with + * core field attributes, for example an add-on field that also uses a + * `product` selector. Keeping only the last field hides the earlier selector + * because its Vue visibility condition is replaced. Preserve the first field + * configuration and make it visible for both field types. + * + * @since 2.4.13 + * + * @param array $existing_field Previously registered editor field. + * @param array $new_field New editor field using the same key. + * @return array + */ + protected function merge_duplicate_field_type_field($existing_field, $new_field) { + + $existing_show = wu_get_isset($existing_field, 'wrapper_html_attr', [])['v-show'] ?? ''; + $new_show = wu_get_isset($new_field, 'wrapper_html_attr', [])['v-show'] ?? ''; + + if ($existing_show && $new_show && $existing_show !== $new_show) { + $existing_field['wrapper_html_attr']['v-show'] = sprintf('(%s) || (%s)', $existing_show, $new_show); + } + + return $existing_field; + } + /** * Gets the field from the checkout step OR from the session. * diff --git a/inc/checkout/signup-fields/class-signup-field-order-bump.php b/inc/checkout/signup-fields/class-signup-field-order-bump.php index d990a6ba5..6e5127c05 100644 --- a/inc/checkout/signup-fields/class-signup-field-order-bump.php +++ b/inc/checkout/signup-fields/class-signup-field-order-bump.php @@ -110,6 +110,7 @@ public function get_icon() { public function defaults() { return [ + 'product' => '', 'order_bump_template' => 'simple', 'display_product_description' => 0, ]; @@ -172,6 +173,7 @@ public function get_fields() { 'tooltip' => '', 'order' => 12, 'html_attr' => [ + 'v-model' => 'product', 'data-model' => 'product', 'data-value-field' => 'id', 'data-label-field' => 'name', diff --git a/tests/WP_Ultimo/Checkout/Signup_Fields/Signup_Field_Order_Bump_Test.php b/tests/WP_Ultimo/Checkout/Signup_Fields/Signup_Field_Order_Bump_Test.php index 5d30cb6d8..26a1d38b7 100644 --- a/tests/WP_Ultimo/Checkout/Signup_Fields/Signup_Field_Order_Bump_Test.php +++ b/tests/WP_Ultimo/Checkout/Signup_Fields/Signup_Field_Order_Bump_Test.php @@ -97,6 +97,8 @@ public function test_is_site_field(): void { public function test_defaults(): void { $defaults = $this->field->defaults(); $this->assertIsArray( $defaults ); + $this->assertArrayHasKey( 'product', $defaults ); + $this->assertEquals( '', $defaults['product'] ); $this->assertArrayHasKey( 'order_bump_template', $defaults ); $this->assertEquals( 'simple', $defaults['order_bump_template'] ); $this->assertArrayHasKey( 'display_product_description', $defaults ); @@ -141,6 +143,14 @@ public function test_get_fields_product_is_model_type(): void { $this->assertEquals( 'model', $fields['product']['type'] ); } + /** + * Test product field is bound to modal state. + */ + public function test_get_fields_product_is_bound_to_modal_state(): void { + $fields = $this->field->get_fields(); + $this->assertEquals( 'product', $fields['product']['html_attr']['v-model'] ); + } + /** * Test get_fields display_product_description is toggle type. */