prefix . 'usedkit_prices'; } /** The price-history table; created on activation and whenever its version changes. */ function usedkit_prices_install() { global $wpdb; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta('CREATE TABLE ' . usedkit_prices_table() . ' ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, product_id bigint(20) unsigned NOT NULL, price decimal(19,4) NOT NULL, recorded_at datetime NOT NULL, PRIMARY KEY (id), KEY product_time (product_id, recorded_at) ) ' . $wpdb->get_charset_collate() . ';'); update_option('usedkit_prices_version', USEDKIT_PRICES_VERSION); } add_action('admin_init', function () { if ((int) get_option('usedkit_prices_version') !== USEDKIT_PRICES_VERSION) { usedkit_prices_install(); } }); add_filter('usedkit_default_settings', function ($d) { return $d + array('omnibus' => 'no', 'omnibus_days' => 30); }); add_filter('usedkit_save_settings', function ($out, $post) { return $out + array('omnibus' => !empty($post['omnibus']) ? 'yes' : 'no', 'omnibus_days' => max(1, min(90, absint($post['omnibus_days'] ?? 30)))); }, 10, 2); add_action('usedkit_settings_rows', function ($s) { ?>
is_type('variable') || $product->is_type('grouped')) { return; } $price = $product->get_price(); if ($price === '' || $price === null) { return; } global $wpdb; $table = usedkit_prices_table(); $last = $wpdb->get_var($wpdb->prepare( "SELECT price FROM %i WHERE product_id = %d ORDER BY recorded_at DESC, id DESC LIMIT 1", $table, $product->get_id())); if ($last !== null && abs((float) $last - (float) $price) < 0.00001) { return; } $wpdb->insert($table, array('product_id' => $product->get_id(), 'price' => (float) $price, 'recorded_at' => current_time('mysql', true))); } add_action('woocommerce_after_product_object_save', 'usedkit_record_price'); /** * The lowest price in the `$days` before the current price took effect, or null with no * history from before it. `$history` is [[unix time, price], ...] oldest first. * * The price in force when the window opened counts -- a price set 40 days ago and held * until the discount was applied throughout the window. */ function usedkit_lowest_before($history, $current, $days = 30) { $n = count($history); if ($n === 0) { return null; } // When did the current price begin? Walk back over the run of records at it. $i = $n - 1; if (abs($history[$i][1] - $current) > 0.00001) { return null; // the history has not caught up with this price } while ($i > 0 && abs($history[$i - 1][1] - $current) < 0.00001) { $i--; } if ($i === 0) { return null; // nothing before the current price } $start = $history[$i][0]; $from = $start - $days * DAY_IN_SECONDS; $lowest = null; for ($k = 0; $k < $i; $k++) { list($t, $p) = $history[$k]; $next = $history[$k + 1][0]; if ($next <= $from) { continue; // replaced before the window opened } $lowest = $lowest === null ? $p : min($lowest, $p); } return $lowest; } function usedkit_price_history($product_id) { global $wpdb; $table = usedkit_prices_table(); $rows = $wpdb->get_results($wpdb->prepare( "SELECT UNIX_TIMESTAMP(recorded_at) AS t, price FROM %i WHERE product_id = %d " . "ORDER BY recorded_at, id", $table, $product_id), ARRAY_N); return array_map(function ($r) { return array((int) $r[0], (float) $r[1]); }, $rows ?: array()); } add_filter('woocommerce_get_price_html', function ($html, $product) { $s = usedkit_settings(); if ($s['omnibus'] !== 'yes' || !$product->is_on_sale() || $product->is_type('variable') || $product->is_type('grouped') || is_admin()) { return $html; } $lowest = usedkit_lowest_before(usedkit_price_history($product->get_id()), (float) $product->get_price(), (int) $s['omnibus_days']); if ($lowest === null) { // No history from before the discount: the regular price was the price. $lowest = (float) $product->get_regular_price(); } if (!$lowest) { return $html; } return $html . wp_kses(sprintf('%s %s', /* translators: %d: number of days, 30 by default */ esc_html(sprintf(__('Lowest price in the %d days before the discount:', 'usedkit'), (int) $s['omnibus_days'])), wp_kses_post(wc_price(wc_get_price_to_display($product, array('price' => $lowest))))), usedkit_allowed_html()); }, 20, 2);