Update tracks events hooks for HPOS (#42879)
* Update ‘orders_view’ tracks event for HPOS * Update ‘orders_view_search’ tracks event for HPOS * Update ‘order_edit_date_created’ tracks event for HPOS * Update ‘order_edit_add_order’ tracks event for HPOS * Correctly enqueue order tracking JS scripts when HPOS is active * Address TS script * Change add_filter() to add_action() * Fix tests * Add changelog * Fix some linting issues * Make PHPCS happy * Better handle deprecating old method * Fix condition
This commit is contained in:
parent
5d5fc57e8c
commit
69a864af67
|
@ -10,9 +10,10 @@ import { staticFormDataToObject } from '~/utils/static-form-helper';
|
|||
|
||||
type FormElements = {
|
||||
post?: HTMLFormElement;
|
||||
order?: HTMLFormElement;
|
||||
} & HTMLCollectionOf< HTMLFormElement >;
|
||||
const forms: FormElements = document.forms;
|
||||
if ( forms?.post ) {
|
||||
if ( forms?.post || forms?.order ) {
|
||||
let triggeredSaveOrDeleteButton = false;
|
||||
const saveButton = document.querySelector( '.save_order' );
|
||||
const deleteButton = document.querySelector( '.submitdelete' );
|
||||
|
@ -27,14 +28,19 @@ if ( forms?.post ) {
|
|||
triggeredSaveOrDeleteButton = true;
|
||||
} );
|
||||
}
|
||||
const formData = staticFormDataToObject( forms.post );
|
||||
const formData = staticFormDataToObject(
|
||||
( forms?.post || forms?.order ) as HTMLFormElement
|
||||
);
|
||||
addCustomerEffortScoreExitPageListener( 'shop_order_update', () => {
|
||||
if ( triggeredSaveOrDeleteButton ) {
|
||||
return false;
|
||||
}
|
||||
const newFormData = forms.post
|
||||
? staticFormDataToObject( forms.post )
|
||||
: {};
|
||||
const newFormData =
|
||||
forms?.post || forms?.order
|
||||
? staticFormDataToObject(
|
||||
( forms?.post || forms?.order ) as HTMLFormElement
|
||||
)
|
||||
: {};
|
||||
for ( const key of Object.keys( formData ) ) {
|
||||
const value =
|
||||
typeof formData[ key ] === 'object'
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Update a few Tracks events to be HPOS compatible.
|
|
@ -19,23 +19,35 @@ class WC_Orders_Tracking {
|
|||
*/
|
||||
public function init() {
|
||||
add_action( 'woocommerce_order_status_changed', array( $this, 'track_order_status_change' ), 10, 3 );
|
||||
add_action( 'load-edit.php', array( $this, 'track_orders_view' ), 10 );
|
||||
add_action( 'pre_post_update', array( $this, 'track_created_date_change' ), 10 );
|
||||
// WC_Meta_Box_Order_Actions::save() hooks in at priority 50.
|
||||
add_action( 'woocommerce_process_shop_order_meta', array( $this, 'track_order_action' ), 51 );
|
||||
|
||||
add_action( 'load-edit.php', array( $this, 'track_orders_view' ), 10 );
|
||||
add_action( 'load-woocommerce_page_wc-orders', array( $this, 'track_orders_view' ), 10 ); // HPOS.
|
||||
|
||||
add_action( 'load-post-new.php', array( $this, 'track_add_order_from_edit' ), 10 );
|
||||
add_filter( 'woocommerce_shop_order_search_results', array( $this, 'track_order_search' ), 10, 3 );
|
||||
add_action( 'load-woocommerce_page_wc-orders', array( $this, 'track_add_order_from_edit' ), 10 ); // HPOS.
|
||||
|
||||
add_action( 'woocommerce_process_shop_order_meta', array( $this, 'track_created_date_change' ), 10 );
|
||||
|
||||
add_action( 'load-edit.php', array( $this, 'track_search_in_orders_list' ) );
|
||||
add_action( 'load-woocommerce_page_wc-orders', array( $this, 'track_search_in_orders_list' ) ); // HPOS.
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'possibly_add_order_tracking_scripts' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a track event when on the Order Listing page, and search results are being displayed.
|
||||
*
|
||||
* @deprecated 8.6.0
|
||||
*
|
||||
* @param array $order_ids Array of order_ids that are matches for the search.
|
||||
* @param string $term The string that was used in the search.
|
||||
* @param array $search_fields Fields that were used in the original search.
|
||||
*/
|
||||
public function track_order_search( $order_ids, $term, $search_fields ) {
|
||||
wc_deprecated_function( __METHOD__, '8.6.0', 'WC_Orders_Tracking::track_search_in_orders_list' );
|
||||
|
||||
// Since `woocommerce_shop_order_search_results` can run in the front-end context, exit if get_current_screen isn't defined.
|
||||
if ( ! function_exists( 'get_current_screen' ) ) {
|
||||
return $order_ids;
|
||||
|
@ -52,20 +64,34 @@ class WC_Orders_Tracking {
|
|||
return $order_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a track event when on the Order Listing page, and search results are being displayed.
|
||||
*
|
||||
* @since 8.6.0
|
||||
*/
|
||||
public function track_search_in_orders_list() {
|
||||
if ( ! OrderUtil::is_order_list_table_screen() || empty( $_REQUEST['s'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
return;
|
||||
}
|
||||
|
||||
WC_Tracks::record_event( 'orders_view_search' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Tracks event when the Orders page is viewed.
|
||||
*/
|
||||
public function track_orders_view() {
|
||||
if ( isset( $_GET['post_type'] ) && 'shop_order' === wp_unslash( $_GET['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
|
||||
$properties = array(
|
||||
'status' => isset( $_GET['post_status'] ) ? sanitize_text_field( $_GET['post_status'] ) : 'all',
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
WC_Tracks::record_event( 'orders_view', $properties );
|
||||
if ( ! OrderUtil::is_order_list_table_screen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
|
||||
$properties = array(
|
||||
'status' => sanitize_text_field( $_GET['post_status'] ?? ( $_GET['status'] ?? 'all' ) ),
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
WC_Tracks::record_event( 'orders_view', $properties );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,15 +126,15 @@ class WC_Orders_Tracking {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( 'auto-draft' === get_post_status( $id ) ) {
|
||||
$order = wc_get_order( $id );
|
||||
if ( ! $order || 'auto-draft' === $order->get_status() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = wc_get_order( $id );
|
||||
$date_created = $order->get_date_created() ? $order->get_date_created()->date( 'Y-m-d H:i:s' ) : '';
|
||||
// phpcs:disable WordPress.Security.NonceVerification
|
||||
$new_date = sprintf(
|
||||
'%s %2d:%2d:%2d',
|
||||
'%s %2d:%02d:%02d',
|
||||
isset( $_POST['order_date'] ) ? wc_clean( wp_unslash( $_POST['order_date'] ) ) : '',
|
||||
isset( $_POST['order_date_hour'] ) ? wc_clean( wp_unslash( $_POST['order_date_hour'] ) ) : '',
|
||||
isset( $_POST['order_date_minute'] ) ? wc_clean( wp_unslash( $_POST['order_date_minute'] ) ) : '',
|
||||
|
@ -151,46 +177,50 @@ class WC_Orders_Tracking {
|
|||
* Track "add order" button on the Edit Order screen.
|
||||
*/
|
||||
public function track_add_order_from_edit() {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
if ( isset( $_GET['post_type'] ) && 'shop_order' === wp_unslash( $_GET['post_type'] ) ) {
|
||||
$referer = wp_get_referer();
|
||||
if ( ! OrderUtil::is_new_order_screen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $referer ) {
|
||||
$referring_page = wp_parse_url( $referer );
|
||||
$referring_args = array();
|
||||
$post_edit_page = wp_parse_url( admin_url( 'post.php' ) );
|
||||
$referer = wp_get_referer();
|
||||
if ( ! $referer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! empty( $referring_page['query'] ) ) {
|
||||
parse_str( $referring_page['query'], $referring_args );
|
||||
}
|
||||
$referring_page = wp_parse_url( $referer );
|
||||
|
||||
// Determine if we arrived from an Order Edit screen.
|
||||
if (
|
||||
$post_edit_page['path'] === $referring_page['path'] &&
|
||||
isset( $referring_args['action'] ) &&
|
||||
'edit' === $referring_args['action'] &&
|
||||
isset( $referring_args['post'] ) &&
|
||||
'shop_order' === OrderUtil::get_order_type( $referring_args['post'] )
|
||||
) {
|
||||
WC_Tracks::record_event( 'order_edit_add_order' );
|
||||
}
|
||||
}
|
||||
if ( empty( $referring_page['query'] ) ) {
|
||||
// Edit Order screen has query args.
|
||||
return;
|
||||
}
|
||||
parse_str( $referring_page['query'], $referring_args );
|
||||
|
||||
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
|
||||
$post_edit_page = admin_url( 'admin.php?page=wc-orders' );
|
||||
$order_id = $referring_args['id'] ?? 0;
|
||||
} else {
|
||||
$post_edit_page = admin_url( 'post.php' );
|
||||
$order_id = $referring_args['post'] ?? 0;
|
||||
}
|
||||
$post_edit_page = wp_parse_url( $post_edit_page );
|
||||
|
||||
if (
|
||||
( $post_edit_page['path'] === $referring_page['path'] ) &&
|
||||
( ! isset( $post_edit_page['query'] ) || false !== strpos( $referring_page['query'], $post_edit_page['query'] ) ) &&
|
||||
( isset( $referring_args['action'] ) && 'edit' === $referring_args['action'] ) &&
|
||||
'shop_order' === OrderUtil::get_order_type( $order_id )
|
||||
) {
|
||||
WC_Tracks::record_event( 'order_edit_add_order' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the tracking scripts for product setting pages.
|
||||
*
|
||||
* @param string $hook Page hook.
|
||||
*/
|
||||
public function possibly_add_order_tracking_scripts( $hook ) {
|
||||
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification
|
||||
if (
|
||||
( isset( $_GET['post_type'] ) && 'shop_order' === wp_unslash( $_GET['post_type'] ) ) ||
|
||||
( 'post.php' === $hook && isset( $_GET['post'] ) && 'shop_order' === get_post_type( intval( $_GET['post'] ) ) )
|
||||
) {
|
||||
WCAdminAssets::register_script( 'wp-admin-scripts', 'order-tracking', false );
|
||||
public function possibly_add_order_tracking_scripts() {
|
||||
if ( ! OrderUtil::is_new_order_screen() && ! OrderUtil::is_order_edit_screen() && ! OrderUtil::is_order_list_table_screen() ) {
|
||||
return;
|
||||
}
|
||||
// phpcs:enable
|
||||
|
||||
WCAdminAssets::register_script( 'wp-admin-scripts', 'order-tracking', false );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,16 @@
|
|||
<?php
|
||||
|
||||
// phpcs:disable Generic.Files.OneObjectStructurePerFile.MultipleFound
|
||||
if ( ! class_exists( 'CurrentScreenMock' ) ) {
|
||||
/**
|
||||
* Class CurrentScreenMock
|
||||
*/
|
||||
class CurrentScreenMock {
|
||||
/**
|
||||
* CustomerEffortScoreTracks only works in wp-admin, so let's fake it.
|
||||
*/
|
||||
public function in_admin() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
use Automattic\WooCommerce\Internal\Admin\Orders\PageController;
|
||||
use Automattic\WooCommerce\RestApi\UnitTests\HPOSToggleTrait;
|
||||
use Automattic\WooCommerce\Utilities\OrderUtil;
|
||||
|
||||
/**
|
||||
* Class WC_Orders_Tracking_Test.
|
||||
*/
|
||||
class WC_Orders_Tracking_Test extends \WC_Unit_Test_Case {
|
||||
|
||||
use HPOSToggleTrait;
|
||||
|
||||
/**
|
||||
* @var object Backup object of $GLOBALS['current_screen'];
|
||||
*/
|
||||
|
@ -33,14 +24,21 @@ class WC_Orders_Tracking_Test extends \WC_Unit_Test_Case {
|
|||
public function setUp(): void {
|
||||
include_once WC_ABSPATH . 'includes/tracks/events/class-wc-orders-tracking.php';
|
||||
update_option( 'woocommerce_allow_tracking', 'yes' );
|
||||
if ( isset( $GLOBALS['current_screen'] ) ) {
|
||||
$this->current_screen_backup = $GLOBALS['current_screen'];
|
||||
|
||||
// Mock screen.
|
||||
$this->current_screen_backup = $GLOBALS['current_screen'] ?? null;
|
||||
$GLOBALS['current_screen'] = $this->get_screen_mock(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
if ( ! did_action( 'current_screen' ) ) {
|
||||
do_action( 'current_screen', $GLOBALS['current_screen'] ); // phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
|
||||
}
|
||||
$GLOBALS['current_screen'] = new CurrentScreenMock(); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
$orders_tracking = new WC_Orders_Tracking();
|
||||
|
||||
$orders_tracking = new WC_Orders_Tracking();
|
||||
$orders_tracking->init();
|
||||
parent::setUp();
|
||||
|
||||
$this->setup_cot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown test
|
||||
*
|
||||
|
@ -52,39 +50,109 @@ class WC_Orders_Tracking_Test extends \WC_Unit_Test_Case {
|
|||
$GLOBALS['current_screen'] = $this->current_screen_backup; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
}
|
||||
parent::tearDown();
|
||||
$this->clean_up_cot_setup();
|
||||
remove_all_filters( 'wc_allow_changing_orders_storage_while_sync_is_pending' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wcadmin_orders_edit_status_change Tracks event
|
||||
* Test wcadmin_orders_edit_status_change Tracks event.
|
||||
*
|
||||
* @testWith [true]
|
||||
* [false]
|
||||
*
|
||||
* @param bool $hpos_enabled Whether to test with HPOS enabled or not.
|
||||
*/
|
||||
public function test_orders_view_search() {
|
||||
public function test_orders_status_change( $hpos_enabled ) {
|
||||
$this->toggle_cot_authoritative( $hpos_enabled );
|
||||
$order = wc_create_order();
|
||||
$order->save();
|
||||
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
do_action( 'woocommerce_order_status_changed', $order->get_id(), 'pending', 'finished' );
|
||||
$this->assertRecordedTracksEvent( 'wcadmin_orders_edit_status_change' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wcadmin_orders_view Tracks event
|
||||
* Test wcadmin_orders_view Tracks event.
|
||||
*
|
||||
* @testWith [true]
|
||||
* [false]
|
||||
*
|
||||
* @param bool $hpos_enabled Whether to test with HPOS enabled or not.
|
||||
*/
|
||||
public function test_orders_view() {
|
||||
$_GET['post_type'] = 'shop_order';
|
||||
public function test_orders_view( $hpos_enabled ) {
|
||||
$this->toggle_cot_authoritative( $hpos_enabled );
|
||||
$this->setup_screen( 'list' );
|
||||
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
// phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
do_action( 'load-edit.php' );
|
||||
do_action( $hpos_enabled ? 'load-woocommerce_page_wc-orders' : 'load-edit.php' );
|
||||
|
||||
$this->assertRecordedTracksEvent( 'wcadmin_orders_view' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wcadmin_orders_view_search Tracks event
|
||||
* Test wcadmin_orders_view_search Tracks event.
|
||||
*
|
||||
* @testWith [true]
|
||||
* [false]
|
||||
*
|
||||
* @param bool $hpos_enabled Whether to test with HPOS enabled or not.
|
||||
*/
|
||||
public function test_orders_search() {
|
||||
$GLOBALS['current_screen']->id = 'edit-shop_order';
|
||||
/* phpcs:disable WooCommerce.Commenting.CommentHooks.MissingHookComment */
|
||||
apply_filters( 'woocommerce_shop_order_search_results', array( 'order_id1' ), 'term', array() );
|
||||
public function test_orders_search( $hpos_enabled ) {
|
||||
$this->toggle_cot_authoritative( $hpos_enabled );
|
||||
|
||||
$_REQUEST['s'] = 'term';
|
||||
$this->setup_screen( 'list' );
|
||||
|
||||
do_action( 'load-edit.php' );
|
||||
|
||||
$this->assertRecordedTracksEvent( 'wcadmin_orders_view_search' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the screen as if it were the "list" orders screen.
|
||||
*/
|
||||
private function setup_screen() {
|
||||
$GLOBALS['current_screen']->post_type = 'shop_order';
|
||||
$GLOBALS['current_screen']->base = 'edit';
|
||||
$_GET['action'] = '';
|
||||
|
||||
if ( OrderUtil::custom_orders_table_usage_is_enabled() ) {
|
||||
$GLOBALS['pagenow'] = 'admin.php'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
$GLOBALS['plugin_page'] = 'wc-orders'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
|
||||
add_filter( 'map_meta_cap', array( $this, 'allow_edit_shop_orders' ), 10, 3 );
|
||||
wc_get_container()->get( PageController::class )->setup();
|
||||
remove_filter( 'map_meta_cap', array( $this, 'allow_edit_shop_orders' ), 10 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object mocking what we need from `\WP_Screen`.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
private function get_screen_mock() {
|
||||
$screen_mock = $this->getMockBuilder( stdClass::class )->setMethods( array( 'in_admin', 'add_option' ) )->getMock();
|
||||
$screen_mock->method( 'in_admin' )->willReturn( true );
|
||||
foreach ( array( 'id', 'base', 'action', 'post_type' ) as $key ) {
|
||||
$screen_mock->{$key} = '';
|
||||
}
|
||||
|
||||
return $screen_mock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to temporarily grant the current user the 'edit_shop_orders' permission.
|
||||
*
|
||||
* @param string[] $caps Primitive capabilities required for the user.
|
||||
* @param string $cap Capability being checked.
|
||||
* @param int $user_id The user ID.
|
||||
* @return array
|
||||
*/
|
||||
public function allow_edit_shop_orders( $caps, $cap, $user_id ) {
|
||||
return ( 0 === $user_id && 'edit_shop_orders' === $cap ) ? array() : $caps;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue