Merge branch 'release/2.3.5'

This commit is contained in:
Remco Tolsma 2018-08-29 10:58:04 +02:00
commit 3a829316be
314 changed files with 569 additions and 288 deletions

0
assets/css/about.css Normal file → Executable file
View File

0
assets/css/admin.css Normal file → Executable file
View File

0
assets/css/checkout.css Normal file → Executable file
View File

0
assets/css/dashboard.css Normal file → Executable file
View File

0
assets/css/view-subscription.css Normal file → Executable file
View File

0
assets/css/wcs-upgrade.css Normal file → Executable file
View File

0
assets/images/add-edit-subscription-screen.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

0
assets/images/admin-change-payment-method.jpg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

0
assets/images/ajax-loader.gif Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 885 B

After

Width:  |  Height:  |  Size: 885 B

0
assets/images/ajax-loader@2x.gif Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

0
assets/images/billing-schedules-meta-box.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

0
assets/images/checkout-recurring-totals.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

0
assets/images/drip-downloadable-content.jpg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

0
assets/images/gift-subscription.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 122 KiB

0
assets/images/renewal-retry-settings.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

0
assets/images/subscribe-all-the-things.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

0
assets/images/subscription-reports.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

0
assets/images/subscription-suspended-email.jpg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

0
assets/images/subscriptions-importer-exporter.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 90 KiB

0
assets/images/view-subscription.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 250 KiB

After

Width:  |  Height:  |  Size: 250 KiB

0
assets/images/woocommerce_subscriptions_logo.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

0
assets/js/admin/admin-pointers.js Normal file → Executable file
View File

0
assets/js/admin/admin.js Normal file → Executable file
View File

0
assets/js/admin/jquery.flot.axislabels.js Normal file → Executable file
View File

0
assets/js/admin/jquery.flot.axislabels.min.js vendored Normal file → Executable file
View File

0
assets/js/admin/jquery.flot.orderBars.js Normal file → Executable file
View File

0
assets/js/admin/jquery.flot.orderBars.min.js vendored Normal file → Executable file
View File

0
assets/js/admin/jstz.js Normal file → Executable file
View File

0
assets/js/admin/jstz.min.js vendored Normal file → Executable file
View File

0
assets/js/admin/meta-boxes-coupon.js Normal file → Executable file
View File

0
assets/js/admin/meta-boxes-subscription.js Normal file → Executable file
View File

0
assets/js/admin/moment.js Normal file → Executable file
View File

0
assets/js/admin/moment.min.js vendored Normal file → Executable file
View File

0
assets/js/admin/reports.js Normal file → Executable file
View File

0
assets/js/admin/wcs-meta-boxes-order.js Normal file → Executable file
View File

0
assets/js/wcs-upgrade.js Normal file → Executable file
View File

10
changelog.txt Normal file → Executable file
View File

@ -1,5 +1,15 @@
*** WooCommerce Subscriptions Changelog ***
2018.08.27 - version 2.3.5
* Fix: Exclude customers with at least 1 subscription from the WC inactivity user cleanup query. PR#2830
* Fix: Calculate PayPal trial args from the next payment date while resubscribing before the subscription's end date. PR#2828
* Fix: Only display the 2.3 upgrade notice after plugin upgrade, not after install. PR#2869
* Tweak: Add 'woocommerce_subscriptions_can_user_renew_early' filter to allow third-parties to filter renew early eligibility. PR#2859
* Tweak: Include resubscribe data in the subscription REST API response. PR#2863
* Tweak: Improve the performance of some queries by using cached customer subscriptions instead of meta queries. PR#2856
* Tweak: Improve the performance of the query which generates the data for the Subscriptions by Date report. PR#2788
* Tweak: Give customers the option to update their subscription tokens after changing their default method. PR#2819
2018.08.10 - version 2.3.4
* New: Add filter to bypass coupon removal for recurring carts. PR#2832
* Fix: Check if subscription is payable before populating the cart with a renewal order. PR#2838

0
composer.lock generated Normal file → Executable file
View File

0
includes/abstracts/abstract-wcs-background-updater.php Normal file → Executable file
View File

View File

0
includes/abstracts/abstract-wcs-cache-manager.php Normal file → Executable file
View File

0
includes/abstracts/abstract-wcs-customer-store.php Normal file → Executable file
View File

View File

0
includes/abstracts/abstract-wcs-debug-tool.php Normal file → Executable file
View File

View File

0
includes/abstracts/abstract-wcs-hook-deprecator.php Normal file → Executable file
View File

View File

0
includes/abstracts/abstract-wcs-retry-store.php Normal file → Executable file
View File

0
includes/abstracts/abstract-wcs-scheduler.php Normal file → Executable file
View File

0
includes/admin/class-wc-subscriptions-admin.php Normal file → Executable file
View File

0
includes/admin/class-wcs-admin-meta-boxes.php Normal file → Executable file
View File

0
includes/admin/class-wcs-admin-notice.php Normal file → Executable file
View File

77
includes/admin/class-wcs-admin-post-types.php Normal file → Executable file
View File

@ -23,6 +23,19 @@ if ( class_exists( 'WCS_Admin_Post_Types' ) ) {
*/
class WCS_Admin_Post_Types {
/**
* The value to use for the 'post__in' query param when no results should be returned.
*
* We can't use an empty array, because WP returns all posts when post__in is an empty
* array. Source: https://core.trac.wordpress.org/ticket/28099
*
* This would ideally be a private CONST but visibility modifiers are only allowed for
* class constants in PHP >= 7.1.
*
* @var array
*/
private static $post__in_none = array( 0 );
/**
* Constructor
*/
@ -732,24 +745,20 @@ class WCS_Admin_Post_Types {
if ( 'shop_subscription' === $typenow ) {
// Filter the orders by the posted customer.
if ( isset( $_GET['_customer_user'] ) && $_GET['_customer_user'] > 0 ) {
$vars['meta_query'][] = array(
'key' => '_customer_user',
'value' => (int) $_GET['_customer_user'],
'compare' => '=',
);
if ( isset( $_GET['_subscriber_id'] ) && $_GET['_subscriber_id'] > 0 ) {
$subscription_ids = WCS_Customer_Store::instance()->get_users_subscription_ids( absint( $_GET['_subscriber_id'] ) );
$vars = self::set_post__in_query_var( $vars, $subscription_ids );
}
if ( isset( $_GET['_wcs_product'] ) && $_GET['_wcs_product'] > 0 ) {
$subscription_ids = wcs_get_subscriptions_for_product( $_GET['_wcs_product'] );
$subscription_ids = array_keys( $subscription_ids );
$vars = self::set_post__in_query_var( $vars, $subscription_ids );
}
if ( ! empty( $subscription_ids ) ) {
$vars['post__in'] = $subscription_ids;
} else {
// no subscriptions contain this product, but we need to pass post__in an ID that no post will have because WP returns all posts when post__in is an empty array: https://core.trac.wordpress.org/ticket/28099
$vars['post__in'] = array( 0 );
}
// If we've using the 'none' flag for the post__in query var, there's no need to apply other query filters, as we're going to return no subscriptions anyway
if ( isset( $vars['post__in'] ) && self::$post__in_none === $vars['post__in'] ) {
return $vars;
}
if ( ! empty( $_GET['_payment_method'] ) ) {
@ -779,7 +788,7 @@ class WCS_Admin_Post_Types {
if ( ! empty( $subscription_ids ) ) {
$vars['post__in'] = $subscription_ids;
} else {
$vars['post__in'] = array( 0 );
$vars['post__in'] = self::$post__in_none;
}
}
@ -816,6 +825,40 @@ class WCS_Admin_Post_Types {
return $vars;
}
/**
* Set the 'post__in' query var with a given set of post ids.
*
* There are a few special conditions for handling the post__in value. Namely:
* - if there are no matching post_ids, the value should be array( 0 ), not an empty array()
* - if there are existing IDs in post__in, we only want to retun posts with an ID in both
* the existing set and the new set
*
* While this method is public, it should not be used as it will eventually be deprecated and
* it's only made publicly available for other Subscriptions methods until Subscriptions
* requires WC 3.0, and can rely on using methods in the data store rather than a hack like
* pulling this for use outside of the admin context.
*
* @param array $query_vars
* @param array $post_ids
* @return array
*/
public static function set_post__in_query_var( $query_vars, $post_ids ) {
if ( empty( $post_ids ) ) {
// No posts for this user
$query_vars['post__in'] = self::$post__in_none;
} elseif ( ! isset( $query_vars['post__in'] ) ) {
// No other posts limitations, include all of these posts
$query_vars['post__in'] = $post_ids;
} elseif ( self::$post__in_none !== $query_vars['post__in'] ) {
// Existing post limitation, we only want to include existing IDs that are also in this new set of IDs
$intersecting_post_ids = array_intersect( $query_vars['post__in'], $post_ids );
$query_vars['post__in'] = empty( $intersecting_post_ids ) ? self::$post__in_none : $intersecting_post_ids;
}
return $query_vars;
}
/**
* Change messages when a post type is updated.
*
@ -1062,8 +1105,8 @@ class WCS_Admin_Post_Types {
$user_string = '';
$user_id = '';
if ( ! empty( $_GET['_customer_user'] ) ) {
$user_id = absint( $_GET['_customer_user'] );
if ( ! empty( $_GET['_subscriber_id'] ) ) {
$user_id = absint( $_GET['_subscriber_id'] );
$user = get_user_by( 'id', $user_id );
$user_string = sprintf(
@ -1075,7 +1118,7 @@ class WCS_Admin_Post_Types {
);
}
?>
<select class="wc-customer-search" name="_customer_user" data-placeholder="<?php esc_attr_e( 'Search for a customer&hellip;', 'woocommerce-subscriptions' ); ?>" data-allow_clear="true">
<select class="wc-customer-search" name="_subscriber_id" data-placeholder="<?php esc_attr_e( 'Search for a customer&hellip;', 'woocommerce-subscriptions' ); ?>" data-allow_clear="true">
<option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo wp_kses_post( $user_string ); ?></option>
</select>
<?php

0
includes/admin/class-wcs-admin-reports.php Normal file → Executable file
View File

0
includes/admin/class-wcs-admin-system-status.php Normal file → Executable file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

0
includes/admin/meta-boxes/views/html-retries-table.php Normal file → Executable file
View File

View File

View File

0
includes/admin/reports/class-wcs-report-dashboard.php Normal file → Executable file
View File

View File

View File

View File

View File

@ -257,47 +257,45 @@ class WC_Report_Subscription_Events_By_Date extends WC_Admin_Report {
$query = $wpdb->prepare(
"SELECT searchdate.Date as date, COUNT( DISTINCT wcsubs.ID) as count
FROM (
SELECT DATE_FORMAT(a.Date,'%%Y-%%m-%%d') as Date, 0 as cnt
SELECT DATE_FORMAT(last_thousand_days.Date,'%%Y-%%m-%%d') as Date
FROM (
SELECT DATE(%s) - INTERVAL(a.a + (10 * b.a) + (100 * c.a)) DAY as Date
SELECT DATE(%s) - INTERVAL(units.digit + (10 * tens.digit) + (100 * hundreds.digit)) DAY as Date
FROM (
SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2
SELECT 0 AS digit UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9
) as a
) as units
CROSS JOIN (
SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2
SELECT 0 AS digit UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9
) as b
) as tens
CROSS JOIN (
SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2
SELECT 0 AS digit UNION ALL SELECT 1 UNION ALL SELECT 2
UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8
UNION ALL SELECT 9
) AS c
) a
WHERE a.Date >= %s AND a.Date <= %s
) searchdate
LEFT JOIN (
{$wpdb->posts} AS wcsubs
LEFT JOIN {$wpdb->postmeta} AS wcsmeta
ON wcsubs.ID = wcsmeta.post_id AND wcsmeta.meta_key = %s
) ON DATE( wcsubs.post_date ) < searchdate.Date
AND wcsubs.post_type IN ( 'shop_subscription' )
AND wcsubs.post_status NOT IN( 'trash', 'auto-draft' )
AND (
DATE( CONVERT_TZ( wcsmeta.meta_value , '+00:00', %s ) ) >= searchdate.Date
OR wcsmeta.meta_value = 0
OR wcsmeta.meta_value IS NULL
)
GROUP BY searchdate.Date
ORDER BY searchdate.Date ASC",
) AS hundreds
) last_thousand_days
WHERE last_thousand_days.Date >= %s AND last_thousand_days.Date <= %s
) searchdate,
{$wpdb->posts} AS wcsubs,
{$wpdb->postmeta} AS wcsmeta
WHERE wcsubs.ID = wcsmeta.post_id AND wcsmeta.meta_key = '%s'
AND DATE( wcsubs.post_date ) <= searchdate.Date
AND wcsubs.post_type IN ( 'shop_subscription' )
AND wcsubs.post_status NOT IN( 'auto-draft' )
AND (
DATE( CONVERT_TZ( wcsmeta.meta_value , '+00:00', %s ) ) >= searchdate.Date
OR wcsmeta.meta_value = 0
OR wcsmeta.meta_value IS NULL
)
ORDER BY searchdate.Date ASC",
$query_end_date,
date( 'Y-m-d', $this->start_date ),
$query_end_date,

View File

View File

0
includes/admin/views/html-report-by-period.php Normal file → Executable file
View File

0
includes/admin/wcs-admin-functions.php Normal file → Executable file
View File

View File

21
includes/api/class-wc-rest-subscriptions-controller.php Normal file → Executable file
View File

@ -81,8 +81,13 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_V1_Controller {
if ( ! empty( $post->post_type ) && ! empty( $post->ID ) && 'shop_subscription' == $post->post_type ) {
$subscription = wcs_get_subscription( $post->ID );
$response->data['billing_period'] = $subscription->get_billing_period();
$response->data['billing_interval'] = $subscription->get_billing_interval();
$response->data['billing_period'] = $subscription->get_billing_period();
$response->data['billing_interval'] = $subscription->get_billing_interval();
// Send resubscribe data
$resubscribed_subscriptions = array_filter( $subscription->get_related_orders( 'ids', 'resubscribe' ), 'wcs_is_subscription' );
$response->data['resubscribed_from'] = strval( wcs_get_objects_property( $subscription, 'subscription_resubscribe' ) );
$response->data['resubscribed_subscription'] = strval( reset( $resubscribed_subscriptions ) ); // Subscriptions can only be resubscribed to once so return the first and only element.
foreach ( array( 'start', 'trial_end', 'next_payment', 'end' ) as $date_type ) {
$date_type_key = ( 'start' === $date_type ) ? 'date_created' : $date_type;
@ -447,6 +452,18 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_V1_Controller {
'type' => 'date-time',
'context' => array( 'view', 'edit' ),
),
'resubscribed_from' => array(
'description' => __( "The subscription's original subscription ID if this is a resubscribed subscription.", 'woocommerce-subscriptions' ),
'type' => 'string',
'context' => array( 'view' ),
'readonly' => true,
),
'resubscribed_subscription' => array(
'description' => __( "The subscription's resubscribed subscription ID.", 'woocommerce-subscriptions' ),
'type' => 'string',
'context' => array( 'view' ),
'readonly' => true,
),
);
$schema['properties'] += $subscriptions_schema;

View File

0
includes/api/legacy/class-wc-api-subscriptions.php Normal file → Executable file
View File

View File

View File

0
includes/class-wc-order-item-pending-switch.php Normal file → Executable file
View File

0
includes/class-wc-product-subscription-variation.php Normal file → Executable file
View File

0
includes/class-wc-product-subscription.php Normal file → Executable file
View File

0
includes/class-wc-product-variable-subscription.php Normal file → Executable file
View File

0
includes/class-wc-subscription.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-addresses.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-cart.php Normal file → Executable file
View File

View File

0
includes/class-wc-subscriptions-checkout.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-coupon.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-email.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-manager.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-order.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-product.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-renewal-order.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-switcher.php Normal file → Executable file
View File

0
includes/class-wc-subscriptions-synchroniser.php Normal file → Executable file
View File

Some files were not shown because too many files have changed in this diff Show More