本文整理汇总了PHP中WC_Subscriptions_Product::get_trial_expiration_date方法的典型用法代码示例。如果您正苦于以下问题:PHP WC_Subscriptions_Product::get_trial_expiration_date方法的具体用法?PHP WC_Subscriptions_Product::get_trial_expiration_date怎么用?PHP WC_Subscriptions_Product::get_trial_expiration_date使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类WC_Subscriptions_Product
的用法示例。
在下文中一共展示了WC_Subscriptions_Product::get_trial_expiration_date方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的PHP代码示例。
示例1: create_pending_subscription_for_order
/**
* Uses the details of an order to create a pending subscription on the customers account
* for a subscription product, as specified with $product_id.
*
* @param $order mixed int | WC_Order The order ID or WC_Order object to create the subscription from.
* @param $product_id int The ID of the subscription product on the order.
* @param $args array An array of name => value pairs to customise the details of the subscription, including:
* 'start_date' A MySQL formatted date/time string on which the subscription should start, in UTC timezone
* 'expiry_date' A MySQL formatted date/time string on which the subscription should expire, in UTC timezone
* @since 1.1
*/
public static function create_pending_subscription_for_order($order, $product_id, $args = array())
{
if (!is_object($order)) {
$order = new WC_Order($order);
}
if (!WC_Subscriptions_Product::is_subscription($product_id)) {
return;
}
$args = wp_parse_args($args, array('start_date' => '', 'expiry_date' => ''));
$subscription_key = self::get_subscription_key($order->id, $product_id);
// In case the subscription exists already
$subscription = self::get_users_subscription($order->customer_user, $subscription_key);
// Adding a new subscription so set the start date/time to now
if (!empty($args['start_date'])) {
if (is_numeric($args['start_date'])) {
$args['start_date'] = date('Y-m-d H:i:s', $args['start_date']);
}
$start_date = $args['start_date'];
} else {
$start_date = isset($subscription['start_date']) ? $subscription['start_date'] : gmdate('Y-m-d H:i:s');
}
// Adding a new subscription so set the expiry date/time from the order date
if (!empty($args['expiry_date'])) {
if (is_numeric($args['expiry_date'])) {
$args['expiry_date'] = date('Y-m-d H:i:s', $args['expiry_date']);
}
$expiration = $args['expiry_date'];
} else {
$expiration = isset($subscription['expiry_date']) ? $subscription['expiry_date'] : WC_Subscriptions_Product::get_expiration_date($product_id, $start_date);
}
// Adding a new subscription so set the expiry date/time from the order date
$trial_expiration = isset($subscription['trial_expiry_date']) ? $subscription['trial_expiry_date'] : WC_Subscriptions_Product::get_trial_expiration_date($product_id, $start_date);
$failed_payments = isset($subscription['failed_payments']) ? $subscription['failed_payments'] : 0;
$completed_payments = isset($subscription['completed_payments']) ? $subscription['completed_payments'] : array();
$subscriptions[$subscription_key] = array('product_id' => $product_id, 'order_key' => $order->order_key, 'order_id' => $order->id, 'start_date' => $start_date, 'expiry_date' => $expiration, 'end_date' => 0, 'status' => 'pending', 'trial_expiry_date' => $trial_expiration, 'failed_payments' => $failed_payments, 'completed_payments' => $completed_payments);
self::update_users_subscriptions($order->customer_user, $subscriptions);
$product = WC_Subscriptions::get_product($product_id);
// Set subscription status to active and log activation
$order->add_order_note(sprintf(__('Pending subscription created for "%s".', WC_Subscriptions::$text_domain), $product->get_title()));
do_action('pending_subscription_created_for_order', $order, $product_id);
}
示例2: calculate_first_payment_date
/**
* Calculate the first payment date for a synced subscription.
*
* The date is calculated in UTC timezone.
*
* @param WC_Product $product A subscription product.
* @param string $type (optional) The format to return the first payment date in, either 'mysql' or 'timestamp'. Default 'mysql'.
* @param string $from_date (optional) The date to calculate the first payment from in GMT/UTC timzeone. If not set, it will use the current date. This should not include any trial period on the product.
* @since 1.5
*/
public static function calculate_first_payment_date($product, $type = 'mysql', $from_date = '')
{
if (!is_object($product)) {
$product = WC_Subscriptions::get_product($product);
}
if (!self::is_product_synced($product)) {
return 0;
}
$period = WC_Subscriptions_Product::get_period($product);
$trial_period = WC_Subscriptions_Product::get_trial_period($product);
$trial_length = WC_Subscriptions_Product::get_trial_length($product);
$from_date_param = $from_date;
if (empty($from_date)) {
$from_date = gmdate('Y-m-d H:i:s');
}
// If the subscription has a free trial period, the first payment should be synced to a day after the free trial
if ($trial_length > 0) {
$from_date = WC_Subscriptions_Product::get_trial_expiration_date($product, $from_date);
}
$from_timestamp = strtotime($from_date) + get_option('gmt_offset') * 3600;
// Site time
$payment_day = self::get_products_payment_day($product);
if ('week' == $period) {
// strtotime() only handles English, so can't use $wp_locale->weekday here
$weekdays = array(1 => 'Monday', 2 => 'Tuesday', 3 => 'Wednesday', 4 => 'Thursday', 5 => 'Friday', 6 => 'Saturday', 7 => 'Sunday');
// strtotime() will figure out if the day is in the future or today (see: https://gist.github.com/thenbrent/9698083)
$first_payment_timestamp = strtotime($weekdays[$payment_day], $from_timestamp);
} elseif ('month' == $period) {
// strtotime() needs to know the month, so we need to determine if the specified day has occured this month yet or if we want the last day of the month (see: https://gist.github.com/thenbrent/9698083)
if ($payment_day > 27) {
// we actually want the last day of the month
$payment_day = gmdate('t', $from_timestamp);
$month = gmdate('F', $from_timestamp);
} elseif (gmdate('j', $from_timestamp) > $payment_day) {
// today is later than specified day in the from date, we need the next month
$month = date('F', WC_Subscriptions::add_months($from_timestamp, 1));
} else {
// specified day is either today or still to come in the month of the from date
$month = gmdate('F', $from_timestamp);
}
$first_payment_timestamp = strtotime("{$payment_day} {$month}", $from_timestamp);
} elseif ('year' == $period) {
// We can't use $wp_locale here because it is translated
switch ($payment_day['month']) {
case 1:
$month = 'January';
break;
case 2:
$month = 'February';
break;
case 3:
$month = 'March';
break;
case 4:
$month = 'April';
break;
case 5:
$month = 'May';
break;
case 6:
$month = 'June';
break;
case 7:
$month = 'July';
break;
case 8:
$month = 'August';
break;
case 9:
$month = 'September';
break;
case 10:
$month = 'October';
break;
case 11:
$month = 'November';
break;
case 12:
$month = 'December';
break;
}
$first_payment_timestamp = strtotime("{$payment_day['day']} {$month}", $from_timestamp);
}
// Make sure the next payment is in the future and after the $from_date, as strtotime() will return the date this year for any day in the past when adding months or years (see: https://gist.github.com/thenbrent/9698083)
if ('year' == $period || 'month' == $period) {
// First make sure the day is in the past so that we don't end up jumping a month or year because of a few hours difference between now and the billing date
if (gmdate('j', $first_payment_timestamp) < gmdate('j') && gmdate('n', $first_payment_timestamp) <= gmdate('n') && gmdate('Y', $first_payment_timestamp) <= gmdate('Y')) {
$i = 1;
// Then make sure the date and time of the payment is in the future
while (($first_payment_timestamp < gmdate('U') || $first_payment_timestamp < $from_timestamp) && $i < 30) {
//.........这里部分代码省略.........
示例3: processSubscriptions
private function processSubscriptions()
{
global $wpdb;
// check wether subscriptions addon is activated
if (class_exists('WC_Subscriptions_Order') && WC_Subscriptions_Order::order_contains_subscription($this->order)) {
$products = $this->order->get_items();
foreach ($products as $product) {
if (is_array($product) && isset($product['product_id']) && intval($product['product_id']) > 0 && isset($product['subscription_period']) && $product['subscription_period'] != '') {
// product is a subscription?
$woo_sub_key = WC_Subscriptions_Manager::get_subscription_key($this->order_id, $product['product_id']);
// required vars
$amount = floatval(WC_Subscriptions_Order::get_recurring_total($this->order)) * 100;
$currency = get_woocommerce_currency();
$interval = intval($product['subscription_interval']);
$period = strtoupper($product['subscription_period']);
$length = strtoupper($product['subscription_length']);
if ($length > 0) {
$periodOfValidity = $length . ' ' . $period;
} else {
$periodOfValidity = false;
}
$trial_end = strtotime(WC_Subscriptions_Product::get_trial_expiration_date($product['product_id'], get_gmt_from_date($this->order->order_date)));
if ($trial_end === false) {
$trial_time = 0;
} else {
$datediff = $trial_end - time();
$trial_time = ceil($datediff / (60 * 60 * 24));
}
// md5 name
$woo_sub_md5 = md5($amount . $currency . $interval . $trial_time);
// get offer
$name = 'woo_' . $product['product_id'] . '_' . $woo_sub_md5;
$offer = $this->subscriptions->offerGetDetailByName($name);
// check wether offer exists in paymill
if ($offer === false) {
// offer does not exist in paymill yet, create it
$params = array('amount' => $amount, 'currency' => $currency, 'interval' => $interval . ' ' . $period, 'name' => $name, 'trial_period_days' => intval($trial_time));
$offer = $this->subscriptions->offerCreate($params);
if ($GLOBALS['paymill_loader']->paymill_errors->status()) {
$GLOBALS['paymill_loader']->paymill_errors->getErrors();
return false;
}
}
// create user subscription
$user_sub = $this->subscriptions->create($this->clientClass->getCurrentClientID(), $offer, $this->paymentClass->getPaymentID(), isset($_POST['paymill_delivery_date']) ? $_POST['paymill_delivery_date'] : false, $periodOfValidity);
if ($GLOBALS['paymill_loader']->paymill_errors->status()) {
//maybe offer cache is outdated, recache and try again
$GLOBALS['paymill_loader']->paymill_errors->reset();
// reset error status
$this->subscriptions->offerGetList(true);
$params = array('amount' => $amount, 'currency' => $currency, 'interval' => $interval . ' ' . $period, 'name' => $name, 'trial_period_days' => intval($trial_time));
$offer = $this->subscriptions->offerCreate($params);
if ($GLOBALS['paymill_loader']->paymill_errors->status()) {
$GLOBALS['paymill_loader']->paymill_errors->getErrors();
return false;
}
$user_sub = $this->subscriptions->create($this->clientClass->getCurrentClientID(), $offer, $this->paymentClass->getPaymentID(), isset($_POST['paymill_delivery_date']) ? $_POST['paymill_delivery_date'] : false, $periodOfValidity);
if ($GLOBALS['paymill_loader']->paymill_errors->status()) {
$GLOBALS['paymill_loader']->paymill_errors->getErrors();
return false;
}
}
$wpdb->query($wpdb->prepare('INSERT INTO ' . $wpdb->prefix . 'paymill_subscriptions (paymill_sub_id, woo_user_id, woo_offer_id) VALUES (%s, %s, %s)', array($user_sub, get_current_user_id(), $woo_sub_key)));
// subscription successful
do_action('paymill_woocommerce_subscription_created', array('product_id' => $product['product_id'], 'offer_id' => $offer));
return true;
}
}
} else {
return true;
}
}
示例4: create_pending_subscription_for_order
/**
* Uses the details of an order to create a pending subscription on the customers account
* for a subscription product, as specified with $product_id.
*
* @param int|WC_Order $order The order ID or WC_Order object to create the subscription from.
* @param int $product_id The ID of the subscription product on the order.
* @param array $args An array of name => value pairs to customise the details of the subscription, including:
* 'start_date' A MySQL formatted date/time string on which the subscription should start, in UTC timezone
* 'expiry_date' A MySQL formatted date/time string on which the subscription should expire, in UTC timezone
* @since 1.1
*/
public static function create_pending_subscription_for_order($order, $product_id, $args = array())
{
if (!is_object($order)) {
$order = new WC_Order($order);
}
if (!WC_Subscriptions_Product::is_subscription($product_id)) {
return;
}
$args = wp_parse_args($args, array('start_date' => '', 'expiry_date' => ''));
$subscription_key = self::get_subscription_key($order->id, $product_id);
// In case the subscription exists already
$subscription = self::get_subscription($subscription_key);
if (!empty($subscription['variation_id'])) {
$product_id = $subscription['variation_id'];
} elseif (!empty($subscription['product_id'])) {
$product_id = $subscription['product_id'];
}
// Adding a new subscription so set the start date/time to now
if (!empty($args['start_date'])) {
if (is_numeric($args['start_date'])) {
$args['start_date'] = date('Y-m-d H:i:s', $args['start_date']);
}
$start_date = $args['start_date'];
} else {
$start_date = !empty($subscription['start_date']) ? $subscription['start_date'] : gmdate('Y-m-d H:i:s');
}
// Adding a new subscription so set the expiry date/time from the order date
if (!empty($args['expiry_date'])) {
if (is_numeric($args['expiry_date'])) {
$args['expiry_date'] = date('Y-m-d H:i:s', $args['expiry_date']);
}
$expiration = $args['expiry_date'];
} else {
$expiration = !empty($subscription['expiry_date']) ? $subscription['expiry_date'] : WC_Subscriptions_Product::get_expiration_date($product_id, $start_date);
}
// Adding a new subscription so set the expiry date/time from the order date
$trial_expiration = !empty($subscription['trial_expiry_date']) ? $subscription['trial_expiry_date'] : WC_Subscriptions_Product::get_trial_expiration_date($product_id, $start_date);
$failed_payments = !empty($subscription['failed_payments']) ? $subscription['failed_payments'] : 0;
$completed_payments = !empty($subscription['completed_payments']) ? $subscription['completed_payments'] : array();
$order_item_id = WC_Subscriptions_Order::get_item_id_by_subscription_key($subscription_key);
// Store the subscription details in item meta
woocommerce_add_order_item_meta($order_item_id, '_subscription_start_date', $start_date, true);
woocommerce_add_order_item_meta($order_item_id, '_subscription_expiry_date', $expiration, true);
woocommerce_add_order_item_meta($order_item_id, '_subscription_trial_expiry_date', $trial_expiration, true);
woocommerce_add_order_item_meta($order_item_id, '_subscription_failed_payments', $failed_payments, true);
woocommerce_add_order_item_meta($order_item_id, '_subscription_completed_payments', $completed_payments, true);
woocommerce_add_order_item_meta($order_item_id, '_subscription_status', 'pending', true);
woocommerce_add_order_item_meta($order_item_id, '_subscription_end_date', 0, true);
woocommerce_add_order_item_meta($order_item_id, '_subscription_suspension_count', 0, true);
$product = WC_Subscriptions::get_product($product_id);
// Set subscription status to active and log activation
$order->add_order_note(sprintf(__('Pending subscription created for "%s".', 'woocommerce-subscriptions'), $product->get_title()));
do_action('pending_subscription_created_for_order', $order, $product_id);
}
示例5: create_pending_subscription_for_order
/**
* Uses the details of an order to create a pending subscription on the customers account
* for a subscription product, as specified with $product_id.
*
* @param int|WC_Order $order The order ID or WC_Order object to create the subscription from.
* @param int $product_id The ID of the subscription product on the order, if a variation, it must be the variation's ID.
* @param array $args An array of name => value pairs to customise the details of the subscription, including:
* 'start_date' A MySQL formatted date/time string on which the subscription should start, in UTC timezone
* 'expiry_date' A MySQL formatted date/time string on which the subscription should expire, in UTC timezone
* @since 1.1
*/
public static function create_pending_subscription_for_order($order, $product_id, $args = array())
{
_deprecated_function(__METHOD__, '2.0', 'wcs_create_subscription()');
if (!is_object($order)) {
$order = new WC_Order($order);
}
if (!WC_Subscriptions_Product::is_subscription($product_id)) {
return;
}
$args = wp_parse_args($args, array('start_date' => get_gmt_from_date($order->order_date), 'expiry_date' => ''));
$billing_period = WC_Subscriptions_Product::get_period($product_id);
$billing_interval = WC_Subscriptions_Product::get_interval($product_id);
// Support passing timestamps
$args['start_date'] = is_numeric($args['start_date']) ? date('Y-m-d H:i:s', $args['start_date']) : $args['start_date'];
$product = wc_get_product($product_id);
// Check if there is already a subscription for this product and order
$subscriptions = wcs_get_subscriptions(array('order_id' => $order->id, 'product_id' => $product_id));
if (!empty($subscriptions)) {
$subscription = array_pop($subscriptions);
// Make sure the subscription is pending and start date is set correctly
wp_update_post(array('ID' => $subscription->id, 'post_status' => 'wc-' . apply_filters('woocommerce_default_subscription_status', 'pending'), 'post_date' => get_date_from_gmt($args['start_date'])));
} else {
$subscription = wcs_create_subscription(array('start_date' => get_date_from_gmt($args['start_date']), 'order_id' => $order->id, 'customer_id' => $order->get_user_id(), 'billing_period' => $billing_period, 'billing_interval' => $billing_interval, 'customer_note' => $order->customer_note));
if (is_wp_error($subscription)) {
throw new Exception(__('Error: Unable to create subscription. Please try again.', 'woocommerce-subscriptions'));
}
$item_id = $subscription->add_product($product, 1, array('variation' => method_exists($product, 'get_variation_attributes') ? $product->get_variation_attributes() : array(), 'totals' => array('subtotal' => $product->get_price(), 'subtotal_tax' => 0, 'total' => $product->get_price(), 'tax' => 0, 'tax_data' => array('subtotal' => array(), 'total' => array()))));
if (!$item_id) {
throw new Exception(__('Error: Unable to add product to created subscription. Please try again.', 'woocommerce-subscriptions'));
}
}
// Make sure some of the meta is copied form the order rather than the store's defaults
update_post_meta($subscription->id, '_order_currency', $order->order_currency);
update_post_meta($subscription->id, '_prices_include_tax', $order->prices_include_tax);
// Adding a new subscription so set the expiry date/time from the order date
if (!empty($args['expiry_date'])) {
if (is_numeric($args['expiry_date'])) {
$args['expiry_date'] = date('Y-m-d H:i:s', $args['expiry_date']);
}
$expiration = $args['expiry_date'];
} else {
$expiration = WC_Subscriptions_Product::get_expiration_date($product_id, $args['start_date']);
}
// Adding a new subscription so set the expiry date/time from the order date
$trial_expiration = WC_Subscriptions_Product::get_trial_expiration_date($product_id, $args['start_date']);
$dates_to_update = array();
if ($trial_expiration > 0) {
$dates_to_update['trial_end'] = $trial_expiration;
}
if ($expiration > 0) {
$dates_to_update['end'] = $expiration;
}
if (!empty($dates_to_update)) {
$subscription->update_dates($dates_to_update);
}
// Set the recurring totals on the subscription
$subscription->set_total(0, 'tax');
$subscription->set_total($product->get_price(), 'total');
$subscription->add_order_note(__('Pending subscription created.', 'woocommerce-subscriptions'));
do_action('pending_subscription_created_for_order', $order, $product_id);
}
示例6: calculate_next_payment_date
/**
* Takes a subscription product's ID and calculates the date on which the next payment is due.
*
* Calculation is based on $from_date if specified, otherwise it will fall back to the last
* completed payment, the subscription's start time, or the current date/time, in that order.
*
* The next payment date will occur after any free trial period and up to any expiration date.
*
* @param mixed $order A WC_Order object or the ID of the order which the subscription was purchased in.
* @param int $product_id The product/post ID of the subscription
* @param string $type (optional) The format for the Either 'mysql' or 'timestamp'.
* @param mixed $from_date A MySQL formatted date/time string from which to calculate the next payment date, or empty (default), which will use the last payment on the subscription, or today's date/time if no previous payments have been made.
* @return mixed If there is no future payment set, returns 0, otherwise it will return a date of the next payment in the form specified by $type
* @since 1.0
*/
public static function calculate_next_payment_date($order, $product_id, $type = 'mysql', $from_date = '')
{
if (!is_object($order)) {
$order = new WC_Order($order);
}
$from_date_arg = $from_date;
$subscription = WC_Subscriptions_Manager::get_subscription(WC_Subscriptions_Manager::get_subscription_key($order->id, $product_id));
$subscription_period = self::get_subscription_period($order, $product_id);
$subscription_interval = self::get_subscription_interval($order, $product_id);
$subscription_trial_length = self::get_subscription_trial_length($order, $product_id);
$subscription_trial_period = self::get_subscription_trial_period($order, $product_id);
$subscription_length = self::get_subscription_length($order, $product_id);
$trial_end_time = !empty($subscription['trial_expiry_date']) ? $subscription['trial_expiry_date'] : WC_Subscriptions_Product::get_trial_expiration_date($product_id, get_gmt_from_date($order->order_date));
$trial_end_time = strtotime($trial_end_time);
// If the subscription is not active, there is no next payment date
if ($subscription['status'] != 'active' || $subscription_interval == $subscription_length) {
$next_payment_timestamp = 0;
// If the subscription has a free trial period, and we're still in the free trial period, the next payment is due at the end of the free trial
} elseif ($subscription_trial_length > 0 && $trial_end_time > gmdate('U') + 60 * 60 * 23 + 120) {
// Make sure trial expiry is more than 23+ hours in the future to account for trial expiration dates incorrectly stored in non-UTC/GMT timezone and also for any potential changes to the site's timezone
$next_payment_timestamp = $trial_end_time;
// The next payment date is {interval} billing periods from the from date
} else {
// We have a timestamp
if (!empty($from_date) && is_numeric($from_date)) {
$from_date = date('Y-m-d H:i:s', $from_date);
}
if (empty($from_date)) {
if (!empty($subscription['completed_payments'])) {
$from_date = array_pop($subscription['completed_payments']);
$add_failed_payments = true;
} else {
if (!empty($subscription['start_date'])) {
$from_date = $subscription['start_date'];
$add_failed_payments = true;
} else {
$from_date = gmdate('Y-m-d H:i:s');
$add_failed_payments = false;
}
}
$failed_payment_count = self::get_failed_payment_count($order, $product_id);
// Maybe take into account any failed payments
if (true === $add_failed_payments && $failed_payment_count > 0) {
$failed_payment_periods = $failed_payment_count * $subscription_interval;
$from_timestamp = strtotime($from_date);
if ('month' == $subscription_period) {
$from_date = date('Y-m-d H:i:s', WC_Subscriptions::add_months($from_timestamp, $failed_payment_periods));
} else {
// Safe to just add the billing periods
$from_date = date('Y-m-d H:i:s', strtotime("+ {$failed_payment_periods} {$subscription_period}", $from_timestamp));
}
}
}
$from_timestamp = strtotime($from_date);
if ('month' == $subscription_period) {
// Workaround potential PHP issue
$next_payment_timestamp = WC_Subscriptions::add_months($from_timestamp, $subscription_interval);
} else {
$next_payment_timestamp = strtotime("+ {$subscription_interval} {$subscription_period}", $from_timestamp);
}
// Make sure the next payment is in the future
$i = 1;
while ($next_payment_timestamp < gmdate('U') && $i < 30) {
if ('month' == $subscription_period) {
$next_payment_timestamp = WC_Subscriptions::add_months($next_payment_timestamp, $subscription_interval);
} else {
// Safe to just add the billing periods
$next_payment_timestamp = strtotime("+ {$subscription_interval} {$subscription_period}", $next_payment_timestamp);
}
$i = $i + 1;
}
}
// If the subscription has an expiry date and the next billing period comes after the expiration, return 0
if (isset($subscription['expiry_date']) && 0 != $subscription['expiry_date'] && $next_payment_timestamp + 120 > strtotime($subscription['expiry_date'])) {
$next_payment_timestamp = 0;
}
$next_payment = 'mysql' == $type && 0 != $next_payment_timestamp ? date('Y-m-d H:i:s', $next_payment_timestamp) : $next_payment_timestamp;
return apply_filters('woocommerce_subscriptions_calculated_next_payment_date', $next_payment, $order, $product_id, $type, $from_date, $from_date_arg);
}
示例7: recalculate_trial_end_date
/**
* Maybe recalculate the trial end date for synced subscription products that contain the unnecessary
* "one day trial" period.
*
* @since 2.0
* @deprecated 2.0.14
*/
public static function recalculate_trial_end_date($trial_end_date, $recurring_cart, $product)
{
_deprecated_function(__METHOD__, '2.0.14');
if (self::is_product_synced($product)) {
$product_id = isset($product->variation_id) ? $product->variation_id : $product->id;
$trial_end_date = WC_Subscriptions_Product::get_trial_expiration_date($product_id);
}
return $trial_end_date;
}
示例8: calculate_subscription_totals
/**
* Calculate the initial and recurring totals for all subscription products in the cart.
*
* We need to group subscriptions by billing schedule to make the display and creation of recurring totals sane,
* when there are multiple subscriptions in the cart. To do that, we use an array with keys of the form:
* '{billing_interval}_{billing_period}_{trial_interval}_{trial_period}_{length}_{billing_period}'. This key
* is used to reference WC_Cart objects for each recurring billing schedule and these are stored in the master
* cart with the billing schedule key.
*
* After we have calculated and grouped all recurring totals, we need to checks the structure of the subscription
* product prices to see whether they include sign-up fees and/or free trial periods and then recalculates the
* appropriate totals by using the @see self::$calculation_type flag and cloning the cart to run @see WC_Cart::calculate_totals()
*
* @since 1.3.5
* @version 2.0
*/
public static function calculate_subscription_totals($total, $cart)
{
if (!self::cart_contains_subscription() && !wcs_cart_contains_resubscribe()) {
// cart doesn't contain subscription
return $total;
} elseif ('none' != self::$calculation_type) {
// We're in the middle of a recalculation, let it run
return $total;
}
// Save the original cart values/totals, as we'll use this when there is no sign-up fee
WC()->cart->total = $total < 0 ? 0 : $total;
do_action('woocommerce_subscription_cart_before_grouping');
$subscription_groups = array();
// Group the subscription items by their cart item key based on billing schedule
foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
if (WC_Subscriptions_Product::is_subscription($cart_item['data'])) {
$subscription_groups[self::get_recurring_cart_key($cart_item)][] = $cart_item_key;
}
}
do_action('woocommerce_subscription_cart_after_grouping');
$recurring_carts = array();
// Now let's calculate the totals for each group of subscriptions
self::$calculation_type = 'recurring_total';
foreach ($subscription_groups as $recurring_cart_key => $subscription_group) {
// Create a clone cart to calculate and store totals for this group of subscriptions
$recurring_cart = clone WC()->cart;
$product = null;
// Remove any items not in this subscription group
foreach ($recurring_cart->get_cart() as $cart_item_key => $cart_item) {
if (!in_array($cart_item_key, $subscription_group)) {
unset($recurring_cart->cart_contents[$cart_item_key]);
continue;
}
if (null === $product) {
$product = $cart_item['data'];
}
}
$recurring_cart->start_date = apply_filters('wcs_recurring_cart_start_date', gmdate('Y-m-d H:i:s'), $recurring_cart);
$recurring_cart->trial_end_date = apply_filters('wcs_recurring_cart_trial_end_date', WC_Subscriptions_Product::get_trial_expiration_date($product, $recurring_cart->start_date), $recurring_cart, $product);
$recurring_cart->next_payment_date = apply_filters('wcs_recurring_cart_next_payment_date', WC_Subscriptions_Product::get_first_renewal_payment_date($product, $recurring_cart->start_date), $recurring_cart, $product);
$recurring_cart->end_date = apply_filters('wcs_recurring_cart_end_date', WC_Subscriptions_Product::get_expiration_date($product, $recurring_cart->start_date), $recurring_cart, $product);
// No fees recur (yet)
$recurring_cart->fees = array();
$recurring_cart->fee_total = 0;
WC()->shipping->reset_shipping();
self::maybe_recalculate_shipping();
$recurring_cart->calculate_totals();
// Store this groups cart details
$recurring_carts[$recurring_cart_key] = clone $recurring_cart;
// And remove some other floatsam
$recurring_carts[$recurring_cart_key]->removed_cart_contents = array();
$recurring_carts[$recurring_cart_key]->cart_session_data = array();
}
self::$calculation_type = 'none';
// We need to reset the packages and totals stored in WC()->shipping too
self::maybe_recalculate_shipping();
WC()->cart->calculate_shipping();
// If there is no sign-up fee and a free trial, and no products being purchased with the subscription, we need to zero the fees for the first billing period
if (0 == self::get_cart_subscription_sign_up_fee() && self::all_cart_items_have_free_trial()) {
foreach (WC()->cart->get_fees() as $fee_index => $fee) {
WC()->cart->fees[$fee_index]->amount = 0;
WC()->cart->fees[$fee_index]->tax = 0;
}
WC()->cart->fee_total = 0;
}
WC()->cart->recurring_carts = $recurring_carts;
$total = max(0, round(WC()->cart->cart_contents_total + WC()->cart->tax_total + WC()->cart->shipping_tax_total + WC()->cart->shipping_total + WC()->cart->fee_total, WC()->cart->dp));
if (isset(WC()->cart->discount_total) && 0 !== WC()->cart->discount_total) {
// WC < 2.3, deduct deprecated after tax discount total
$total = max(0, round($total - WC()->cart->discount_total, WC()->cart->dp));
}
if (!self::charge_shipping_up_front()) {
$total = max(0, $total - WC()->cart->shipping_tax_total - WC()->cart->shipping_total);
WC()->cart->shipping_taxes = array();
WC()->cart->shipping_tax_total = 0;
WC()->cart->shipping_total = 0;
}
return apply_filters('woocommerce_subscriptions_calculated_total', $total);
}
示例9: maybe_record_subscription_payment
/**
* Records the initial payment against a subscription.
*
* This function is called when an orders status is changed to completed or processing
* for those gateways which never call @see WC_Order::payment_complete(), like the core
* WooCommerce Cheque and Bank Transfer gateways.
*
* It will also set the start date on the subscription to the time the payment is completed.
*
* @param $order_id int|WC_Order
* @param $old_order_status
* @param $new_order_status
* @since 2.0
*/
public static function maybe_record_subscription_payment($order_id, $old_order_status, $new_order_status)
{
if (wcs_order_contains_subscription($order_id)) {
$subscriptions = wcs_get_subscriptions_for_order($order_id);
$was_activated = false;
$order_completed = in_array($new_order_status, array(apply_filters('woocommerce_payment_complete_order_status', 'processing', $order_id), 'processing', 'completed')) && in_array($old_order_status, apply_filters('woocommerce_valid_order_statuses_for_payment', array('pending', 'on-hold', 'failed')));
foreach ($subscriptions as $subscription) {
// Do we need to activate a subscription?
if ($order_completed && !$subscription->has_status(wcs_get_subscription_ended_statuses()) && !$subscription->has_status('active')) {
$new_start_date_offset = current_time('timestamp', true) - $subscription->get_time('start');
// if the payment has been processed more than an hour after the order was first created, let's update the dates on the subscription to account for that, because it may have even been processed days after it was first placed
if ($new_start_date_offset > HOUR_IN_SECONDS) {
$dates = array('start' => current_time('mysql', true));
if (WC_Subscriptions_Synchroniser::subscription_contains_synced_product($subscription)) {
$trial_end = $subscription->get_time('trial_end');
$next_payment = $subscription->get_time('next_payment');
// if either there is a free trial date or a next payment date that falls before now, we need to recalculate all the sync'd dates
if ($trial_end > 0 && $trial_end < strtotime($dates['start']) || $next_payment > 0 && $next_payment < strtotime($dates['start'])) {
foreach ($subscription->get_items() as $item) {
$product_id = wcs_get_canonical_product_id($item);
if (WC_Subscriptions_Synchroniser::is_product_synced($product_id)) {
$dates['trial_end'] = WC_Subscriptions_Product::get_trial_expiration_date($product_id, $dates['start']);
$dates['next_payment'] = WC_Subscriptions_Synchroniser::calculate_first_payment_date($product_id, 'mysql', $dates['start']);
$dates['end'] = WC_Subscriptions_Product::get_expiration_date($product_id, $dates['start']);
break;
}
}
}
} else {
// No sync'ing to mess about with, just add the offset to the existing dates
foreach (array('trial_end', 'next_payment', 'end') as $date_type) {
if (0 != $subscription->get_time($date_type)) {
$dates[$date_type] = gmdate('Y-m-d H:i:s', $subscription->get_time($date_type) + $new_start_date_offset);
}
}
}
$subscription->update_dates($dates);
}
$subscription->payment_complete();
$was_activated = true;
} elseif ('failed' == $new_order_status) {
$subscription->payment_failed();
}
}
if ($was_activated) {
do_action('subscriptions_activated_for_order', $order_id);
}
}
}
示例10: calculate_next_payment_date
/**
* Takes a subscription product's ID and calculates the date on which the next payment is due.
*
* Calculation is based on $from_date if specified, otherwise it will fall back to the last
* completed payment, the subscription's start time, or the current date/time, in that order.
*
* The next payment date will occur after any free trial period and up to any expiration date.
*
* @param $order mixed A WC_Order object or the ID of the order which the subscription was purchased in.
* @param $product_id int The product/post ID of the subscription
* @param $type string (optional) The format for the Either 'mysql' or 'timestamp'.
* @param $from_date mixed A MySQL formatted date/time string from which to calculate the next payment date, or empty (default), which will use the last payment on the subscription, or today's date/time if no previous payments have been made.
* @return mixed If there is no future payment set, returns 0, otherwise it will return a date of the next payment in the form specified by $type
* @since 1.0
*/
public static function calculate_next_payment_date($order, $product_id, $type = 'mysql', $from_date = '')
{
if (!is_object($order)) {
$order = new WC_Order($order);
}
$subscription = WC_Subscriptions_Manager::get_users_subscription($order->user_id, WC_Subscriptions_Manager::get_subscription_key($order->id, $product_id));
$subscription_period = self::get_subscription_period($order, $product_id);
$subscription_interval = self::get_subscription_interval($order, $product_id);
$subscription_trial_length = self::get_subscription_trial_length($order, $product_id);
$subscription_trial_period = self::get_subscription_trial_period($order, $product_id);
$trial_end_time = !empty($subscription['trial_expiry_date']) ? $subscription['trial_expiry_date'] : WC_Subscriptions_Product::get_trial_expiration_date($product_id, $order->order_date);
$trial_end_time = strtotime($trial_end_time);
// If the subscription is not active, there is no next payment date
if ($subscription['status'] != 'active') {
$next_payment_timestamp = 0;
// If the subscription has a free trial period, and we're still in the free trial period, the next payment is due at the end of the free trial
} elseif ($subscription_trial_length > 0 && $trial_end_time > time() + 120) {
$next_payment_timestamp = $trial_end_time;
// The next payment date is {interval} billing periods from the from date
} else {
// We have a timestamp
if (!empty($from_date) && is_numeric($from_date)) {
$from_date = date('Y-m-d H:i:s', $from_date);
}
if (empty($from_date)) {
if (!empty($subscription['completed_payments'])) {
$from_date = array_pop($subscription['completed_payments']);
$add_failed_payments = true;
} else {
if (!empty($subscription['start_date'])) {
$from_date = $subscription['start_date'];
$add_failed_payments = true;
} else {
$from_date = date('Y-m-d H:i:s');
$add_failed_payments = false;
}
}
$failed_payment_count = self::get_failed_payment_count($order, $product_id);
// Maybe take into account any failed payments
if (true === $add_failed_payments && $failed_payment_count > 0) {
$failed_payment_periods = $failed_payment_count * $subscription_interval;
$from_date = date('Y-m-d H:i:s', strtotime("+ {$failed_payment_periods} {$subscription_period}", strtotime($from_date)));
}
}
$next_payment_timestamp = strtotime("+ {$subscription_interval} {$subscription_period}", strtotime($from_date));
// Make sure the next payment is in the future
while ($next_payment_timestamp < time()) {
$next_payment_timestamp = strtotime("+ {$subscription_interval} {$subscription_period}", $next_payment_timestamp);
}
}
// If the subscription has an expiry date and the next billing period comes after the expiration, return 0
if (isset($subscription['expiry_date']) && 0 != $subscription['expiry_date'] && $next_payment_timestamp > strtotime($subscription['expiry_date'])) {
$next_payment_timestamp = 0;
}
$next_payment = 'mysql' == $type && 0 != $next_payment_timestamp ? date('Y-m-d H:i:s', $next_payment_timestamp) : $next_payment_timestamp;
return apply_filters('woocommerce_subscriptions_calculated_next_payment_date', $next_payment, $order, $product_id, $type, $from_date);
}