diff --git a/plugins/woocommerce/changelog/add-validation-for-event-recording-on-client b/plugins/woocommerce/changelog/add-validation-for-event-recording-on-client new file mode 100644 index 00000000000..ce9b3ac4c01 --- /dev/null +++ b/plugins/woocommerce/changelog/add-validation-for-event-recording-on-client @@ -0,0 +1,4 @@ +Significance: patch +Type: add + +Add validations to recordEvent #33911 diff --git a/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php b/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php index 258cb3097bd..efb49276ff8 100644 --- a/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php +++ b/plugins/woocommerce/includes/tracks/class-wc-site-tracking.php @@ -93,6 +93,16 @@ class WC_Site_Tracking { delete( eventProperties._ui ); delete( eventProperties._ut ); } + // Verify the event name is correct + if ( ! .test( eventName ) ) { + console.error( `A valid event name must be specified. The event name: "${ eventName }" is not valid.` ); + } + // Verify the properties are correct + for( prop in eventProperties ) { + if ( ! .test( prop ) ) { + console.error( `A valid prop name must be specified. The property name: "${ prop }" is not valid.` ); + } + } window._tkq = window._tkq || []; window._tkq.push( [ 'recordEvent', eventName, eventProperties ] ); } diff --git a/plugins/woocommerce/includes/tracks/class-wc-tracks-event.php b/plugins/woocommerce/includes/tracks/class-wc-tracks-event.php index e129ce8e854..c7f1377a4d2 100644 --- a/plugins/woocommerce/includes/tracks/class-wc-tracks-event.php +++ b/plugins/woocommerce/includes/tracks/class-wc-tracks-event.php @@ -17,12 +17,12 @@ class WC_Tracks_Event { /** * Event name regex. */ - const EVENT_NAME_REGEX = '/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/'; + public const EVENT_NAME_REGEX = '/^(([a-z0-9]+)_){2}([a-z0-9_]+)$/'; /** * Property name regex. */ - const PROP_NAME_REGEX = '/^[a-z_][a-z0-9_]*$/'; + public const PROP_NAME_REGEX = '/^[a-z_][a-z0-9_]*$/'; /** * Error message as WP_Error. @@ -97,7 +97,7 @@ class WC_Tracks_Event { } foreach ( array_keys( (array) $_event ) as $key ) { - if ( ! self::prop_name_is_valid( $key ) ) { + if ( ! self::prop_name_is_valid( $key ) && '_en' !== $key ) { return new WP_Error( 'invalid_prop_name', __( 'A valid prop name must be specified', 'woocommerce' ) ); } } diff --git a/plugins/woocommerce/tests/php/includes/class-wc-tracks-test.php b/plugins/woocommerce/tests/php/includes/class-wc-tracks-test.php index d0a787c7e20..509adfa3d01 100644 --- a/plugins/woocommerce/tests/php/includes/class-wc-tracks-test.php +++ b/plugins/woocommerce/tests/php/includes/class-wc-tracks-test.php @@ -14,6 +14,7 @@ class WC_Tracks_Test extends \WC_Unit_Test_Case { parent::setUp(); include_once WC_ABSPATH . 'includes/tracks/class-wc-tracks.php'; include_once WC_ABSPATH . 'includes/tracks/class-wc-tracks-client.php'; + include_once WC_ABSPATH . 'includes/tracks/class-wc-tracks-event.php'; } /** @@ -60,4 +61,72 @@ class WC_Tracks_Test extends \WC_Unit_Test_Case { $this->assertNotEquals( 'bad', $properties['_ut'] ); } + /** + * Test the event validation and sanitization with a valid event. + */ + public function test_event_validation_and_sanitization_valid_event() { + $event_props = array( + '_en' => 'valid_event_name', + '_ts' => WC_Tracks_Client::build_timestamp(), + 'valid_property' => 'My value', + '_via_ip' => '192.168.10.1', + ); + + // Valid event and property names. + $event = \WC_Tracks_Event::validate_and_sanitize( $event_props ); + $this->assertTrue( property_exists( $event, 'browser_type' ) ); + $this->assertTrue( property_exists( $event, '_ts' ) ); + $this->assertTrue( property_exists( $event, 'valid_property' ) ); + $this->assertFalse( property_exists( $event, '_via_ip' ) ); + } + + /** + * Test the event validation and sanitization with an invalid event. + */ + public function test_event_validation_and_sanitization_invalid_event_name() { + $event_props = array( + '_en' => 'valid_event_name', + '_ts' => WC_Tracks_Client::build_timestamp(), + 'valid_property' => 'My value', + '_via_ip' => '192.168.10.1', + ); + + // Invalid event name. + $event = \WC_Tracks_Event::validate_and_sanitize( + array_merge( + $event_props, + array( '_en' => 'invalidName' ) + ) + ); + $this->assertTrue( is_wp_error( $event ) ); + $this->assertEquals( $event->get_error_code(), 'invalid_event_name' ); + + $event = \WC_Tracks_Event::validate_and_sanitize( + array_merge( + $event_props, + array( '_en' => 'invalid-name' ) + ) + ); + $this->assertTrue( is_wp_error( $event ) ); + $this->assertEquals( $event->get_error_code(), 'invalid_event_name' ); + + // Invalid property name. + $event = \WC_Tracks_Event::validate_and_sanitize( + array_merge( + $event_props, + array( 'invalid-property-name' => 'My value' ) + ) + ); + $this->assertTrue( is_wp_error( $event ) ); + $this->assertEquals( $event->get_error_code(), 'invalid_prop_name' ); + + $event = \WC_Tracks_Event::validate_and_sanitize( + array_merge( + $event_props, + array( 'invalid property name' => 'My value' ) + ) + ); + $this->assertTrue( is_wp_error( $event ) ); + $this->assertEquals( $event->get_error_code(), 'invalid_prop_name' ); + } }