/** * Save meta box data */ public static function save($post_id, $post) { if ('shop_subscription' == $post->post_type && !empty($_POST['woocommerce_meta_nonce']) && wp_verify_nonce($_POST['woocommerce_meta_nonce'], 'woocommerce_save_data')) { if (isset($_POST['_billing_interval'])) { update_post_meta($post_id, '_billing_interval', $_POST['_billing_interval']); } if (!empty($_POST['_billing_period'])) { update_post_meta($post_id, '_billing_period', $_POST['_billing_period']); } $subscription = wcs_get_subscription($post_id); $dates = array(); foreach (wcs_get_subscription_date_types() as $date_key => $date_label) { if ('last_payment' == $date_key) { continue; } $utc_timestamp_key = $date_key . '_timestamp_utc'; // A subscription needs a start date, even if it wasn't set if (isset($_POST[$utc_timestamp_key])) { $datetime = $_POST[$utc_timestamp_key]; } elseif ('start' === $date_key) { $datetime = current_time('timestamp', true); } else { // No date to set continue; } $dates[$date_key] = date('Y-m-d H:i:s', $datetime); } try { $subscription->update_dates($dates, 'gmt'); wp_cache_delete($post_id, 'posts'); } catch (Exception $e) { wcs_add_admin_notice($e->getMessage(), 'error'); } } }
public function __construct() { $this->date_types_to_schedule = apply_filters('woocommerce_subscriptions_date_types_to_schedule', array_keys(wcs_get_subscription_date_types())); add_action('woocommerce_subscription_date_updated', array(&$this, 'update_date'), 10, 3); add_action('woocommerce_subscription_date_deleted', array(&$this, 'delete_date'), 10, 2); add_action('woocommerce_subscription_status_updated', array(&$this, 'update_status'), 10, 3); }
} else { ?> <strong><?php esc_html_e('Recurring:', 'woocommerce-subscriptions'); ?> </strong> <?php printf('%s %s', esc_html(wcs_get_subscription_period_interval_strings($the_subscription->billing_interval)), esc_html(wcs_get_subscription_period_strings(1, $the_subscription->billing_period))); ?> <?php } ?> </div> <?php foreach (wcs_get_subscription_date_types() as $date_key => $date_label) { ?> <?php if ('last_payment' === $date_key) { ?> <?php continue; ?> <?php } ?> <div id="subscription-<?php echo esc_attr($date_key); ?> -date" class="date-fields"> <strong><?php
/** * Set the dates on the subscription. * * Because dates are interdependent on each other, this function will take an array of dates, make sure that all * dates are in the right order in the right format, that there is at least something to update. * * @param array $dates array containing dates with keys: 'start', 'trial_end', 'next_payment', * 'last_payment' or 'end'. Values are time * @param string $timezone The timezone of the $datetime param. Default 'gmt'. */ public function update_dates($dates, $timezone = 'gmt') { global $wpdb; if (!is_array($dates)) { throw new InvalidArgumentException(__('Invalid format. First parameter needs to be an array.', 'woocommerce-subscriptions')); } if (empty($dates)) { throw new InvalidArgumentException(__('Invalid data. First parameter was empty when passed to update_dates().', 'woocommerce-subscriptions')); } $allowed_date_keys = array_keys(wcs_get_subscription_date_types()); $passed_date_keys = array_keys($dates); $extra_keys = array_diff(str_replace('_date', '', $passed_date_keys), $allowed_date_keys); if (!empty($extra_keys)) { throw new InvalidArgumentException(__('Invalid data. First parameter has a date that is not in the registered date types.', 'woocommerce-subscriptions')); } $timestamps = array(); foreach ($dates as $date_type => $datetime) { if (!empty($datetime) && false === wcs_is_datetime_mysql_format($datetime)) { // translators: placeholder is date type (e.g. "end", "next_payment"...) throw new InvalidArgumentException(sprintf(_x('Invalid %s date. The date must be of the format: "Y-m-d H:i:s".', 'appears in an error message if date is wrong format', 'woocommerce-subscriptions'), $date_type)); } $date_type = str_replace('_date', '', $date_type); if (empty($datetime)) { $timestamps[$date_type] = 0; } else { if ('gmt' !== strtolower($timezone)) { $datetime = get_gmt_from_date($datetime); } $timestamps[$date_type] = strtotime($datetime); } } foreach ($allowed_date_keys as $date_type) { if (!array_key_exists($date_type, $timestamps)) { $timestamps[$date_type] = $this->get_time($date_type); } if (0 == $timestamps[$date_type]) { // Last payment is not in the UI, and it should NOT be deleted as that would mess with scheduling if ('last_payment' != $date_type && 'start' != $date_type) { $this->delete_date($date_type); } unset($timestamps[$date_type]); continue; } } $messages = array(); // And then iterate over them. We need the two separate loops as we need a full array before we start checking // the relationships between them. foreach ($timestamps as $date_type => $datetime) { switch ($date_type) { case 'end': if (array_key_exists('last_payment', $timestamps) && $datetime <= $timestamps['last_payment']) { $messages[] = sprintf(__('The %s date must occur after the last payment date.', 'woocommerce-subscriptions'), $date_type); } if (array_key_exists('next_payment', $timestamps) && $datetime <= $timestamps['next_payment']) { $messages[] = sprintf(__('The %s date must occur after the next payment date.', 'woocommerce-subscriptions'), $date_type); } case 'next_payment': // Guarantees that end is strictly after trial_end, because if next_payment and end can't be at same // time if (array_key_exists('trial_end', $timestamps) && $datetime < $timestamps['trial_end']) { $messages[] = sprintf(__('The %s date must occur after the trial end date.', 'woocommerce-subscriptions'), $date_type); } case 'trial_end': if ($datetime <= $timestamps['start']) { $messages[] = sprintf(__('The %s date must occur after the start date.', 'woocommerce-subscriptions'), $date_type); } } } if (!empty($messages)) { throw new Exception(join(' ', $messages)); } $is_updated = false; foreach ($timestamps as $date_type => $timestamp) { $datetime = date('Y-m-d H:i:s', $timestamp); if ($datetime == $this->get_date($date_type)) { continue; } switch ($date_type) { case 'next_payment': case 'trial_end': case 'end': $is_updated = update_post_meta($this->id, wcs_get_date_meta_key($date_type), $datetime); break; case 'start': $wpdb->query($wpdb->prepare("UPDATE {$wpdb->posts} SET post_date = %s, post_date_gmt = %s WHERE ID = %s", get_date_from_gmt($datetime), $datetime, $this->id)); // Don't use wp_update_post() to avoid infinite loops here $is_updated = true; break; case 'last_payment': $this->update_last_payment_date($datetime); $is_updated = true; break; } if ($is_updated) { $this->schedule->{$date_type} = $datetime; do_action('woocommerce_subscription_date_updated', $this, $date_type, $datetime); } } }
public function set_date_types_to_schedule() { $this->date_types_to_schedule = apply_filters('woocommerce_subscriptions_date_types_to_schedule', array_keys(wcs_get_subscription_date_types())); }