Schedule showing and hiding of WooCommerce products
Sun Mar 30 2025 19:10:53 GMT+0000 (Coordinated Universal Time)
Saved by @satinbest #php
<?php /* Plugin Name: WooCommerce - Schedule showing and hiding of products Plugin URI: https://www.damiencarbery.com/2025/01/schedule-showing-and-hiding-of-woocommerce-products/ Description: Add the ability to show and hide a product on specified dates. Author: Damien Carbery Author URI: https://www.damiencarbery.com Version: 0.1.20250108 Requires Plugins: woocommerce */ class ScheduleHideProducts { private $show_hide_dates_start_key; private $show_hide_dates_end_key; // Returns an instance of this class. public static function get_instance() { if ( null == self::$instance ) { self::$instance = new self; } return self::$instance; } // Initialize the plugin variables. public function __construct() { // The custom meta key for the start and end dates. $this->show_hide_dates_start_key = '_show_hide_dates_start'; $this->show_hide_dates_end_key = '_show_hide_dates_end'; $this->init(); } // Set up WordPress specfic actions. public function init() { // Declare that this plugin supports WooCommerce HPOS. // This plugin does not interact with WooCommerce orders so it doesn't have to do anything special to support HPOS. add_action( 'before_woocommerce_init', function() { if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) { \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true ); } } ); // Add the date fields to the Product/General tab. add_action( 'woocommerce_product_options_pricing', array( $this, 'add_hide_date' ) ); // Save the date fields values if set. add_action( 'woocommerce_process_product_meta', array( $this, 'save_show_hide_dates' ), 10, 2 ); // Scheduled check for products to show or hide. add_action( 'woocommerce_scheduled_sales', array( $this, 'scheduled_show_hide_check' ) ); // For debugging. add_shortcode( 'show_hide', array( $this, 'show_hide_shortcode' ) ); } public function show_hide_shortcode() { $product_id = 32; $visibility_terms = $this->get_visibility_terms( $product_id ); echo '<pre>', var_export( $visibility_terms, true ), '</pre>'; array_push( $visibility_terms, 'exclude-from-catalog', 'exclude-from-search' ); echo '<pre>', var_export( $visibility_terms, true ), '</pre>'; } // Get the terms without the 'exclude-from-catalog' or 'exclude-from-search' terms. private function get_visibility_terms( $product_id ) { // Get the term slugs. $visibility_terms = wp_list_pluck( wp_get_object_terms( $product_id, 'product_visibility' ), 'slug' ); // Remove 'exclude-from-catalog' or 'exclude-from-search' terms, if present. $visibility_terms = array_filter( $visibility_terms, function( $x ) { return $x != 'exclude-from-catalog' && $x != 'exclude-from-search'; } ); return $visibility_terms; } // Add the date fields to the Product/General tab. public function add_hide_date() { $post_id = get_the_ID(); $product_type = WC_Product_Factory::get_product_type( $post_id ); $classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' ); $product = new $classname( $post_id ); $show_hide_dates_start_timestamp = $product->get_meta( $this->show_hide_dates_start_key, true, 'edit' ); $show_hide_dates_end_timestamp = $product->get_meta( $this->show_hide_dates_end_key, true, 'edit' ); // Convert the timestamp into Y-m-d format. $show_hide_dates_start = $show_hide_dates_start_timestamp ? date_i18n( 'Y-m-d', $show_hide_dates_start_timestamp ) : ''; $show_hide_dates_end = $show_hide_dates_end_timestamp ? date_i18n( 'Y-m-d', $show_hide_dates_end_timestamp ) : ''; // Attach DatePicker to the two fields. echo " <script> jQuery( function ( $ ) { $( '.show_hide_dates_fields' ).each( function () { $( this ) .find( 'input' ) .datepicker( { defaultDate: '', dateFormat: 'yy-mm-dd', numberOfMonths: 1, showButtonPanel: true, } ); } ); $( '#woocommerce-product-data' ).on( 'click', '.cancel_show_hide_schedule', function () { var wrap = $( this ).closest( 'div, table' ); //$( this ).hide(); // Hide the 'Cancel' link. wrap.find( '.show_hide_dates_fields' ).find( 'input' ).val( '' ); return false; } ); } ); </script> "; echo ' <style> .woocommerce_options_panel .show_hide_dates_fields .short:first-of-type { margin-bottom: 1em; } .woocommerce_options_panel .show_hide_dates_fields .short:nth-of-type(2) { clear: left; } </style> <p class="form-field show_hide_dates_fields"> <label for="'.$this->show_hide_dates_start_key.'">' . esc_html__( 'Show/hide dates', 'woocommerce' ) . '</label> <input type="text" class="short" name="'.$this->show_hide_dates_start_key.'" id="'.$this->show_hide_dates_start_key.'" value="' . esc_attr( $show_hide_dates_start ) . '" placeholder="' . esc_html( _x( 'Starting…', 'placeholder', 'woocommerce' ) ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" /> <input type="text" class="short" name="'.$this->show_hide_dates_end_key.'" id="'.$this->show_hide_dates_end_key.'" value="' . esc_attr( $show_hide_dates_end ) . '" placeholder="' . esc_html( _x( 'Ending…', 'placeholder', 'woocommerce' ) ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />' . '<a href="#" class="description cancel_show_hide_schedule">' . esc_html__( 'Cancel', 'woocommerce' ) . '</a>' . wc_help_tip( __( 'The product will be shown at 00:00:00 of "Starting" date and hidden at 23:59:59 of "Ending" date.', 'woocommerce' ) ) . ' </p>'; } // Save the date fields values if set. public function save_show_hide_dates( $post_id, $post ) { $product_type = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( wp_unslash( $_POST['product-type'] ) ); $classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' ); $product = new $classname( $post_id ); // Handle show/hide dates. $show_hide_dates_start = ''; $show_hide_dates_end = ''; // Force 'date from' to beginning of day. if ( isset( $_POST['_show_hide_dates_start'] ) ) { $show_hide_dates_start = wc_clean( wp_unslash( $_POST['_show_hide_dates_start'] ) ); if ( ! empty( $show_hide_dates_start ) ) { // ToDo: Maybe use code from set_date_prop() in woocommerce/includes/abstracts/abstract-wc-data.php. $show_hide_dates_start = new WC_DateTime( date( 'Y-m-d 00:00:00', strtotime( $show_hide_dates_start ) ), new DateTimeZone( 'UTC' ) ); // ToDo: If $show_hide_dates_start is in the future I should hide the product now! (set product_visibility terms)? } } // Force 'date to' to the end of the day. if ( isset( $_POST['_show_hide_dates_end'] ) ) { $show_hide_dates_end = wc_clean( wp_unslash( $_POST['_show_hide_dates_end'] ) ); if ( ! empty( $show_hide_dates_end ) ) { // ToDo: Maybe use code from set_date_prop() in woocommerce/includes/abstracts/abstract-wc-data.php. $show_hide_dates_end = new WC_DateTime( date( 'Y-m-d 00:00:00', strtotime( $show_hide_dates_end ) ), new DateTimeZone( 'UTC' ) ); } } $product->update_meta_data( $this->show_hide_dates_start_key, $show_hide_dates_start ? $show_hide_dates_start->getTimestamp() : $show_hide_dates_start ); $product->update_meta_data( $this->show_hide_dates_end_key, $show_hide_dates_end ? $show_hide_dates_end->getTimestamp() : $show_hide_dates_end ); $product->save(); } // Returns an array of IDs of products that will be shown soon. public function get_starting_shows() { global $wpdb; return $wpdb->get_col( $wpdb->prepare( "SELECT postmeta.post_id FROM {$wpdb->postmeta} as postmeta WHERE postmeta.meta_key = '%s' AND postmeta.meta_value > 0 AND postmeta.meta_value < %s", $this->show_hide_dates_start_key, time() ) ); } // Returns an array of IDs of products that are due to be hidden. public function get_ending_shows() { global $wpdb; return $wpdb->get_col( $wpdb->prepare( "SELECT postmeta.post_id FROM {$wpdb->postmeta} as postmeta WHERE postmeta.meta_key = '%s' AND postmeta.meta_value > 0 AND postmeta.meta_value < %s", $this->show_hide_dates_end_key, time() ) ); } // Scheduled check for products to show or hide. public function scheduled_show_hide_check() { // Get products to be shown (or published). $product_ids = $this->get_starting_shows(); if ( $product_ids ) { $visibility_ids = wc_get_product_visibility_term_ids(); foreach ( $product_ids as $product_id ) { $product = wc_get_product( $product_id ); if ( $product ) { $visibility_terms = $this->get_visibility_terms( $product_id ); wp_set_object_terms( $product_id, $visibility_terms, 'product_visibility' ); // Delete the start date so we don't keep changing the product_visibility terms. $product->delete_meta_data( $this->show_hide_dates_start_key ); $product->save(); } } } // Get products to be hidden (or unpublished). $product_ids = $this->get_ending_shows(); if ( $product_ids ) { foreach ( $product_ids as $product_id ) { $product = wc_get_product( $product_id ); if ( $product ) { // Get the terms without the 'exclude-from-catalog' or 'exclude-from-search' terms. $visibility_terms = $this->get_visibility_terms( $product_id ); // Add 'exclude-from-catalog' and 'exclude-from-search' terms so that the product will be hidden. array_push( $visibility_terms, 'exclude-from-catalog', 'exclude-from-search' ); // Hide product by adding 'exclude-from-catalog' and 'exclude-from-search' terms. wp_set_object_terms( $product_id, $visibility_terms, 'product_visibility' ); // Delete the end date so we don't keep hiding this product. $product->delete_meta_data( $this->show_hide_dates_end_key ); $product->save(); } } } } } $ScheduleHideProducts = new ScheduleHideProducts();
Comments