From 689a3d639131014eb995446d0a2e86df141e8a34 Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Fri, 3 Jan 2025 14:20:18 -0800 Subject: [PATCH 1/4] Fix: #14912 --- .../forms/src/contact-form/class-contact-form-field.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/packages/forms/src/contact-form/class-contact-form-field.php b/projects/packages/forms/src/contact-form/class-contact-form-field.php index cb234ac6a2889..afdf682d9950a 100644 --- a/projects/packages/forms/src/contact-form/class-contact-form-field.php +++ b/projects/packages/forms/src/contact-form/class-contact-form-field.php @@ -1033,7 +1033,7 @@ public function render_field( $type, $id, $label, $value, $class, $placeholder, $field .= "\n
\n"; // new in Jetpack 6.8.0 // If they are logged in, and this is their site, don't pre-populate fields - if ( current_user_can( 'manage_options' ) ) { + if ( current_user_can( 'manage_options' ) && isset( $type ) && $type !== 'checkbox' ) { $value = ''; } From 1d1c5b7e9f2cbddc4dfe3873b00507f554ec64cf Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Fri, 3 Jan 2025 14:23:32 -0800 Subject: [PATCH 2/4] changelog --- projects/packages/forms/changelog/fix-checkbox-checked-state | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 projects/packages/forms/changelog/fix-checkbox-checked-state diff --git a/projects/packages/forms/changelog/fix-checkbox-checked-state b/projects/packages/forms/changelog/fix-checkbox-checked-state new file mode 100644 index 0000000000000..93093a7ae3ad5 --- /dev/null +++ b/projects/packages/forms/changelog/fix-checkbox-checked-state @@ -0,0 +1,4 @@ +Significance: patch +Type: fixed + +Form: fix the default checkstate for admins From efba70f04166662cdad2f48262699cffb858cffd Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Fri, 17 Jan 2025 11:54:01 -0800 Subject: [PATCH 3/4] Fix the check that lets you prefills the form fields --- .../contact-form/class-contact-form-field.php | 106 ++++++++++-------- 1 file changed, 60 insertions(+), 46 deletions(-) diff --git a/projects/packages/forms/src/contact-form/class-contact-form-field.php b/projects/packages/forms/src/contact-form/class-contact-form-field.php index afdf682d9950a..9482f87d5e938 100644 --- a/projects/packages/forms/src/contact-form/class-contact-form-field.php +++ b/projects/packages/forms/src/contact-form/class-contact-form-field.php @@ -280,7 +280,6 @@ public function get_option_value( $value, $index, $options ) { * @return string HTML */ public function render() { - global $current_user, $user_identity; $field_id = $this->get_attribute( 'id' ); $field_type = $this->maybe_override_type(); @@ -359,46 +358,7 @@ public function render() { */ $field_class = apply_filters( 'jetpack_contact_form_input_class', $class ); - if ( isset( $_POST[ $field_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. - if ( is_array( $_POST[ $field_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. - $this->value = array_map( 'sanitize_textarea_field', wp_unslash( $_POST[ $field_id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. - } else { - $this->value = sanitize_textarea_field( wp_unslash( $_POST[ $field_id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. - } - } elseif ( isset( $_GET[ $field_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no site changes. - $this->value = sanitize_textarea_field( wp_unslash( $_GET[ $field_id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no site changes. - } elseif ( - is_user_logged_in() && - ( ( defined( 'IS_WPCOM' ) && IS_WPCOM ) || - /** - * Allow third-party tools to prefill the contact form with the user's details when they're logged in. - * - * @module contact-form - * - * @since 3.2.0 - * - * @param bool false Should the Contact Form be prefilled with your details when you're logged in. Default to false. - */ - true === apply_filters( 'jetpack_auto_fill_logged_in_user', false ) - ) - ) { - // Special defaults for logged-in users - switch ( $field_type ) { - case 'email': - $this->value = $current_user->data->user_email; - break; - case 'name': - $this->value = $user_identity; - break; - case 'url': - $this->value = $current_user->data->user_url; - break; - default: - $this->value = $this->get_attribute( 'default' ); - } - } else { - $this->value = $this->get_attribute( 'default' ); - } + $this->value = $this->get_computed_field_value( $field_type, $field_id ); $field_value = Contact_Form_Plugin::strip_tags( $this->value ); $field_label = Contact_Form_Plugin::strip_tags( $field_label ); @@ -418,6 +378,65 @@ public function render() { */ return apply_filters( 'grunion_contact_form_field_html', $rendered_field, $field_label, ( in_the_loop() ? get_the_ID() : null ) ); } + /** + * Returns the computed field value for a field. It uses the POST, GET, Logged in data. + * + * @module contact-form + * + * @param string $field_type The field type. + * @param string $field_id The field id. + * + * @return string; + */ + public function get_computed_field_value( $field_type, $field_id ) { + global $current_user, $user_identity; + // Use the POST Field if it is available. + if ( isset( $_POST[ $field_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. + if ( is_array( $_POST[ $field_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. + return array_map( 'sanitize_textarea_field', wp_unslash( $_POST[ $field_id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. + } + + return sanitize_textarea_field( wp_unslash( $_POST[ $field_id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- no site changes. + } + + // Use the GET Field if it is available. + if ( isset( $_GET[ $field_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no site changes. + if ( is_array( $_GET[ $field_id ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no site changes. + return array_map( 'sanitize_textarea_field', wp_unslash( $_GET[ $field_id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no site changes. + } + + return sanitize_textarea_field( wp_unslash( $_GET[ $field_id ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- no site changes. + } + + if ( ! is_user_logged_in() ) { + return $this->get_attribute( 'default' ); + } + + /** + * Allow third-party tools to prefill the contact form with the user's details when they're logged in. + * + * @module contact-form + * + * @since 3.2.0 + * + * @param bool false Should the Contact Form be prefilled with your details when you're logged in. Default to false. + */ + $filter_value = apply_filters( 'jetpack_auto_fill_logged_in_user', false ); + if ( ( ! current_user_can( 'manage_options' ) && ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) || $filter_value ) { + switch ( $field_type ) { + case 'email': + return $current_user->data->user_email; + + case 'name': + return ! empty( $user_identity ) ? $user_identity : $current_user->data->display_name; + + case 'url': + return $current_user->data->user_url; + } + } + + return $this->get_attribute( 'default' ); + } /** * Return the HTML for the label. @@ -1032,11 +1051,6 @@ public function render_field( $type, $id, $label, $value, $class, $placeholder, $field .= "\n
\n"; // new in Jetpack 6.8.0 - // If they are logged in, and this is their site, don't pre-populate fields - if ( current_user_can( 'manage_options' ) && isset( $type ) && $type !== 'checkbox' ) { - $value = ''; - } - switch ( $type ) { case 'email': $field .= $this->render_email_field( $id, $label, $value, $field_class, $required, $required_field_text, $field_placeholder ); From 15f872927c0f0203a5bdb2699e159f6922f36d06 Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Fri, 17 Jan 2025 12:02:29 -0800 Subject: [PATCH 4/4] Add tests --- .../contact-form/class-contact-form-field.php | 2 +- .../test-class.contact-form-field.php | 162 ++++++++++++++++++ 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 projects/packages/forms/tests/php/contact-form/test-class.contact-form-field.php diff --git a/projects/packages/forms/src/contact-form/class-contact-form-field.php b/projects/packages/forms/src/contact-form/class-contact-form-field.php index 9482f87d5e938..0a4701185d910 100644 --- a/projects/packages/forms/src/contact-form/class-contact-form-field.php +++ b/projects/packages/forms/src/contact-form/class-contact-form-field.php @@ -386,7 +386,7 @@ public function render() { * @param string $field_type The field type. * @param string $field_id The field id. * - * @return string; + * @return string */ public function get_computed_field_value( $field_type, $field_id ) { global $current_user, $user_identity; diff --git a/projects/packages/forms/tests/php/contact-form/test-class.contact-form-field.php b/projects/packages/forms/tests/php/contact-form/test-class.contact-form-field.php new file mode 100644 index 0000000000000..19cdc676e05b6 --- /dev/null +++ b/projects/packages/forms/tests/php/contact-form/test-class.contact-form-field.php @@ -0,0 +1,162 @@ + 'admin', + 'user_pass' => 'pass', + 'user_email' => 'admin@admin.com', + 'role' => 'reader', + 'user_url' => 'https://example.com', + ) + ); + + // Simulate a logged-in user + wp_set_current_user( $user_id ); + $user_identity = 'Test User'; + } + + protected function tearDown(): void { + parent::tearDown(); + global $current_user, $user_identity; + + // Clean up globals + unset( $_POST, $_GET, $current_user, $user_identity ); + } + + /** + * Helper function to invoke the function from the class. + */ + private function invoke_get_computed_field_value( $field_type, $field_id ) { + $field = $this->get_new_field_instance( + array( + 'type' => $field_type, + 'id' => $field_id, + ) + ); + return $field->get_computed_field_value( $field_type, $field_id ); + } + + private function get_new_field_instance( $attributes ) { + $defaults = array( + 'type' => 'text', + 'id' => 'id', + 'default' => 'default', + ); + + return new Contact_Form_Field( wp_parse_args( $attributes, $defaults ) ); + } + + /** + * Test handling $_POST single value + */ + public function test_handles_post_single_value() { + $_POST['test_field'] = 'Post Value'; + + $result = $this->invoke_get_computed_field_value( 'text', 'test_field' ); + + $this->assertEquals( 'Post Value', $result ); + } + + /** + * Test handling $_POST array value + */ + public function test_handles_post_array_value() { + $_POST['test_field'] = array( 'value1', 'value2' ); + + $result = $this->invoke_get_computed_field_value( 'text', 'test_field' ); + + $this->assertEquals( array( 'value1', 'value2' ), $result ); + } + + /** + * Test handling $_GET single value + */ + public function test_handles_get_single_value() { + $_GET['test_field'] = 'Get Value'; + + $result = $this->invoke_get_computed_field_value( 'text', 'test_field' ); + + $this->assertEquals( 'Get Value', $result ); + } + + /** + * Test handling $_GET array value + */ + public function test_handles_get_array_value() { + $_GET['test_field'] = array( 'value1', 'value2' ); + + $result = $this->invoke_get_computed_field_value( 'text', 'test_field' ); + + $this->assertEquals( array( 'value1', 'value2' ), $result ); + } + + /** + * Test logged-in user email return + */ + public function test_returns_logged_in_user_email() { + add_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + $result = $this->invoke_get_computed_field_value( 'email', 'test_field' ); + remove_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + + $this->assertEquals( 'admin@admin.com', $result ); + } + + /** + * Test logged-in user name return + */ + public function test_returns_logged_in_user_name() { + add_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + $result = $this->invoke_get_computed_field_value( 'name', 'test_field' ); + remove_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + + $this->assertEquals( 'Test User', $result ); + } + + /** + * Test logged-in user URL return + */ + public function test_returns_logged_in_user_url() { + add_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + $result = $this->invoke_get_computed_field_value( 'url', 'test_field' ); + remove_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + + $this->assertEquals( 'https://example.com', $result ); + } + + /** + * Test logged-in user URL return + */ + public function test_returns_logged_out_user_url() { + global $current_user; + unset( $current_user ); + wp_set_current_user( 0 ); + + add_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + $result = $this->invoke_get_computed_field_value( 'url', 'test_field' ); + remove_filter( 'jetpack_auto_fill_logged_in_user', '__return_true' ); + + $this->assertEquals( 'default', $result ); + } +} // end class