Skip to content

Instantly share code, notes, and snippets.

@devinsays
Created November 23, 2022 16:47

Revisions

  1. devinsays created this gist Nov 23, 2022.
    99 changes: 99 additions & 0 deletions schedule-products-sale.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,99 @@
    <?php
    /**
    * WP CLI script to schedule a sale for specific dates.
    *
    * To support scheduled sales to the hour/minute, use this free plugin:
    * https://wordpress.org/plugins/precise-sales-for-woocommerce/
    *
    * wp eval-file schedule-products-sale.php
    */
    if ( ! defined( 'ABSPATH' ) ) {
    exit;
    }

    // Quick explainer of script.
    WP_CLI::log( '' );
    WP_CLI::log( 'This script schedules a sale for specific dates.' );
    WP_CLI::log( 'The sale will only apply to shop products (no subscriptions).' );
    WP_CLI::log( 'Sale times should entered in Eastern Timezone.' );
    WP_CLI::log( '' );

    // Prompt for sale dates.
    $sale_start = cli_ask( 'Start date (YYYY-MM-DD HH:mm):' );
    $sale_end = cli_ask( 'End date (YYYY-MM-DD HH:mm):' );
    $percentage = floatval( cli_ask( 'Sale percentage (e.g. 10):' ) );

    try {
    $date_start = new DateTime( $sale_start, wp_timezone() );
    $date_end = new DateTime( $sale_end, wp_timezone() );
    } catch ( Exception $e ) {
    WP_CLI::error( 'Dates could not be parsed.' );
    return;
    }

    if ( current_datetime()->format( 'U' ) > $date_end->format( 'U' ) ) {
    WP_CLI::error( 'End date must be in the future.' );
    return;
    }

    $products = get_posts(
    [
    'post_type' => [ 'product', 'product_variation' ],
    'posts_per_page' => -1,
    'fields' => 'ids',
    'post_status' => 'publish',
    ]
    );

    if ( $products ) {
    WP_CLI::log( 'Found ' . count( $products ) . '.' );
    $progress = \WP_CLI\Utils\make_progress_bar( 'Updating Products', count( $products ) );

    foreach ( $products as $product_id ) {
    $product = wc_get_product( $product_id );

    // Skip subscriptions.
    if ( ! in_array( $product->get_type(), [ 'simple', 'variation' ], true ) ) {
    $progress->tick();
    continue;
    }

    $price = $product->get_regular_price();

    // If not price is set, or price is $0, skip.
    if ( ! $price ) {
    $progress->tick();
    continue;
    }

    $sale_price = wc_format_decimal( $price - $price * $percentage / 100, 2 );
    $product->set_props(
    [
    'sale_price' => $sale_price,
    'date_on_sale_from' => $sale_start,
    'date_on_sale_to' => $sale_end,
    ]
    );

    $product->save();
    $progress->tick();
    }

    $progress->finish();
    WP_CLI::success( 'Finished!' );
    }

    /**
    * Ask a question and returns the user's input.
    *
    * @param string $question
    * @param bool $case_sensitive
    *
    * @return string
    */
    function cli_ask( $question, $case_sensitive = false ) {
    fwrite( STDOUT, trim( $question ) . ' ' );
    $answer = trim( fgets( STDIN ) );
    $answer = $case_sensitive ? $answer : strtolower( $answer );
    return $answer;
    }