From 1036cfc64bad825227d690d4fe6c8f96d1f1287d Mon Sep 17 00:00:00 2001 From: tbradsha <32492176+tbradsha@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:00:52 -0700 Subject: [PATCH] CRM: 3433 - Additional HPOS tweaks (#36003) * Don't set up Woo Admin hooks if Woo isn't active * Gather screens where we want to add metaboxes * Don't set up local Woo hooks if Woo isn't active * Add backslash to class lookup * Coding standards * Remove legacy condition * Coding standards * Simplify Woo subs code using wc_get_orders() * Further simplify code * Use proper date functions * Add changelog * Fix segment listview escape issue * Update changelog * Search all subscription statuses * Ensure each email alias adds to the array --- .../crm/changelog/fix-crm-3433-hpos-tweaks | 6 + .../crm/js/ZeroBSCRM.admin.listview.js | 6 +- .../class-woo-sync-background-sync.php | 23 +- .../class-woo-sync-woo-admin-integration.php | 38 +++- .../includes/jpcrm-woo-sync-contact-tabs.php | 210 +++++------------- .../modules/woo-sync/jpcrm-woo-sync-init.php | 2 +- 6 files changed, 110 insertions(+), 175 deletions(-) create mode 100644 projects/plugins/crm/changelog/fix-crm-3433-hpos-tweaks diff --git a/projects/plugins/crm/changelog/fix-crm-3433-hpos-tweaks b/projects/plugins/crm/changelog/fix-crm-3433-hpos-tweaks new file mode 100644 index 0000000000000..5929f65b4a97a --- /dev/null +++ b/projects/plugins/crm/changelog/fix-crm-3433-hpos-tweaks @@ -0,0 +1,6 @@ +Significance: patch +Type: fixed + +WooSync: No longer shows today as renewal date if subscription has no renewal date set. +WooSync: Modernize code. +Segments: Fix output if segment has an error. diff --git a/projects/plugins/crm/js/ZeroBSCRM.admin.listview.js b/projects/plugins/crm/js/ZeroBSCRM.admin.listview.js index aed2a891ce83d..32e57c6823297 100644 --- a/projects/plugins/crm/js/ZeroBSCRM.admin.listview.js +++ b/projects/plugins/crm/js/ZeroBSCRM.admin.listview.js @@ -2799,15 +2799,15 @@ function zeroBSCRMJS_listView_segment_added( dataLine ) { * @param dataLine */ function zeroBSCRMJS_listView_segment_name( dataLine ) { - var name_str = dataLine.name; + var name_str = jpcrm.esc_html(dataLine.name); // if any errors, attach an exclaimation mark if ( typeof dataLine.error !== 'undefined' ) { - name_str += ' '; + name_str += ' '; } var td = - '' + jpcrm.esc_html(name_str) + ''; + '' + name_str + ''; return td; } diff --git a/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-background-sync.php b/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-background-sync.php index 0a914c97ce004..89987d5074693 100644 --- a/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-background-sync.php +++ b/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-background-sync.php @@ -131,17 +131,25 @@ private function debug( $str ){ /** * Initialise Hooks */ - private function init_hooks( ) { + private function init_hooks() { // cron add_action( 'jpcrm_woosync_sync', array( $this, 'cron_job' ) ); - // Syncing based on WooCommerce hooks: + // add our cron task to the core crm cron monitor list + add_filter( 'jpcrm_cron_to_monitor', array( $this, 'add_cron_monitor' ) ); + + global $zbs; + + // Abort if Woo isn't active. + if ( ! $zbs->woocommerce_is_active() ) { + return; + } // Order changes: - add_action( 'woocommerce_order_status_changed', array( $this, 'add_update_from_woo_order' ), 1, 1 ); + add_action( 'woocommerce_order_status_changed', array( $this, 'add_update_from_woo_order' ), 1, 1 ); add_action( 'woocommerce_process_shop_order_meta', array( $this, 'add_update_from_woo_order' ), 100, 1 ); - add_action( 'woocommerce_deposits_create_order', array( $this, 'add_update_from_woo_order' ), 100, 1 ); + add_action( 'woocommerce_deposits_create_order', array( $this, 'add_update_from_woo_order' ), 100, 1 ); if ( jpcrm_woosync_is_hpos_enabled() ) { // These hooks are available as of Woo 7.1.0 and are required for HPOS. add_action( 'woocommerce_before_trash_order', array( $this, 'woocommerce_order_trashed' ), 10, 1 ); @@ -152,14 +160,9 @@ private function init_hooks( ) { } // Catch WooCommerce customer address changes and update contact: - add_action( 'woocommerce_customer_save_address', array( $this, 'update_contact_address_from_wp_user' ), 10, 3 ); - - // add our cron task to the core crm cron monitor list - add_filter( 'jpcrm_cron_to_monitor', array( $this, 'add_cron_monitor' ) ); - + add_action( 'woocommerce_customer_save_address', array( $this, 'update_contact_address_from_wp_user' ), 10, 3 ); } - /** * Setup cron schedule */ diff --git a/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-woo-admin-integration.php b/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-woo-admin-integration.php index fd8aac993ecbc..ea5e5a3989cb6 100644 --- a/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-woo-admin-integration.php +++ b/projects/plugins/crm/modules/woo-sync/includes/class-woo-sync-woo-admin-integration.php @@ -51,6 +51,12 @@ public static function instance() { * Initialise Hooks */ private function init_hooks() { + global $zbs; + + // Abort if Woo isn't active. + if ( ! $zbs->woocommerce_is_active() ) { + return; + } // Hook into Woo orders listview. if ( jpcrm_woosync_is_hpos_enabled() ) { @@ -137,20 +143,28 @@ public function render_orders_column_content( $column, $order_or_post_id ) { * Add CRM meta boxes to Woo pages */ public function add_meta_boxes() { - if ( jpcrm_woosync_is_hpos_enabled() ) { - $screen = wc_get_page_screen_id( 'shop-order' ); - } else { - $screen = array( 'shop_order', 'shop_subscription' ); + + // Gather Woo screens where we'll want to add metaboxes. + $screens_to_use = array(); + $woo_screens = array( 'shop_order', 'shop_subscription' ); + foreach ( $woo_screens as $woo_screen ) { + $potential_screen = wc_get_page_screen_id( $woo_screen ); + if ( ! empty( $potential_screen ) ) { + $screens_to_use[] = $potential_screen; + } } - add_meta_box( - 'zbs_crm_contact', - __( 'CRM Contact', 'zero-bs-crm' ), - array( $this, 'render_woo_order_page_contact_box' ), - $screen, - 'side', - 'core' - ); + // Currently if Woo is active we should at least have the orders page, but that could change. + if ( ! empty( $screens_to_use ) ) { + add_meta_box( + 'zbs_crm_contact', + __( 'CRM Contact', 'zero-bs-crm' ), + array( $this, 'render_woo_order_page_contact_box' ), + $screens_to_use, + 'side', + 'core' + ); + } } /** diff --git a/projects/plugins/crm/modules/woo-sync/includes/jpcrm-woo-sync-contact-tabs.php b/projects/plugins/crm/modules/woo-sync/includes/jpcrm-woo-sync-contact-tabs.php index e7cbac72cc6f6..0cf534e445078 100644 --- a/projects/plugins/crm/modules/woo-sync/includes/jpcrm-woo-sync-contact-tabs.php +++ b/projects/plugins/crm/modules/woo-sync/includes/jpcrm-woo-sync-contact-tabs.php @@ -181,13 +181,12 @@ private function generate_bookings_tab_html( $object_id = -1 ){ */ private function generate_subscriptions_tab_html( $object_id = -1 ) { - $contact_has_subscriptions = false; + $subscriptions = array(); if ( zeroBSCRM_getClientPortalUserID( $object_id ) > 0 ) { // Retrieve any subs against the main email or aliases. - $subscriptions = $this->get_contact_subscriptions( $object_id ); - $contact_has_subscriptions = ( 'success' === $subscriptions['message'] && count( $subscriptions['data'] ) > 0 ); + $subscriptions = $this->get_contact_subscriptions( $object_id ); } - if ( ! $contact_has_subscriptions ) { + if ( count( $subscriptions ) === 0 ) { return '
' . __( 'This contact does not have any WooCommerce Subscriptions yet.', 'zero-bs-crm' ) . '
'; } @@ -203,20 +202,19 @@ private function generate_subscriptions_tab_html( $object_id = -1 ) { $html .= ''; $html .= ''; - foreach ( $subscriptions['data'] as $k => $v ) { - - $order = wc_get_order( $k ); + foreach ( $subscriptions as $order_id ) { + $order = wc_get_order( $order_id ); $status = $order->get_status(); $date_created = $order->get_date_created(); $date_renew = $order->get_date( 'next_payment_date' ); $price = $order->get_formatted_order_total(); $name = ''; - $sub_link = admin_url( "post.php?post={$k}&action=edit" ); - $created = zeroBSCRM_date_i18n( zeroBSCRM_getDateFormat(), strtotime( $date_created ), true, false ); - $next = zeroBSCRM_date_i18n( zeroBSCRM_getDateFormat(), strtotime( $date_renew ), true, false ); + $sub_link = admin_url( "post.php?post={$order_id}&action=edit" ); + $created = jpcrm_uts_to_date_str( strtotime( $date_created ) ); + $next = jpcrm_uts_to_date_str( strtotime( $date_renew ) ); $html .= ''; - $html .= '' . $name . __( ' Subscription #', 'zero-bs-crm' ) . $k . ''; + $html .= '' . $name . __( ' Subscription #', 'zero-bs-crm' ) . $order_id . ''; $html .= '' . $status . ''; $html .= '' . $price . ''; $html .= '' . $created . ''; @@ -264,12 +262,12 @@ private function generate_memberships_tab_html( $object_id = -1 ) { foreach ( $memberships as $membership ) { // populate fields - $member_id = $membership->id; - $status = $this->display_membership_status( $membership->get_status() ); - $name = $membership->plan->name; - $date_expires = $membership->get_end_date( 'Y-m-d H:i:s' ); - $date_created = $membership->get_start_date(); - $created = zeroBSCRM_date_i18n( zeroBSCRM_getDateFormat(), strtotime( $date_created ), true, false ); + $member_id = $membership->id; + $status = $this->display_membership_status( $membership->get_status() ); + $name = $membership->plan->name; + $date_expires = $membership->get_end_date( 'Y-m-d H:i:s' ); + $date_created = $membership->get_start_date(); + $created = jpcrm_uts_to_date_str( strtotime( $date_created ) ); if ( empty( $date_expires ) ) { @@ -277,7 +275,7 @@ private function generate_memberships_tab_html( $object_id = -1 ) { } else { - $expires = zeroBSCRM_date_i18n( zeroBSCRM_getDateFormat(), strtotime( $date_expires ), true, false ); + $expires = jpcrm_uts_to_date_str( strtotime( $date_expires ) ); } @@ -354,142 +352,56 @@ private function get_contact_memberships( $object_id = -1 ){ } } + /** + * Retrieves any Woo Subscriptions against a contact + * + * @param int $object_id Contact ID. + */ + private function get_contact_subscriptions( $object_id = -1 ) { + $all_sub_statuses = array_keys( wcs_get_subscription_statuses() ); - /** - * Retrieves any Woo Subscriptions against a contact - * - * @var int contactID - */ - private function get_contact_subscriptions( $object_id = -1 ){ - - $return = array(); - - if ( $object_id > 0 ){ - - $subscription_user_ids = array(); - $subscription_email_ids = array(); - - // 1 - get the subscription IDs for the attached wp user (array_1) - $user_id = zeroBS_getCustomerWPID($object_id); - if ($user_id > 0){ - - $subscription_user_ids = \WCS_Customer_Store::instance()->get_users_subscription_ids( $user_id ); - - } - - // 2 - find subs for all emails (inc aliases) #3.0.12+ of core - if ( function_exists( 'zeroBS_customerEmails' ) ){ - - // multi, inc aliases - $emails = zeroBS_customerEmails( $object_id ); - if ( is_array( $emails ) ){ - - foreach ( $emails as $email ){ - - $subscription_ids = $this->get_subscriptions_by_email( $email ); - - // add any to the stack - if ( is_array( $subscription_ids ) ){ - - foreach ( $subscription_ids as $id ){ - - $subscription_email_ids[] = $id; - - } - - } - - } - - } - - - } else { - - // subscription IDs for the main EMAIL (array_2) - $contact_email = zeroBS_customerEmail($object_id); - $subscription_email_ids = $this->get_subscriptions_by_email($contact_email); - - } - - // 3 - remove any duplicate IDs between array_1 and array_2 - $subscription_ids = array_unique( array_merge( $subscription_user_ids, $subscription_email_ids ), SORT_REGULAR ); - - // 4 - get the subscriptions from the combined IDs - $return = array( - 'data' => $this->get_subscriptions_by_id_array( $subscription_ids ) - ); - - // 5 - return the new array of subscriptions - if ( count( $return['data'] ) > 0){ - - $return['message'] = 'success'; - - } else { - - $return['message'] = 'notfound'; - - } - - } - - return $return; - - } - - - /** - * Turns out that wcs_get_users_subscriptions runs from userIDs and we need a variant from email - */ - private function get_subscriptions_by_id_array( $subscription_ids ){ - - $subscriptions = array(); - foreach ( $subscription_ids as $subscription_id ) { - $subscription = wcs_get_subscription( $subscription_id ); - - if ( $subscription ) { - $subscriptions[ $subscription_id ] = $subscription; - } - } - - return $subscriptions; + $subscription_ids = array(); - } + if ( $object_id > 0 ) { + // 1 - get the subscription IDs for the attached wp user + $user_id = zeroBS_getCustomerWPID( $object_id ); + if ( $user_id > 0 ) { + $args = array( + 'customer_id' => $user_id, + 'status' => $all_sub_statuses, + 'type' => 'shop_subscription', + 'return' => 'ids', + ); - /** - * Get subs by email - */ - private function get_subscriptions_by_email($email = ''){ - - if ( empty( $email ) ) { - - return array(); + $subscription_ids = wc_get_orders( $args ); + } - } + // 2 - find subs for all emails (inc aliases) + $emails = zeroBS_customerEmails( $object_id ); + if ( is_array( $emails ) ) { + + foreach ( $emails as $email ) { + if ( empty( $email ) ) { + continue; + } + + $args = array( + 'billing_email' => $email, + 'status' => $all_sub_statuses, + 'type' => 'shop_subscription', + 'return' => 'ids', + ); + + $subscription_ids_by_email = wc_get_orders( $args ); + $subscription_ids = array_merge( $subscription_ids, $subscription_ids_by_email ); + } + } - $query = new \WP_Query(); - - return $query->query( array( - - 'post_type' => 'shop_subscription', - 'posts_per_page' => -1, - 'post_status' => 'any', - 'orderby' => array( - 'date' => 'DESC', - 'ID' => 'DESC', - ), - 'fields' => 'ids', - 'no_found_rows' => true, - 'ignore_sticky_posts' => true, - 'meta_query' => array( - array( - 'key' => '_billing_email', - 'value' => $email, - ), - ), - - )); + // 3 - remove any duplicate IDs between array_1 and array_2 + $subscription_ids = array_unique( $subscription_ids, SORT_REGULAR ); + } - } + return $subscription_ids; + } } diff --git a/projects/plugins/crm/modules/woo-sync/jpcrm-woo-sync-init.php b/projects/plugins/crm/modules/woo-sync/jpcrm-woo-sync-init.php index d2f8ccee3cf87..cdb9f9da8d622 100644 --- a/projects/plugins/crm/modules/woo-sync/jpcrm-woo-sync-init.php +++ b/projects/plugins/crm/modules/woo-sync/jpcrm-woo-sync-init.php @@ -237,7 +237,7 @@ function jpcrm_add_woo_jobs_to_system_assistant( $job_list ) { * @return bool Defaults to false. */ function jpcrm_woosync_is_hpos_enabled() { - if ( class_exists( 'Automattic\WooCommerce\Utilities\OrderUtil' ) ) { + if ( class_exists( '\Automattic\WooCommerce\Utilities\OrderUtil' ) ) { return \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled(); } return false;