Advertisement
daymobrew

CMB2 and WooCommerce HPOS

Aug 22nd, 2023
869
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 10.20 KB | None | 0 0
  1. <?php
  2. /*
  3. Plugin Name: Tracking Info to WooCommerce order
  4. Plugin URI: https://www.damiencarbery.com/2020/01/add-tracking-info-to-woocommerce-order/
  5. Description: Use CMB2 to add a custom metabox to add tracking information to WooCommerce orders. The information is then added to the "Completed Order" email.
  6. Author: Damien Carbery
  7. Author URI: https://www.damiencarbery.com
  8. Version: 0.9
  9. */
  10.  
  11.  
  12. // Verify that CMB2 plugin is active.
  13. add_action( 'admin_notices', 'titwo_verify_cmb2_active' );
  14. function titwo_verify_cmb2_active() {
  15.     if ( ! defined( 'CMB2_LOADED' ) ) {
  16.         $current_screen = get_current_screen();
  17.         if ( $current_screen->id == 'shop_order' ) {
  18.             $plugin_data = get_plugin_data( __FILE__ );
  19.             $plugin_name = $plugin_data['Name'];
  20. ?>
  21. <div class="notice notice-warning is-dismissible"><p>The <strong><?php echo $plugin_name; ?></strong> plugin requires <a href="https://wordpress.org/plugins/cmb2/">CMB2 plugin</a> to be active to enable adding tracking information to orders.</p></div>
  22. <?php
  23.         }
  24.     }
  25. }
  26.  
  27.  
  28. // Declare that this plugin supports WooCommerce HPOS.
  29. add_action( 'before_woocommerce_init', function() {
  30.     if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
  31.         \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
  32.     }
  33. } );
  34.  
  35.  
  36. // Add the metabox to allow for manual entering (or editing) of tracking information.
  37. add_action( 'cmb2_admin_init', 'dcwd_order_metabox' );
  38. function dcwd_order_metabox() {
  39.     $cmb = new_cmb2_box( array(
  40.         'id'            => 'order_tracking_info',
  41.         'title'         => 'Tracking Information',
  42.         'object_types'  => array( 'shop_order', 'woocommerce_page_wc-orders' ), // Post type
  43.         'context'       => 'side',
  44.         'priority'      => 'high',
  45.         'show_names'    => true, // Show field names on the left
  46.     ) );
  47.     $cmb->add_field( array(
  48.         'name'  => 'Tracking number',
  49.         'id'    => 'tracking_number',
  50.         'type'  => 'text',
  51.     ) );
  52.     $cmb->add_field( array(
  53.         'name'       => 'Tracking URL',
  54.         'id'         => 'tracking_url',
  55.         'type'       => 'text_url',
  56.         'protocols'  => array( 'http', 'https' ),
  57.         'desc' => 'Be sure to add tracking data and click \'Update\' before setting the order status to \'Completed\', and clicking \'Update\' again. If not done in this order the email sent to the customer will not contain the tracking data.',
  58.     ) );
  59. }
  60.  
  61.  
  62. // 2022-10-16: Comment this out as it is breaking in Woo >6.9.3. Instead, I simply enable the deferring of emails.
  63. /*
  64. // Move the saving of order meta (which triggers emails) to be *after* CMB2 data saved.
  65. // NOTE: This could have unintended consequences.
  66. //add_action( 'wp_loaded', 'dcwd_move_wc_order_meta_save');
  67. function dcwd_move_wc_order_meta_save() {
  68.     remove_action( 'woocommerce_process_shop_order_meta', 'WC_Meta_Box_Order_Data::save', 40 );
  69.     // Call WC_Meta_Box_Order_Data::save later, after CMB2 data is saved.
  70.     add_action( 'save_post', 'dcwd_save_post_order_data', 50, 3 );
  71. }
  72.  
  73.  
  74. // Call WC_Meta_Box_Order_Data::save later, after CMB2 data is saved.
  75. function dcwd_save_post_order_data( $post_id, $post, $update ) {
  76.     // Call the WooCommerce Meta Box Order Data save function for WC_Order posts only.
  77. // TODO: Look at wc_get_order_types() as do_action('woocommerce_process_shop_order_meta') runs when in_array( $post->post_type, wc_get_order_types( 'order-meta-boxes' ), true )
  78.     if ( 'shop_order' == $post->post_type) {
  79.         WC_Meta_Box_Order_Data::save( $post_id );
  80.     }
  81. }*/
  82.  
  83.  
  84. // Defer emails for 10 seconds to allow time for CMB2 to save the tracking data.
  85. add_filter( 'woocommerce_defer_transactional_emails', '__return_true' );
  86.  
  87.  
  88. // If using 'Email Template Customizer for WooCommerce' plugin then use a different hook
  89. // to add the tracking information to the email.
  90. add_action( 'plugins_loaded', 'dcwd_check_for_email_template_customizer' );
  91. function dcwd_check_for_email_template_customizer() {
  92.     if ( class_exists( 'Woo_Email_Template_Customizer' ) ) {
  93.         // Email Template Customizer for WooCommerce plugin does not use the 'woocommerce_email_order_details'
  94.         // hook so use 'woocommerce_email_after_order_table' instead (it is one of the 3 available ones in the
  95.         // plugin's 'WC Hook' field.
  96.         add_action( 'woocommerce_email_after_order_table', 'dcwd_add_tracking_info_to_order_completed_email', 5, 4 );
  97.     }
  98. }
  99.  
  100.  
  101. // Examine the tracking url and return a provider name.
  102. function dcwd_get_tracking_provider_from_url( $url ) {
  103.     if ( strpos( $url, 'usps.com' ) !== false ) {
  104.         return 'USPS';
  105.     }
  106.     if ( strpos( $url, 'fedex.com' ) !== false ) {
  107.         return 'FedEx';
  108.     }
  109.     if ( strpos( $url, 'ups.com' ) !== false ) {
  110.         return 'UPS';
  111.     }
  112.     // Add more as necessary.
  113.     if ( strpos( $url, 'www.singpost.com' ) !== false ) {
  114.         return 'Singapore Post';
  115.     }
  116.    
  117.     // Unknown provider.
  118.     return null;
  119. }
  120.  
  121.  
  122. // If available, include the tracking information in the Completed Order email.
  123. add_action( 'woocommerce_email_order_details', 'dcwd_add_tracking_info_to_order_completed_email', 5, 4 );
  124. function dcwd_add_tracking_info_to_order_completed_email( $order, $sent_to_admin, $plain_text, $email ) {
  125. /*  // Only customers need to know about the tracking information.
  126.     if ( ! $sent_to_admin ) {
  127.         return;
  128.     }
  129. */
  130.     if ( 'customer_completed_order' == $email->id ) {
  131.         $order_id = $order->get_id();
  132.         $tracking_number = wc_get_order_item_meta( $order_id, 'tracking_number');
  133.         $tracking_url = wc_get_order_item_meta( $order_id, 'tracking_url' );
  134.        
  135.         // Quit if either tracking field is empty.
  136.         if ( empty( $tracking_number ) || empty( $tracking_url ) ) {
  137.             // Debugging code.
  138.             //error_log( sprintf( 'Order %d does not have both tracking number (%s) and url (%s)', $order_id, $tracking_number, $tracking_url ) );
  139.             //echo '<p>Sorry, tracking information is not available at this time.</p>';
  140.             return;
  141.         }
  142.        
  143.         $tracking_provider = dcwd_get_tracking_provider_from_url( $tracking_url );
  144.  
  145.         if ( $plain_text ) {
  146.             if ( ! empty( $tracking_provider ) ) {
  147.                 printf( "\nYour order has been shipped with %s. The tracking number is %s and you can track it at %s.\n", $tracking_provider, esc_html( $tracking_number ), esc_url( $tracking_url, array( 'http', 'https' ) ) );
  148.             }
  149.             else {
  150.                 printf( "\nYour order has been shipped. The tracking number is %s and you can track it at %s.\n", esc_html( $tracking_number ), esc_url( $tracking_url, array( 'http', 'https' ) ) );
  151.             }
  152.         }
  153.         else {
  154.             if ( ! empty( $tracking_provider ) ) {
  155.                 printf( '<p>Your order has been shipped with <strong>%s</strong>. The tracking number is <strong><a href="%s">%s</a></strong>.</p>', $tracking_provider, esc_url( $tracking_url, array( 'http', 'https' ) ), esc_html( $tracking_number ) );
  156.             }
  157.             else {
  158.                 printf( '<p>Your order has been shipped. The tracking number is <strong><a href="%s">%s</a></strong>.</p>', esc_url( $tracking_url, array( 'http', 'https' ) ), esc_html( $tracking_number ) );
  159.             }
  160.         }
  161.     }
  162. }
  163.  
  164.  
  165. // Display tracking information in My Account area.
  166. add_action( 'woocommerce_view_order', 'dcwd_add_tracking_info_to_view_order_page', 5 );
  167. function dcwd_add_tracking_info_to_view_order_page( $order_id ) {
  168.     $tracking_number = wc_get_order_item_meta( $order_id, 'tracking_number' );
  169.     $tracking_url = wc_get_order_item_meta( $order_id, 'tracking_url' );
  170.        
  171.     // Quit if either tracking field is empty.
  172.     if ( empty( $tracking_number ) || empty( $tracking_url ) ) {
  173.         // Debugging code.
  174.         //error_log( sprintf( 'Order %d does not have both tracking number (%s) and url (%s)', $order_id, $tracking_number, $tracking_url ) );
  175.         echo '<p>Sorry, tracking information is not available at this time.</p>';
  176.         return;
  177.     }
  178.        
  179.     $tracking_provider = dcwd_get_tracking_provider_from_url( $tracking_url );
  180.     if ( ! empty( $tracking_provider ) ) {
  181.         printf( '<p>Your order has been shipped with <strong>%s</strong>. The tracking number is <strong><a href="%s">%s</a></strong>.</p>', $tracking_provider, esc_url( $tracking_url, array( 'http', 'https' ) ), esc_html( $tracking_number ) );
  182.     }
  183.     else {
  184.         printf( '<p>Your order has been shipped. The tracking number is <strong><a href="%s">%s</a></strong>.</p>', esc_url( $tracking_url, array( 'http', 'https' ) ), esc_html( $tracking_number ) );
  185.     }
  186. }
  187.  
  188.  
  189. // DEBUGGING FUNCTIONS
  190. //add_filter( 'cmb2_override_meta_value', 'dcwd_cmb2_override_meta_value', 10, 4 );
  191. add_filter( 'cmb2_override_tracking_number_meta_value', 'dcwd_cmb2_override_meta_value', 10, 4 );
  192. add_filter( 'cmb2_override_tracking_url_meta_value', 'dcwd_cmb2_override_meta_value', 10, 4 );
  193. function dcwd_cmb2_override_meta_value( $type, $object_id, $a, $this_obj ) {
  194.     error_log( 'Type: '. $type );
  195.     error_log( 'Post/object ID: '. $object_id );
  196.     error_log( '$a: '. var_export( $a, true ) );
  197.     //error_log( '$this: '. var_export( $this_obj, true ) );
  198.    
  199.     if ( 'tracking_number' == $a[ 'field_id' ] ) {
  200.         return '12345';
  201.     }
  202.     if ( 'tracking_url' == $a[ 'field_id' ] ) {
  203.         return 'https://www.dhl.ie/track/12345';
  204.     }
  205.  
  206.     return 'cmb2_field_no_override_val';
  207. }
  208.  
  209.  
  210. add_filter( 'cmb2_override_meta_save', 'dcwd_cmb2_override_meta_save', 10, 4 );
  211. add_filter( 'cmb2_override_tracking_number_meta_save', 'dcwd_cmb2_override_meta_save', 10, 4 );
  212. add_filter( 'cmb2_override_tracking_url_meta_save', 'dcwd_cmb2_override_meta_save', 10, 4 );
  213. function dcwd_cmb2_override_meta_save( $override, $a, $args, $this_obj ) {
  214.     error_log( 'Type: cmb2_override_*' . $a['field_id'] . '*_meta_save' );
  215.     error_log( '$a: '. var_export( $a, true ) );
  216.     error_log( '$_POST: '. var_export( $_POST, true ) );
  217.     //error_log( '$args: '. var_export( $args, true ) );
  218.     //error_log( '$this: '. var_export( $this_obj, true ) );
  219.    
  220.     return $override;
  221. }
  222. //$override = apply_filters( 'cmb2_override_meta_save', null, $a, $this->args(), $this );
  223.  
  224.  
  225. add_filter( 'cmb2_can_save', 'dcwd_cmb2_can_save', 10, 2 );
  226. function dcwd_cmb2_can_save( $can_save, $cmb_obj ) {
  227.     $current_screen = get_current_screen();
  228.    
  229.     if ( 'woocommerce_page_wc-orders' == $current_screen->id ) {
  230.         if ( array_key_exists( 'tracking_number', $_POST ) && ( !empty( $_POST[ 'tracking_number' ] ) ) ) {
  231.             if ( array_key_exists( 'tracking_url', $_POST ) && ( !empty( $_POST[ 'tracking_url' ] ) ) )
  232.                 error_log( 'dcwd_cmb2_can_save: Return true as tracking_number and tracking_url are in $_POST.' );
  233.                 return true;
  234.         }
  235.     }
  236.  
  237.     return $can_save;
  238. }
  239.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement