From 3f6036c1be1834d12935aaac7ac7c63b17f9d44e Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Wed, 16 Feb 2022 14:41:21 +0100 Subject: [PATCH 01/87] Introduce new `$gateway->get_mode()` function. --- src/Core/Gateway.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Core/Gateway.php b/src/Core/Gateway.php index 9a4ded41..a42748a5 100644 --- a/src/Core/Gateway.php +++ b/src/Core/Gateway.php @@ -831,4 +831,13 @@ public function create_invoice( $payment ) { public function cancel_reservation( $payment ) { return false; } + + /** + * Get mode. + * + * @return string + */ + public function get_mode() { + return self::MODE_LIVE; + } } From b9dee633d9a87479e4e7f40ee46c200e450774ce Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Wed, 16 Feb 2022 14:42:11 +0100 Subject: [PATCH 02/87] No longer use '_pronamic_gateway_mode' meta in config select options. --- src/Plugin.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index a0e17950..bbc090e2 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -769,11 +769,7 @@ public static function get_config_select_options( $payment_method = null ) { $id = $post->ID; - $options[ $id ] = sprintf( - '%s (%s)', - get_the_title( $id ), - get_post_meta( $id, '_pronamic_gateway_mode', true ) - ); + $options[ $id ] = \get_the_title( $id ); } return $options; From 20417d05c8fb9181b19d3f00a918ceef459fcabf Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Wed, 16 Feb 2022 14:42:37 +0100 Subject: [PATCH 03/87] No longer complement payment mode from '_pronamic_gateway_mode' meta. --- src/Plugin.php | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index bbc090e2..56ac272c 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -915,15 +915,6 @@ public static function complement_payment( Payment $payment ) { $payment->set_version( pronamic_pay_plugin()->get_version() ); } - // Mode. - $config_id = $payment->get_config_id(); - - if ( null === $payment->get_mode() && null !== $config_id ) { - $mode = get_post_meta( $config_id, '_pronamic_gateway_mode', true ); - - $payment->set_mode( $mode ); - } - // Issuer. $issuer = $payment->get_meta( 'issuer' ); @@ -1052,6 +1043,9 @@ public static function start_payment( Payment $payment ) { return $payment; } + // Mode. + $payment->set_mode( $gateway->get_mode() ); + // Subscriptions. $subscriptions = $payment->get_subscriptions(); From d0a7eecb3d228b3652245ec4a8078c80189bcd26 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Wed, 16 Feb 2022 14:44:49 +0100 Subject: [PATCH 04/87] Remove global mode setting. --- src/Admin/AdminGatewayPostType.php | 7 ------ views/meta-box-gateway-config.php | 37 ------------------------------ 2 files changed, 44 deletions(-) diff --git a/src/Admin/AdminGatewayPostType.php b/src/Admin/AdminGatewayPostType.php index 4db581a1..1d5ca01b 100644 --- a/src/Admin/AdminGatewayPostType.php +++ b/src/Admin/AdminGatewayPostType.php @@ -429,13 +429,6 @@ public function save_post( $post_id ) { \update_post_meta( $post_id, '_pronamic_gateway_id', $gateway_id ); - // Mode. - if ( \filter_has_var( INPUT_POST, '_pronamic_gateway_mode' ) ) { - $gateway_mode = \filter_input( INPUT_POST, '_pronamic_gateway_mode', FILTER_SANITIZE_STRING ); - - \update_post_meta( $post_id, '_pronamic_gateway_mode', $gateway_mode ); - } - // Transient. \delete_transient( 'pronamic_outdated_webhook_urls' ); diff --git a/views/meta-box-gateway-config.php b/views/meta-box-gateway-config.php index 71c4e5de..a7b5bac4 100644 --- a/views/meta-box-gateway-config.php +++ b/views/meta-box-gateway-config.php @@ -126,43 +126,6 @@ function( $integration_a, $integration_b ) {

- - - - - - 'pronamic_ideal_mode', - 'name' => '_pronamic_gateway_mode', - 'class' => 'pronamic-pay-form-control', - ); - - $options = array( - array( - 'options' => array( - 'test' => __( 'Test', 'pronamic_ideal' ), - 'live' => __( 'Live', 'pronamic_ideal' ), - ), - ), - ); - - $value = get_post_meta( $config_id, '_pronamic_gateway_mode', true ); - - printf( - '', - // @codingStandardsIgnoreStart - Util::array_to_html_attributes( $attributes ), - Util::select_options_grouped( $options, $value ) - // @codingStandardsIgnoreEnd - ); - - ?> - - From aedc385606c604c9cdfa6cb4b3ba9e89d7038bf6 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Wed, 16 Feb 2022 14:51:55 +0100 Subject: [PATCH 05/87] No longer use '_pronamic_gateway_mode' in site health information. --- src/Admin/AdminHealth.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Admin/AdminHealth.php b/src/Admin/AdminHealth.php index 961e8e4d..619d5c7e 100644 --- a/src/Admin/AdminHealth.php +++ b/src/Admin/AdminHealth.php @@ -161,11 +161,7 @@ private function get_active_gateway_integrations_debug() { $integration = $this->plugin->gateway_integrations->get_integration( $gateway_id ); - $active[] = sprintf( - '%s (%s)', - null === $integration ? $gateway_id : $integration->get_name(), - \get_post_meta( $post->ID, '_pronamic_gateway_mode', true ) - ); + $active[] = ( null === $integration ) ? $gateway_id : $integration->get_name(); } $active = \array_unique( $active ); From 4a7f526686efce7d9667c8635d263c83e5bf85c8 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 09:02:51 +0100 Subject: [PATCH 06/87] Remove general mode var from gateway config. --- src/Core/GatewayConfig.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Core/GatewayConfig.php b/src/Core/GatewayConfig.php index 9d615a58..da377e75 100644 --- a/src/Core/GatewayConfig.php +++ b/src/Core/GatewayConfig.php @@ -21,10 +21,5 @@ * @since 1.0.0 */ abstract class GatewayConfig { - /** - * Mode - * - * @var string - */ - public $mode; + } From 5fa1437a14be6332c3be10247d1de9f5de6456ce Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 09:15:47 +0100 Subject: [PATCH 07/87] Allow callable for default value. --- views/meta-box-gateway-settings.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/views/meta-box-gateway-settings.php b/views/meta-box-gateway-settings.php index 88e8ac42..d8130939 100644 --- a/views/meta-box-gateway-settings.php +++ b/views/meta-box-gateway-settings.php @@ -275,6 +275,8 @@ function( $section ) { // Set default. if ( empty( $value ) && isset( $field['default'] ) ) { + $default = $field['default']; + /** * An empty value can also be an empty string, this * should not always be overwritten with the default @@ -286,7 +288,7 @@ function( $section ) { $meta = get_post_meta( $config_id, $field['meta_key'], false ); if ( empty( $meta ) ) { - $value = $field['default']; + $value = \is_callable( $default ) ? call_user_func( $default, $config_id ) : $default; } } From 91630102fbf8db7b13617df0a7e47b80c940ee7f Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 09:50:30 +0100 Subject: [PATCH 08/87] Add mode trait. --- src/AbstractGatewayIntegration.php | 7 ++++ src/Core/Gateway.php | 11 ++---- src/Core/ModeTrait.php | 56 ++++++++++++++++++++++++++++++ src/Payments/PaymentInfo.php | 37 ++------------------ 4 files changed, 67 insertions(+), 44 deletions(-) create mode 100644 src/Core/ModeTrait.php diff --git a/src/AbstractGatewayIntegration.php b/src/AbstractGatewayIntegration.php index 2fe03a71..7b77ec8c 100644 --- a/src/AbstractGatewayIntegration.php +++ b/src/AbstractGatewayIntegration.php @@ -12,6 +12,7 @@ use Pronamic\WordPress\Pay\Core\Gateway; use Pronamic\WordPress\Pay\Core\GatewayConfig; +use Pronamic\WordPress\Pay\Core\ModeTrait; /** * Title: Abstract gateway integration @@ -67,6 +68,8 @@ abstract class AbstractGatewayIntegration extends AbstractIntegration { */ protected $supports = array(); + use ModeTrait; + /** * Construct. * @@ -76,6 +79,7 @@ public function __construct( $args = array() ) { $args = wp_parse_args( $args, array( + 'mode' => 'live', 'provider' => null, 'url' => null, 'product_url' => null, @@ -87,6 +91,9 @@ public function __construct( $args = array() ) { parent::__construct( $args ); + // Mode. + $this->set_mode( $args['mode'] ); + // Provider. $this->provider = $args['provider']; diff --git a/src/Core/Gateway.php b/src/Core/Gateway.php index a42748a5..4668fed0 100644 --- a/src/Core/Gateway.php +++ b/src/Core/Gateway.php @@ -107,6 +107,8 @@ abstract class Gateway { */ public $error; + use ModeTrait; + /** * Constructs and initializes an gateway * @@ -831,13 +833,4 @@ public function create_invoice( $payment ) { public function cancel_reservation( $payment ) { return false; } - - /** - * Get mode. - * - * @return string - */ - public function get_mode() { - return self::MODE_LIVE; - } } diff --git a/src/Core/ModeTrait.php b/src/Core/ModeTrait.php new file mode 100644 index 00000000..2daebab2 --- /dev/null +++ b/src/Core/ModeTrait.php @@ -0,0 +1,56 @@ + + * @copyright 2005-2022 Pronamic + * @license GPL-3.0-or-later + * @package Pronamic\WordPress\Pay\Privacy + */ + +namespace Pronamic\WordPress\Pay\Core; + +/** + * Mode Trait + * + * @author Remco Tolsma + * @version 2.5.0 + * @since 2.5.0 + * @link https://github.com/search?q=%22trait+VersionTrait%22+language%3APHP&type=Code + */ +trait ModeTrait { + /** + * Mode. + * + * @var string + */ + private $mode = 'live'; + + /** + * Set mode. + * + * @param string $mode Mode. + * @return void + * @throws \InvalidArgumentException Throws invalid argument exception when mode is not a string or not one of the mode constants. + */ + public function set_mode( $mode ) { + if ( ! is_string( $mode ) ) { + throw new \InvalidArgumentException( 'Mode must be a string.' ); + } + + if ( ! in_array( $mode, array( Gateway::MODE_TEST, Gateway::MODE_LIVE ), true ) ) { + throw new \InvalidArgumentException( 'Invalid mode.' ); + } + + $this->mode = $mode; + } + + /** + * Get mode. + * + * @return string + */ + public function get_mode() { + return $this->mode; + } +} diff --git a/src/Payments/PaymentInfo.php b/src/Payments/PaymentInfo.php index 802fe944..8e3f0fa1 100644 --- a/src/Payments/PaymentInfo.php +++ b/src/Payments/PaymentInfo.php @@ -34,6 +34,8 @@ abstract class PaymentInfo { use \Pronamic\WordPress\Pay\Core\VersionTrait; + use \Pronamic\WordPress\Pay\Core\ModeTrait; + use \Pronamic\WordPress\Pay\Privacy\AnonymizedTrait; use \Pronamic\WordPress\Pay\Payments\PaymentInfoTrait; @@ -174,13 +176,6 @@ abstract class PaymentInfo { */ public $lines; - /** - * Mode. - * - * @var string|null - */ - private $mode; - /** * Credit card * @@ -557,34 +552,6 @@ public function get_credit_card() { return $this->credit_card; } - /** - * Set mode. - * - * @param string|null $mode Mode. - * @return void - * @throws \InvalidArgumentException Throws invalid argument exception when mode is not a string or not one of the mode constants. - */ - public function set_mode( $mode ) { - if ( ! is_string( $mode ) ) { - throw new \InvalidArgumentException( 'Mode must be a string.' ); - } - - if ( ! in_array( $mode, array( Gateway::MODE_TEST, Gateway::MODE_LIVE ), true ) ) { - throw new \InvalidArgumentException( 'Invalid mode.' ); - } - - $this->mode = $mode; - } - - /** - * Get mode. - * - * @return string|null - */ - public function get_mode() { - return $this->mode; - } - /** * Get the unique key. * From 1905e669f6b71aa13b575e9b352adbdf54258814 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 12:07:23 +0100 Subject: [PATCH 09/87] Simplify dashboard URL's, just one URL allowed. --- src/AbstractGatewayIntegration.php | 18 ++++-------------- views/meta-box-gateway-config.php | 26 +++++--------------------- 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/src/AbstractGatewayIntegration.php b/src/AbstractGatewayIntegration.php index 7b77ec8c..ff54d54d 100644 --- a/src/AbstractGatewayIntegration.php +++ b/src/AbstractGatewayIntegration.php @@ -50,7 +50,7 @@ abstract class AbstractGatewayIntegration extends AbstractIntegration { /** * Dashboard URL. * - * @var string|array + * @var string|null */ public $dashboard_url; @@ -83,7 +83,7 @@ public function __construct( $args = array() ) { 'provider' => null, 'url' => null, 'product_url' => null, - 'dashboard_url' => array(), + 'dashboard_url' => null, 'manual_url' => null, 'supports' => array(), ) @@ -138,20 +138,10 @@ public function get_settings_fields() { /** * Get dashboard URL. * - * @return array + * @return string|null */ public function get_dashboard_url() { - $url = array(); - - if ( isset( $this->dashboard_url ) ) { - if ( is_string( $this->dashboard_url ) ) { - $url = array( $this->dashboard_url ); - } elseif ( is_array( $this->dashboard_url ) ) { - $url = $this->dashboard_url; - } - } - - return $url; + return $this->dashboard_url; } /** diff --git a/views/meta-box-gateway-config.php b/views/meta-box-gateway-config.php index a7b5bac4..757046cd 100644 --- a/views/meta-box-gateway-config.php +++ b/views/meta-box-gateway-config.php @@ -60,29 +60,13 @@ function( $integration_a, $integration_b ) { } // Dashboard links. - $dashboards = $integration->get_dashboard_url(); + $dashboard_url = $integration->get_dashboard_url(); - if ( 1 === count( $dashboards ) ) { + if ( null !== $dashboard_url ) {if ( is_array( $dashboard_url ) ) {var_dump($integration );} $links[] = sprintf( - '%2$s', - esc_attr( $dashboards[0] ), - __( 'Dashboard', 'pronamic_ideal' ) - ); - } elseif ( count( $dashboards ) > 1 ) { - $dashboard_urls = array(); - - foreach ( $dashboards as $dashboard_name => $dashboard_url ) { - $dashboard_urls[] = sprintf( - '%2$s', - esc_attr( $dashboard_url ), - esc_html( ucfirst( $dashboard_name ) ) - ); - } - - $links[] = sprintf( - '%s: %s', - __( 'Dashboards', 'pronamic_ideal' ), - strtolower( implode( ', ', $dashboard_urls ) ) + '%2$s', + \esc_url( $dashboard_url ), + \esc_html__( 'Dashboard', 'pronamic_ideal' ) ); } From a28fe2a058e447a33939b5333dafe570cb331560 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 12:10:52 +0100 Subject: [PATCH 10/87] Remove title attribute and use correct escape functions. --- views/meta-box-gateway-config.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/views/meta-box-gateway-config.php b/views/meta-box-gateway-config.php index 757046cd..4ef451d7 100644 --- a/views/meta-box-gateway-config.php +++ b/views/meta-box-gateway-config.php @@ -73,9 +73,9 @@ function( $integration_a, $integration_b ) { // Product link. if ( null !== $integration->get_product_url() ) { $links[] = sprintf( - '%2$s', - $integration->get_product_url(), - __( 'Product information', 'pronamic_ideal' ) + '%s', + \esc_url( $integration->get_product_url() ), + \esc_html__( 'Product information', 'pronamic_ideal' ) ); } @@ -84,9 +84,8 @@ function( $integration_a, $integration_b ) { if ( null !== $manual_url ) { $links[] = sprintf( - '%s', + '%s', \esc_url( $plugin->tracking_module->get_tracking_url( $manual_url ) ), - \esc_attr__( 'Manual', 'pronamic_ideal' ), \esc_html__( 'Manual', 'pronamic_ideal' ) ); } From 00f610ff2c70802f9825e10a32c7e5c977afd24b Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:28:07 +0100 Subject: [PATCH 11/87] Remove `$gateway->set_error()`, no longer used. --- src/Core/Gateway.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Core/Gateway.php b/src/Core/Gateway.php index 4668fed0..ab415520 100644 --- a/src/Core/Gateway.php +++ b/src/Core/Gateway.php @@ -158,16 +158,6 @@ public function has_error() { return null !== $this->error; } - /** - * Set error - * - * @param WP_Error|null $error WordPress error object or null. - * @return void - */ - public function set_error( WP_Error $error = null ) { - $this->error = $error; - } - /** * Set the method. * From e850cb2f4cafd26040eabbbd30512f17e3026f06 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:29:22 +0100 Subject: [PATCH 12/87] No longer need to check for gateway error, we will use exceptions only. --- src/Plugin.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index 56ac272c..3cf7268a 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -1072,21 +1072,6 @@ public static function start_payment( Payment $payment ) { // Start payment at the gateway. try { $gateway->start( $payment ); - - // Add gateway errors as payment notes. - $error = $gateway->get_error(); - - if ( $error instanceof \WP_Error ) { - $message = $error->get_error_message(); - $code = $error->get_error_code(); - - if ( ! \is_int( $code ) ) { - $message = sprintf( '%s: %s', $code, $message ); - $code = 0; - } - - throw new \Exception( $message, $code ); - } } catch ( \Exception $error ) { $message = $error->getMessage(); From 396e80219b68b7fa8f053f9471ebc45f5086000e Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:30:36 +0100 Subject: [PATCH 13/87] No longer need to check for gateway error, will use exceptions only. --- src/Subscriptions/SubscriptionsModule.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Subscriptions/SubscriptionsModule.php b/src/Subscriptions/SubscriptionsModule.php index 7f809a0d..0c49966e 100644 --- a/src/Subscriptions/SubscriptionsModule.php +++ b/src/Subscriptions/SubscriptionsModule.php @@ -515,14 +515,6 @@ private function handle_subscription_mandate( Subscription $subscription ) { exit; } - $error = $gateway->get_error(); - - if ( $error instanceof WP_Error ) { - Plugin::render_errors( $error ); - - exit; - } - $gateway->redirect( $payment ); return; From 874e0ef92e94a6617b5924f0e16a9c745eda836a Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:30:58 +0100 Subject: [PATCH 14/87] No longer need to check for gateway error, will use exceptions only. --- src/Subscriptions/SubscriptionsModule.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Subscriptions/SubscriptionsModule.php b/src/Subscriptions/SubscriptionsModule.php index 0c49966e..a421990f 100644 --- a/src/Subscriptions/SubscriptionsModule.php +++ b/src/Subscriptions/SubscriptionsModule.php @@ -395,14 +395,6 @@ private function handle_subscription_renew( Subscription $subscription ) { exit; } - $error = $gateway->get_error(); - - if ( $error instanceof WP_Error ) { - Plugin::render_errors( $error ); - - exit; - } - // Redirect. try { $gateway->redirect( $payment ); From 0d52ed6813891d063de01a632fe84b684dc7d416 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:35:15 +0100 Subject: [PATCH 15/87] No longer check for gateway error, step towards exceptions only. --- views/meta-box-gateway-test.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/views/meta-box-gateway-test.php b/views/meta-box-gateway-test.php index 19b9201e..a4fa1952 100644 --- a/views/meta-box-gateway-test.php +++ b/views/meta-box-gateway-test.php @@ -54,10 +54,6 @@ } } -if ( $gateway->has_error() ) { - $pronamic_ideal_errors[] = $gateway->get_error(); -} - require Plugin::$dirname . '/views/errors.php'; $currency = Currency::get_instance( 'EUR' ); From d196e6316ca9540157b758331b860bcadb038526 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:35:49 +0100 Subject: [PATCH 16/87] Remove `$gateway->has_error()`, no longer used. --- src/Core/Gateway.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Core/Gateway.php b/src/Core/Gateway.php index ab415520..13be181b 100644 --- a/src/Core/Gateway.php +++ b/src/Core/Gateway.php @@ -149,15 +149,6 @@ public function get_error() { return $this->error; } - /** - * Has error - * - * @return boolean - */ - public function has_error() { - return null !== $this->error; - } - /** * Set the method. * From d8c83fabdb1a4d63eb8e47a05e5a92f97e31efef Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:46:04 +0100 Subject: [PATCH 17/87] No longer check on gateway error, requires exception handling. --- src/Plugin.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index 3cf7268a..46a8c017 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -522,13 +522,7 @@ public function maybe_redirect() { if ( $gateway->is_html_form() ) { $gateway->start( $payment ); - $error = $gateway->get_error(); - - if ( $error instanceof WP_Error ) { - self::render_errors( $error ); - } else { - $gateway->redirect( $payment ); - } + $gateway->redirect( $payment ); } } From ecc2ebd6bdbec7f5eca916c75561b9c6da60571c Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:48:37 +0100 Subject: [PATCH 18/87] No longer check on gateway error, instead catch exceptions for payment note. --- src/Plugin.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index 46a8c017..a9347dcf 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -369,19 +369,24 @@ public static function update_payment( $payment = null, $can_redirect = true ) { } // Update status. - $gateway->update_status( $payment ); + try { + $gateway->update_status( $payment ); - // Add gateway errors as payment notes. - $error = $gateway->get_error(); + // Update payment in data store. + $payment->save(); + } catch ( \Exception $error ) { + $message = $error->getMessage(); + + // Maybe include error code in message. + $code = $error->getCode(); - if ( $error instanceof WP_Error ) { - foreach ( $error->get_error_codes() as $code ) { - $payment->add_note( sprintf( '%s: %s', $code, $error->get_error_message( $code ) ) ); + if ( $code > 0 ) { + $message = \sprintf( '%s: %s', $code, $message ); } - } - // Update payment in data store. - $payment->save(); + // Add note. + $payment->add_note( $message ); + } // Maybe redirect. if ( ! $can_redirect ) { From 930353dd222b09eda003741f2eeb33006133f699 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:50:21 +0100 Subject: [PATCH 19/87] Remove error from gateway, no longer used. --- src/Core/Gateway.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/Core/Gateway.php b/src/Core/Gateway.php index 13be181b..16329609 100644 --- a/src/Core/Gateway.php +++ b/src/Core/Gateway.php @@ -100,13 +100,6 @@ abstract class Gateway { */ protected $supports; - /** - * Error - * - * @var WP_Error|null - */ - public $error; - use ModeTrait; /** @@ -140,15 +133,6 @@ public function supports( $feature ) { return in_array( $feature, $this->supports, true ); } - /** - * Get the error - * - * @return WP_Error|null - */ - public function get_error() { - return $this->error; - } - /** * Set the method. * From fa8e6977f1ebfc2bd68733eb89de8882d917c754 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 14:08:12 +0100 Subject: [PATCH 20/87] Dashboard URL update. --- src/Admin/AdminGatewayPostType.php | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/src/Admin/AdminGatewayPostType.php b/src/Admin/AdminGatewayPostType.php index 1d5ca01b..44f3618f 100644 --- a/src/Admin/AdminGatewayPostType.php +++ b/src/Admin/AdminGatewayPostType.php @@ -177,35 +177,15 @@ public function custom_columns( $column, $post_id ) { break; case 'pronamic_gateway_dashboard': if ( isset( $integration ) ) { - $urls = $integration->get_dashboard_url(); + $url = $integration->get_dashboard_url(); - // Output. - $content = array(); - - foreach ( $urls as $name => $url ) { - if ( empty( $name ) ) { - $name = __( 'Dashboard', 'pronamic_ideal' ); - } - - $content[] = sprintf( + if ( null !== $url ) { + \printf( '%s', - esc_attr( $url ), - esc_html( ucfirst( strval( $name ) ) ) + esc_url( $url ), + esc_html__( 'Dashboard', 'pronamic_ideal' ) ); } - - echo wp_kses( - implode( - ' | ', - $content - ), - array( - 'a' => array( - 'href' => array(), - 'target' => array(), - ), - ) - ); } break; From 2ac4833c95b3f4e5963f9e53155bc1983033ba58 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Thu, 17 Feb 2022 17:06:08 +0100 Subject: [PATCH 21/87] Remove gateway configuration. --- src/Core/Gateway.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Core/Gateway.php b/src/Core/Gateway.php index 16329609..2d7fc871 100644 --- a/src/Core/Gateway.php +++ b/src/Core/Gateway.php @@ -56,13 +56,6 @@ abstract class Gateway { */ const MODE_LIVE = 'live'; - /** - * Config - * - * @var GatewayConfig - */ - protected $config; - /** * The method of this gateway * @@ -107,9 +100,7 @@ abstract class Gateway { * * @param GatewayConfig $config Gateway configuration object. */ - public function __construct( GatewayConfig $config ) { - $this->config = $config; - + public function __construct( GatewayConfig $config = null ) { /** * Supported features. * @@ -188,7 +179,7 @@ public function get_transient_issuers() { $issuers = null; // Transient name. - $transient = 'pronamic_pay_issuers_' . md5( serialize( $this->config ) ); + $transient = 'pronamic_pay_issuers_' . md5( serialize( $this ) ); $result = get_transient( $transient ); @@ -215,7 +206,7 @@ public function get_transient_credit_card_issuers() { $issuers = null; // Transient name. - $transient = 'pronamic_pay_credit_card_issuers_' . md5( serialize( $this->config ) ); + $transient = 'pronamic_pay_credit_card_issuers_' . md5( serialize( $this ) ); $result = get_transient( $transient ); @@ -274,7 +265,7 @@ public function get_available_payment_methods() { */ public function get_transient_available_payment_methods( $update_active_methods = true ) { // Transient name. - $transient = 'pronamic_gateway_payment_methods_' . md5( serialize( $this->config ) ); + $transient = 'pronamic_gateway_payment_methods_' . md5( serialize( $this ) ); $methods = get_transient( $transient ); From 4a405bf440ef7b4bb50742a2b634628be410da27 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Fri, 18 Feb 2022 10:53:55 +0100 Subject: [PATCH 22/87] Update composer.json --- composer.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index d7f6d33b..5980ea51 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,12 @@ ] }, "config": { - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "bamarni/composer-bin-plugin": true, + "roots/wordpress-core-installer": true + } }, "repositories": [ { @@ -46,7 +51,6 @@ "ext-dom": "*", "ext-libxml": "*", "ext-simplexml": "*", - "composer/installers": "^1.7", "pronamic/wp-datetime": "^2.0", "pronamic/wp-html": "^2.0", "pronamic/wp-http": "^1.0", @@ -57,6 +61,7 @@ "woocommerce/action-scheduler": "^3.0" }, "require-dev": { + "automattic/wordbless": "^0.3.1", "bamarni/composer-bin-plugin": "^1.4", "overtrue/phplint": "^2.2", "php-coveralls/php-coveralls": "^2.4", From ea2407518e68d686c9972fd2b10e345e1cfafd29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Tue, 22 Feb 2022 09:17:22 +0100 Subject: [PATCH 23/87] Fix "Notice: Undefined variable: error". --- src/Plugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin.php b/src/Plugin.php index a9347dcf..32540f8f 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -1097,7 +1097,7 @@ public static function start_payment( Payment $payment ) { } // Throw/rethrow exception. - if ( $error instanceof \Exception ) { + if ( isset( $error ) && $error instanceof \Exception ) { throw $error; } From b3d8a403b53bbf064c9bd4a9c32a2ffbae72b8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Tue, 22 Feb 2022 10:24:34 +0100 Subject: [PATCH 24/87] Remove debug code. --- composer.json | 3 ++- docs/hooks.md | 10 +++++----- views/meta-box-gateway-config.php | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 5980ea51..631b8d4d 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,8 @@ "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, "bamarni/composer-bin-plugin": true, - "roots/wordpress-core-installer": true + "roots/wordpress-core-installer": true, + "composer/installers": true } }, "repositories": [ diff --git a/docs/hooks.md b/docs/hooks.md index 6b3289ef..8c615633 100644 --- a/docs/hooks.md +++ b/docs/hooks.md @@ -368,7 +368,7 @@ Argument | Type | Description `$should_redirect` | `bool` | Flag to indicate if redirect is allowed on handling payment return. `$payment` | `\Pronamic\WordPress\Pay\Payments\Payment` | Payment. -Source: [src/Plugin.php](../src/Plugin.php), [line 457](../src/Plugin.php#L457-L463) +Source: [src/Plugin.php](../src/Plugin.php), [line 462](../src/Plugin.php#L462-L468) ### `pronamic_pay_gateways` @@ -380,7 +380,7 @@ Argument | Type | Description -------- | ---- | ----------- `$gateways` | `\Pronamic\WordPress\Pay\AbstractGatewayIntegration[]` | Gateway integrations. -Source: [src/Plugin.php](../src/Plugin.php), [line 623](../src/Plugin.php#L623-L628) +Source: [src/Plugin.php](../src/Plugin.php), [line 622](../src/Plugin.php#L622-L627) ### `pronamic_pay_plugin_integrations` @@ -392,7 +392,7 @@ Argument | Type | Description -------- | ---- | ----------- `$plugin_integrations` | `\Pronamic\WordPress\Pay\AbstractPluginIntegration[]` | Plugin integrations. -Source: [src/Plugin.php](../src/Plugin.php), [line 638](../src/Plugin.php#L638-L643) +Source: [src/Plugin.php](../src/Plugin.php), [line 637](../src/Plugin.php#L637-L642) ### `pronamic_payment_gateway_configuration_id` @@ -405,7 +405,7 @@ Argument | Type | Description `$config_id` | `null\|int` | Gateway configuration ID. `$payment` | `\Pronamic\WordPress\Pay\Payments\Payment` | Payment. -Source: [src/Plugin.php](../src/Plugin.php), [line 1033](../src/Plugin.php#L1033-L1039) +Source: [src/Plugin.php](../src/Plugin.php), [line 1019](../src/Plugin.php#L1019-L1025) ### `pronamic_payment_redirect_url_{$source}` @@ -418,7 +418,7 @@ Argument | Type | Description `$url` | `null\|string` | Redirect URL. `$payment` | `\Pronamic\WordPress\Pay\Payments\Payment` | Payment. -Source: [src/Plugin.php](../src/Plugin.php), [line 1233](../src/Plugin.php#L1233-L1239) +Source: [src/Plugin.php](../src/Plugin.php), [line 1207](../src/Plugin.php#L1207-L1213) ### `pronamic_gateway_configuration_display_value` diff --git a/views/meta-box-gateway-config.php b/views/meta-box-gateway-config.php index 4ef451d7..44fcd45b 100644 --- a/views/meta-box-gateway-config.php +++ b/views/meta-box-gateway-config.php @@ -62,7 +62,7 @@ function( $integration_a, $integration_b ) { // Dashboard links. $dashboard_url = $integration->get_dashboard_url(); - if ( null !== $dashboard_url ) {if ( is_array( $dashboard_url ) ) {var_dump($integration );} + if ( null !== $dashboard_url ) { $links[] = sprintf( '%2$s', \esc_url( $dashboard_url ), From 7117045fe5aea93de00696bbf0e23b41c549109f Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 28 Feb 2022 15:52:59 +0100 Subject: [PATCH 25/87] Simplify exception handling. --- src/Plugin.php | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index 32540f8f..8aee716d 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -1071,11 +1071,11 @@ public static function start_payment( Payment $payment ) { // Start payment at the gateway. try { $gateway->start( $payment ); - } catch ( \Exception $error ) { - $message = $error->getMessage(); + } catch ( \Exception $exception ) { + $message = $exception->getMessage(); // Maybe include error code in message. - $code = $error->getCode(); + $code = $exception->getCode(); if ( $code > 0 ) { $message = \sprintf( '%s: %s', $code, $message ); @@ -1086,21 +1086,19 @@ public static function start_payment( Payment $payment ) { // Set payment status. $payment->set_status( PaymentStatus::FAILURE ); - } - // Save payment. - $payment->save(); + // Rethrow. + throw $exception; + } finally { + // Save payment. + $payment->save(); + } // Schedule payment status check. if ( $gateway->supports( 'payment_status_request' ) ) { StatusChecker::schedule_event( $payment ); } - // Throw/rethrow exception. - if ( isset( $error ) && $error instanceof \Exception ) { - throw $error; - } - return $payment; } From fce326aa450054ed27656e0a4d27203825f8025b Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 28 Feb 2022 15:54:06 +0100 Subject: [PATCH 26/87] Obvious. --- src/Plugin.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Plugin.php b/src/Plugin.php index 8aee716d..b8d236d1 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -1081,16 +1081,12 @@ public static function start_payment( Payment $payment ) { $message = \sprintf( '%s: %s', $code, $message ); } - // Add note. $payment->add_note( $message ); - // Set payment status. $payment->set_status( PaymentStatus::FAILURE ); - // Rethrow. throw $exception; } finally { - // Save payment. $payment->save(); } From b7cb9a10682937087f22844fc872d3f3220c08c5 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:04:22 +0100 Subject: [PATCH 27/87] Catch exception, no longer use `errors.php` from plugin repo. --- views/meta-box-gateway-test.php | 44 ++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/views/meta-box-gateway-test.php b/views/meta-box-gateway-test.php index a4fa1952..819ae984 100644 --- a/views/meta-box-gateway-test.php +++ b/views/meta-box-gateway-test.php @@ -36,26 +36,42 @@ $inputs = array(); -foreach ( $payment_methods as $payment_method => $method_name ) { - if ( ! \is_string( $payment_method ) ) { - $payment_method = null; - } +try { + foreach ( $payment_methods as $payment_method => $method_name ) { + if ( ! \is_string( $payment_method ) ) { + $payment_method = null; + } - $gateway->set_payment_method( $payment_method ); + $gateway->set_payment_method( $payment_method ); - // Payment method input HTML. - $html = $gateway->get_input_html(); + // Payment method input HTML. + $html = $gateway->get_input_html(); - if ( ! empty( $html ) ) { - $inputs[ $payment_method ] = array( - 'label' => $method_name, - 'html' => $html, - ); + if ( ! empty( $html ) ) { + $inputs[ $payment_method ] = array( + 'label' => $method_name, + 'html' => $html, + ); + } } +} catch ( \Exception $exception ) { + ?> +
+
+
+
getMessage() ); ?>
+ + getCode() ) : ?> + +
+
getCode() ); ?>
+ + +
+
+ From 6f29d4fb5b2f533753f67e9f1fc54ea2728ab1e4 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:07:33 +0100 Subject: [PATCH 28/87] No longer use global `$pronamic_ideal_errors`. --- views/meta-box-gateway-test.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/views/meta-box-gateway-test.php b/views/meta-box-gateway-test.php index 819ae984..6ebdba99 100644 --- a/views/meta-box-gateway-test.php +++ b/views/meta-box-gateway-test.php @@ -6,8 +6,7 @@ * @copyright 2005-2022 Pronamic * @license GPL-3.0-or-later * @package Pronamic\WordPress\Pay - * @var \WP_Post $post WordPress post. - * @var array $pronamic_ideal_errors Pronamic IDEAL errors. + * @var \WP_Post $post WordPress post. */ use Pronamic\WordPress\Money\Currency; @@ -16,8 +15,6 @@ use Pronamic\WordPress\Pay\Gateways\IDealBasic\Gateway as IDealBasic_Gateway; use Pronamic\WordPress\Pay\Plugin; -global $pronamic_ideal_errors; - $gateway = Plugin::get_gateway( $post->ID ); if ( null === $gateway ) { From 3dcff397d36fb11bb4d737da174c8609b12cc5e9 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 28 Feb 2022 16:08:45 +0100 Subject: [PATCH 29/87] Remove unused use statements. --- views/meta-box-gateway-test.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/views/meta-box-gateway-test.php b/views/meta-box-gateway-test.php index 6ebdba99..557848ef 100644 --- a/views/meta-box-gateway-test.php +++ b/views/meta-box-gateway-test.php @@ -11,8 +11,6 @@ use Pronamic\WordPress\Money\Currency; use Pronamic\WordPress\Pay\Core\PaymentMethods; -use Pronamic\WordPress\Pay\Gateways\IDealAdvancedV3\Gateway as IDealAdvancedV3_Gateway; -use Pronamic\WordPress\Pay\Gateways\IDealBasic\Gateway as IDealBasic_Gateway; use Pronamic\WordPress\Pay\Plugin; $gateway = Plugin::get_gateway( $post->ID ); From c3e836b0e40adf9ff1c4f11855c9c07f8bddc4ac Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Tue, 1 Mar 2022 10:02:51 +0100 Subject: [PATCH 30/87] Also display pay redirect URL #57. --- views/meta-box-payment-info.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/views/meta-box-payment-info.php b/views/meta-box-payment-info.php index f8774597..efa428e3 100644 --- a/views/meta-box-payment-info.php +++ b/views/meta-box-payment-info.php @@ -897,6 +897,24 @@ ?> + + + + + + get_pay_redirect_url(); + + printf( + '%s', + esc_attr( $url ), + esc_html( $url ) + ); + + ?> + + @@ -917,7 +935,7 @@ - + Date: Wed, 2 Mar 2022 10:52:39 +0100 Subject: [PATCH 31/87] Fix typo in subscription end date post meta key. --- src/Subscriptions/SubscriptionsDataStoreCPT.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionsDataStoreCPT.php b/src/Subscriptions/SubscriptionsDataStoreCPT.php index e639137d..3117334f 100644 --- a/src/Subscriptions/SubscriptionsDataStoreCPT.php +++ b/src/Subscriptions/SubscriptionsDataStoreCPT.php @@ -670,7 +670,7 @@ private function update_post_meta( $subscription ) { $this->update_meta( $id, 'source', $subscription->source ); $this->update_meta( $id, 'source_id', $subscription->source_id ); $this->update_meta( $id, 'email', ( null === $customer ? null : $customer->get_email() ) ); - $this->update_meta( $id, 'end_payment', $subscription->get_end_date() ); + $this->update_meta( $id, 'end_date', $subscription->get_end_date() ); $this->update_meta( $id, 'next_payment', $subscription->get_next_payment_date() ); $this->update_meta( $id, 'next_payment_delivery_date', $subscription->get_next_payment_delivery_date() ); $this->update_meta( $id, 'version', $subscription->get_version() ); From e82565cebb0c892e58f2a38ee4364f9df4a01ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Wed, 9 Mar 2022 15:44:49 +0100 Subject: [PATCH 32/87] Columns with transaction ID and customer name are not sortable (resolves #58). --- src/Admin/AdminPaymentPostType.php | 45 ++----------------------- src/Admin/AdminSubscriptionPostType.php | 5 +-- 2 files changed, 3 insertions(+), 47 deletions(-) diff --git a/src/Admin/AdminPaymentPostType.php b/src/Admin/AdminPaymentPostType.php index 1313ba2a..961bfc39 100644 --- a/src/Admin/AdminPaymentPostType.php +++ b/src/Admin/AdminPaymentPostType.php @@ -15,7 +15,6 @@ use Pronamic\WordPress\Pay\Payments\PaymentPostType; use Pronamic\WordPress\Pay\Plugin; use WP_Post; -use WP_Query; /** * WordPress admin payment post type @@ -71,8 +70,6 @@ public function __construct( $plugin ) { add_filter( 'post_row_actions', array( $this, 'post_row_actions' ), 10, 2 ); - add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) ); - add_filter( 'default_hidden_columns', array( $this, 'default_hidden_columns' ) ); add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) ); @@ -272,42 +269,6 @@ public function admin_notices() { } } - /** - * Pre get posts. - * - * @param WP_Query $query WordPress query. - * @return void - */ - public function pre_get_posts( $query ) { - /** - * The `WP_Query::get` function can return different variable type. - * For now this function can only handle one specific string orderby. - * - * @link https://developer.wordpress.org/reference/classes/wp_query/get/ - * @link https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters - * @link https://github.com/WordPress/WordPress/blob/5.2/wp-includes/class-wp-query.php#L1697-L1713 - */ - $orderby = $query->get( 'orderby' ); - - if ( ! is_string( $orderby ) ) { - return; - } - - $map = array( - 'pronamic_payment_customer' => '_pronamic_payment_customer_name', - 'pronamic_payment_transaction' => '_pronamic_payment_transaction_id', - ); - - if ( ! isset( $map[ $orderby ] ) ) { - return; - } - - $meta_key = $map[ $orderby ]; - - $query->set( 'meta_key', $meta_key ); - $query->set( 'orderby', 'meta_value' ); - } - /** * Columns. * @@ -360,10 +321,8 @@ public function default_hidden_columns( $hidden ) { * @return array */ public function sortable_columns( $sortable_columns ) { - $sortable_columns['pronamic_payment_title'] = 'ID'; - $sortable_columns['pronamic_payment_transaction'] = 'pronamic_payment_transaction'; - $sortable_columns['pronamic_payment_customer'] = 'pronamic_payment_customer'; - $sortable_columns['pronamic_payment_date'] = 'date'; + $sortable_columns['pronamic_payment_title'] = 'ID'; + $sortable_columns['pronamic_payment_date'] = 'date'; return $sortable_columns; } diff --git a/src/Admin/AdminSubscriptionPostType.php b/src/Admin/AdminSubscriptionPostType.php index ec6f9682..0d8e47ea 100644 --- a/src/Admin/AdminSubscriptionPostType.php +++ b/src/Admin/AdminSubscriptionPostType.php @@ -14,9 +14,8 @@ use Pronamic\WordPress\Pay\Core\PaymentMethods; use Pronamic\WordPress\Pay\Plugin; use Pronamic\WordPress\Pay\Subscriptions\SubscriptionPeriod; -use Pronamic\WordPress\Pay\Subscriptions\SubscriptionStatus; -use Pronamic\WordPress\Pay\Util; use Pronamic\WordPress\Pay\Subscriptions\SubscriptionPostType; +use Pronamic\WordPress\Pay\Util; use WP_Post; use WP_Query; @@ -252,7 +251,6 @@ public function pre_get_posts( $query ) { } $map = array( - 'pronamic_subscription_customer' => '_pronamic_subscription_customer_name', 'pronamic_subscription_next_payment' => '_pronamic_subscription_next_payment', ); @@ -300,7 +298,6 @@ public function columns( $columns ) { */ public function sortable_columns( $sortable_columns ) { $sortable_columns['pronamic_subscription_title'] = 'ID'; - $sortable_columns['pronamic_subscription_customer'] = 'pronamic_subscription_customer_name'; $sortable_columns['pronamic_subscription_next_payment'] = 'pronamic_subscription_next_payment'; $sortable_columns['pronamic_subscription_date'] = 'date'; From a2d9047652f07219eb8cbe37a20bafca32fc255a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Thu, 10 Mar 2022 11:39:18 +0100 Subject: [PATCH 33/87] Use source `subscription_payment_method_change` for subscription payment method changes. --- src/Subscriptions/SubscriptionsModule.php | 36 ++++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Subscriptions/SubscriptionsModule.php b/src/Subscriptions/SubscriptionsModule.php index a421990f..32a4ee15 100644 --- a/src/Subscriptions/SubscriptionsModule.php +++ b/src/Subscriptions/SubscriptionsModule.php @@ -10,20 +10,14 @@ namespace Pronamic\WordPress\Pay\Subscriptions; -use DateInterval; -use Pronamic\WordPress\DateTime\DateTime; use Pronamic\WordPress\DateTime\DateTimeImmutable; -use Pronamic\WordPress\DateTime\DateTimeZone; use Pronamic\WordPress\Money\Money; use Pronamic\WordPress\Pay\Core\PaymentMethods; use Pronamic\WordPress\Pay\Core\Server; -use Pronamic\WordPress\Pay\Payments\PaymentStatus; use Pronamic\WordPress\Pay\Core\Util; use Pronamic\WordPress\Pay\Payments\Payment; +use Pronamic\WordPress\Pay\Payments\PaymentStatus; use Pronamic\WordPress\Pay\Plugin; -use WP_CLI; -use WP_Error; -use WP_Query; /** * Title: Subscriptions module @@ -74,6 +68,10 @@ public function __construct( Plugin $plugin ) { \add_action( 'pronamic_pay_pre_create_subscription', array( SubscriptionHelper::class, 'complement_subscription' ), 10, 1 ); \add_action( 'pronamic_pay_pre_create_payment', array( $this, 'complement_subscription_by_payment' ), 10, 1 ); + // Payment source filters. + \add_filter( 'pronamic_payment_source_text_subscription_payment_method_change', array( $this, 'source_text_subscription_payment_method_change' ) ); + \add_filter( 'pronamic_payment_source_description_subscription_payment_method_change', array( $this, 'source_description_subscription_payment_method_change' ) ); + // Listen to payment status changes so we can update related subscriptions. \add_action( 'pronamic_payment_status_update', array( $this, 'payment_status_update' ) ); @@ -458,6 +456,10 @@ private function handle_subscription_mandate( Subscription $subscription ) { try { $payment = $subscription->new_payment(); + // Set source. + $payment->set_source( 'subscription_payment_method_change' ); + $payment->set_source_id( null ); + // Set payment method. $payment_method = \filter_input( \INPUT_POST, 'pronamic_pay_subscription_payment_method', \FILTER_SANITIZE_STRING ); @@ -714,4 +716,24 @@ public function rest_api_subscription_phase( \WP_REST_Request $request ) { return $phase; } + + /** + * Source text filter. + * + * @param string $text The source text to filter. + * @return string + */ + public function source_text_subscription_payment_method_change( $text ) { + return __( 'Subscription payment method change', 'pronamic_ideal' ); + } + + /** + * Source description filter. + * + * @param string $text The source text to filter. + * @return string + */ + public function source_description_subscription_payment_method_change( $text ) { + return __( 'subscription payment method change', 'pronamic_ideal' ); + } } From 01086c3caf4518d0e609e7d43c7b1d22ee090187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Tue, 15 Mar 2022 12:13:24 +0100 Subject: [PATCH 34/87] Update default error message. --- src/Plugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plugin.php b/src/Plugin.php index b8d236d1..d94c6dde 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -716,7 +716,7 @@ public function datetime_format( $format ) { * @return string */ public static function get_default_error_message() { - return __( 'Something went wrong with the payment. Please try again later or pay another way.', 'pronamic_ideal' ); + return __( 'Something went wrong with the payment. Please try again or pay another way.', 'pronamic_ideal' ); } /** From e1f9fdf85b4d97828c9e4af03a389004eb4a7f51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 10:58:18 +0100 Subject: [PATCH 35/87] Add menu badge for subscriptions 'On hold' (pronamic/wp-pronamic-pay#315). --- src/Admin/AdminModule.php | 87 ++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 15 deletions(-) diff --git a/src/Admin/AdminModule.php b/src/Admin/AdminModule.php index aa262482..6e44b87f 100644 --- a/src/Admin/AdminModule.php +++ b/src/Admin/AdminModule.php @@ -907,34 +907,81 @@ private function get_menu_icon_url() { * @return void */ public function admin_menu() { - // @link https://github.com/woothemes/woocommerce/blob/2.3.13/includes/admin/class-wc-admin-menus.php#L145 + /** + * Badges. + * + * @link https://github.com/woothemes/woocommerce/blob/2.3.13/includes/admin/class-wc-admin-menus.php#L145 + */ $counts = wp_count_posts( 'pronamic_payment' ); - $badge = ''; + $payments_pending_count = \property_exists( $counts, 'payment_pending' ) ? $counts->payment_pending : 0; - if ( isset( $counts->payment_pending ) && $counts->payment_pending > 0 ) { - $badge = sprintf( - ' %1$s', - $counts->payment_pending, - sprintf( - /* translators: %d: pending payments count */ - \_n( '%d payment pending', '%d payments pending', $counts->payment_pending, 'pronamic_ideal' ), - $counts->payment_pending - ) + $counts = wp_count_posts( 'pronamic_pay_subscr' ); + + $subscriptions_on_hold_count = \property_exists( $counts, 'subscr_on_hold' ) ? $counts->subscr_on_hold : 0; + + $badges = array( + 'pay' => array( + 'title' => array(), + 'count' => 0, + 'html' => '', + ), + 'payments' => array( + 'title' => \sprintf( + /* translators: %d: payments pending count */ + \_n( '%d payment pending', '%d payments pending', $payments_pending_count, 'pronamic_ideal' ), + $payments_pending_count + ), + 'count' => $payments_pending_count, + 'html' => '', + ), + 'subscriptions' => array( + 'title' => \sprintf( + /* translators: %d: subscriptions on hold count */ + \_n( '%d subscription on hold', '%d subscriptions on hold', $subscriptions_on_hold_count, 'pronamic_ideal' ), + $subscriptions_on_hold_count + ), + 'count' => $subscriptions_on_hold_count, + 'html' => '', + ), + ); + + foreach ( $badges as &$badge ) { + $count = $badge['count']; + + if ( 0 === $count ) { + continue; + } + + $title = \array_key_exists( 'title', $badge ) && \is_string( $badge['title'] ) ? $badge['title'] : ''; + + $badge['html'] = \sprintf( + ' %1$d', + $count, + $title ); + + // Pay badge. + $badges['pay']['count'] += $count; + + if ( ! empty( $title ) ) { + $badges['pay']['title'][] = $title; + } } - // Submenu pages. + /** + * Submenu pages. + */ $submenu_pages = array( array( 'page_title' => __( 'Payments', 'pronamic_ideal' ), - 'menu_title' => __( 'Payments', 'pronamic_ideal' ) . $badge, + 'menu_title' => __( 'Payments', 'pronamic_ideal' ) . $badges['payments']['html'], 'capability' => 'edit_payments', 'menu_slug' => 'edit.php?post_type=pronamic_payment', ), array( 'page_title' => __( 'Subscriptions', 'pronamic_ideal' ), - 'menu_title' => __( 'Subscriptions', 'pronamic_ideal' ), + 'menu_title' => __( 'Subscriptions', 'pronamic_ideal' ) . $badges['subscriptions']['html'], 'capability' => 'edit_payments', 'menu_slug' => 'edit.php?post_type=pronamic_pay_subscr', ), @@ -998,9 +1045,19 @@ public function admin_menu() { $menu_icon_url = 'dashicons-money'; } + $pay_badge = ''; + + if ( 0 !== $badges['pay']['count'] ) { + $pay_badge = \sprintf( + ' %1$d', + $badges['pay']['count'], + \implode( ', ', $badges['pay']['title'] ) + ); + } + add_menu_page( __( 'Pronamic Pay', 'pronamic_ideal' ), - __( 'Pay', 'pronamic_ideal' ) . $badge, + __( 'Pay', 'pronamic_ideal' ) . $pay_badge, $minimum_capability, 'pronamic_ideal', function() { From adabed15a451264c32bb410d3c03c8705ee70293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 12:29:08 +0100 Subject: [PATCH 36/87] Remove default `edit` bulk action for subscriptions (only allowed incorrect status changes). --- src/Admin/AdminSubscriptionPostType.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Admin/AdminSubscriptionPostType.php b/src/Admin/AdminSubscriptionPostType.php index 0d8e47ea..3b3babac 100644 --- a/src/Admin/AdminSubscriptionPostType.php +++ b/src/Admin/AdminSubscriptionPostType.php @@ -53,6 +53,7 @@ public function __construct( $plugin ) { add_filter( 'manage_edit-' . self::POST_TYPE . '_columns', array( $this, 'columns' ) ); add_filter( 'manage_edit-' . self::POST_TYPE . '_sortable_columns', array( $this, 'sortable_columns' ) ); + add_filter( 'bulk_actions-edit-' . self::POST_TYPE, array( $this, 'bulk_actions' ) ); add_filter( 'list_table_primary_column', array( $this, 'primary_column' ), 10, 2 ); add_action( 'manage_' . self::POST_TYPE . '_posts_custom_column', array( $this, 'custom_columns' ), 10, 2 ); @@ -116,6 +117,21 @@ public function removable_query_args( $args ) { return $args; } + /** + * Custom bulk actions. + * + * @link https://make.wordpress.org/core/2016/10/04/custom-bulk-actions/ + * @link https://github.com/WordPress/WordPress/blob/4.7/wp-admin/includes/class-wp-list-table.php#L440-L452 + * @param array $bulk_actions Bulk actions. + * @return array + */ + public function bulk_actions( $bulk_actions ) { + // Don't allow edit in bulk. + unset( $bulk_actions['edit'] ); + + return $bulk_actions; + } + /** * Maybe process subscription action. * From 5d5eeac079986fdcf39bb6233bf8755d288e384d Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Fri, 25 Mar 2022 12:52:47 +0100 Subject: [PATCH 37/87] Create Updater.php --- src/Updater.php | 199 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 src/Updater.php diff --git a/src/Updater.php b/src/Updater.php new file mode 100644 index 00000000..36bf99fa --- /dev/null +++ b/src/Updater.php @@ -0,0 +1,199 @@ + + * @copyright 2005-2022 Pronamic + * @license GPL-3.0-or-later + * @package Pronamic\WordPress\Pay + */ + +namespace Pronamic\WordPress\Pay; + +/** + * Updater class + * + * @author Remco Tolsma + * @version 2.5.0 + * @since 2.0.1 + */ +class Updater { + /** + * Plugins filter callback. + * + * @var callable|null + */ + private $plugins_filter_callback; + + /** + * Instance of this class. + * + * @since 1.1.0 + * @var self + */ + protected static $instance = null; + + /** + * Construct updater. + * + * @param callable|null $plugins_filter_callback Plugins filter callback. + */ + private function __construct( $plugins_filter_callback ) { + $this->plugins_filter_callback = $plugins_filter_callback; + + \add_filter( 'http_response', array( $this, 'http_response' ), 10, 3 ); + + \add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 ); + } + + /** + * HTTP Response. + * + * @link https://github.com/WordPress/WordPress/blob/5.5/wp-includes/class-http.php#L437-L446 + * @param array $response HTTP response. + * @param array $parsed_args HTTP request arguments. + * @param string $url The request URL. + * @return array + */ + public function http_response( $response, $parsed_args, $url ) { + if ( ! \array_key_exists( 'method', $parsed_args ) ) { + return $repsonse; + } + + if ( 'POST' !== $parsed_args['method'] ) { + return $response; + } + + if ( false !== strpos( $url, '//api.wordpress.org/plugins/update-check/' ) ) { + $response = $this->extend_response_with_pronamic( $response, $parsed_args, 'plugins' ); + } + + return $response; + } + + /** + * Extends WordPress.org API repsonse with Pronamic API response. + * + * @param array $response HTTP response. + * @param array $parsed_args HTTP request arguments. + * @param string $type Type. + * @return array + */ + public function extend_response_with_pronamic( $response, $parsed_args, $type ) { + $data = \json_decode( \wp_remote_retrieve_body( $response ), true ); + + if ( ! is_array( $data ) ) { + return $response; + } + + $pronamic_data = $this->request_plugins_update_check( $parsed_args ); + + if ( false === $pronamic_data ) { + return $response; + } + + if ( ! array_key_exists( $type, $data ) ) { + $data[ $type ] = array(); + } + + if ( \is_array( $pronamic_data[ $type ] ) ) { + $data[ $type ] = array_merge( $data[ $type ], $pronamic_data[ $type ] ); + } + + $response['body'] = \wp_json_encode( $data ); + + return $response; + } + + /** + * Remote post. + * + * @param string $url URL to retrieve. + * @param array $args Request arguments. + * @param array $parsed_args Parsed request arguments. + * @return array + */ + private function remote_post( $url, $args, $parsed_args ) { + $keys = array( + 'timeout', + 'user-agent', + 'headers', + ); + + foreach ( $keys as $key ) { + if ( \array_key_exists( $key, $parsed_args ) ) { + $args[ $key ] = $parsed_args[ $key ]; + } + } + + return \wp_remote_post( $url, $args ); + } + + /** + * Request plugins update check. + * + * @param array $parsed_args HTTP request arguments. + * @return array + */ + private function request_plugins_update_check( $parsed_args ) { + $plugins = $this->get_plugins(); + + if ( 0 === \count( $plugins ) ) { + return false; + } + + $raw_response = $this->remote_post( + 'https://api.pronamic.eu/plugins/update-check/1.2/', + array( + 'body' => array( + 'plugins' => \wp_json_encode( $plugins ), + ), + ), + $parsed_args + ); + + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison + if ( \is_wp_error( $raw_response ) || '200' != \wp_remote_retrieve_response_code( $raw_response ) ) { + return false; + } + + $response = \json_decode( \wp_remote_retrieve_body( $raw_response ), true ); + + return $response; + } + + /** + * Get plugins. + * + * @link https://github.com/pronamic/wp-pronamic-client/blob/ce45ff5b1cde51aa3959750f2a03ad76c3be0463/includes/functions.php#L3-L25 + * @return array + */ + private function get_plugins() { + if ( ! function_exists( '\get_plugins' ) ) { + return array(); + } + + $plugins = \get_plugins(); + + if ( null !== $this->plugins_filter_callback ) { + $plugins = \array_filter( $plugins, $this->plugins_filter_callback ); + } + + return $plugins; + } + + /** + * Return an instance of this class. + * + * @param callable $plugins_filter_callback Plugins filter callback. + * @return self A single instance of this class. + */ + public static function instance( $plugins_filter_callback = null ) { + // If the single instance hasn't been set, set it now. + if ( null === self::$instance ) { + self::$instance = new self( $plugins_filter_callback ); + } + + return self::$instance; + } +} From 91ff3946a772845b6a1233e955ef36a43ed6002a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 16:38:13 +0100 Subject: [PATCH 38/87] Update payment and subscription update meta boxes. --- css/admin.css | 26 +-- css/admin.css.map | 2 +- docs/hooks.md | 2 +- js/dist/admin.js | 56 +++++ js/src/admin.js | 56 +++++ scss/admin/_meta-box-update.scss | 8 + views/meta-box-payment-info.php | 35 ++-- views/meta-box-payment-update.php | 274 ++++++++++++++----------- views/meta-box-subscription-info.php | 18 -- views/meta-box-subscription-update.php | 72 +++++-- 10 files changed, 367 insertions(+), 182 deletions(-) diff --git a/css/admin.css b/css/admin.css index e956acdb..0ffee749 100644 --- a/css/admin.css +++ b/css/admin.css @@ -25,18 +25,13 @@ } .pronamic-pay-chart-legend li { border-right: 5px solid #aaa; - -webkit-box-shadow: inset 0 -1px 0 0 #e5e5e5; - box-shadow: inset 0 -1px 0 0 #e5e5e5; + box-shadow: inset 0 -1px 0 0 #e5e5e5; color: #aaa; display: block; margin: 0; padding: 1em; - -webkit-transition-duration: 0.5s; - transition-duration: 0.5s; - -webkit-transition-property: border, padding, -webkit-box-shadow; - transition-property: border, padding, -webkit-box-shadow; + transition-duration: 0.5s; transition-property: border, box-shadow, padding; - transition-property: border, box-shadow, padding, -webkit-box-shadow; } .pronamic-pay-chart-legend li.completed-count { border-right-color: #dbe1e3; @@ -58,8 +53,7 @@ } .pronamic-pay-chart-legend li:hover { border-right-color: #23282f; - -webkit-box-shadow: inset 0 -1px 0 0 #e5e5e5, inset 300px 0 0 #f9f9f9; - box-shadow: inset 0 -1px 0 0 #e5e5e5, inset 300px 0 0 #f9f9f9; + box-shadow: inset 0 -1px 0 0 #e5e5e5, inset 300px 0 0 #f9f9f9; padding-left: 1.5em; } .pronamic-pay-chart-legend strong { @@ -80,8 +74,7 @@ } .pronamic-pay-status-list li { border-top: 1px solid #eee; - -webkit-box-sizing: border-box; - box-sizing: border-box; + box-sizing: border-box; color: #aaa; float: left; margin: 0; @@ -94,7 +87,6 @@ font-size: 12px; padding: 9px 12px; position: relative; - -webkit-transition: color ease 0.5s; transition: color ease 0.5s; } .pronamic-pay-status-list li a strong { @@ -290,6 +282,14 @@ body.post-type-pronamic_payment #post-body-content, body.post-type-pronamic_pay_ text-align: right; } +#pronamic-pay-status-display { + font-weight: 600; +} + +#pronamic-pay-post-status-select { + margin-top: 3px; +} + .pronamic-pay-settings select { width: 25em; } @@ -477,3 +477,5 @@ body.post-type-pronamic_payment #post-body-content, body.post-type-pronamic_pay_ .pronamic-pay-cloack { display: none; } + +/*# sourceMappingURL=admin.css.map */ diff --git a/css/admin.css.map b/css/admin.css.map index 58bbcd40..44869103 100644 --- a/css/admin.css.map +++ b/css/admin.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../fonts/src/_variables.scss","../scss/admin/_buttons.scss","../scss/admin/_chart.scss","../scss/admin/_variables.scss","../scss/admin/_dashboard-widget-payments.scss","../scss/admin/_edit-form-post.scss","../scss/admin/_forms.scss","../scss/admin/_icons.scss","../scss/admin/_lists.scss","../scss/admin/_meta-box-gateway-config.scss","../scss/admin/_meta-box-gateway-test.scss","../scss/admin/_meta-box-payment-log.scss","../scss/admin/_meta-box-subscription-info.scss","../scss/admin/_meta-box-update.scss","../scss/admin/_settings.scss","../scss/admin/_tables.scss","../scss/admin/_tabs.scss","../scss/admin/_text.scss","../scss/admin/_tip.scss","../scss/admin/_utilities.scss"],"names":[],"mappings":"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","file":"admin.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../fonts/src/_variables.scss","../scss/admin/_buttons.scss","../scss/admin/_chart.scss","../scss/admin/_variables.scss","../scss/admin/_dashboard-widget-payments.scss","../scss/admin/_edit-form-post.scss","../scss/admin/_forms.scss","../scss/admin/_icons.scss","../scss/admin/_lists.scss","../scss/admin/_meta-box-gateway-config.scss","../scss/admin/_meta-box-gateway-test.scss","../scss/admin/_meta-box-payment-log.scss","../scss/admin/_meta-box-subscription-info.scss","../scss/admin/_meta-box-update.scss","../scss/admin/_settings.scss","../scss/admin/_tables.scss","../scss/admin/_tabs.scss","../scss/admin/_text.scss","../scss/admin/_tip.scss","../scss/admin/_utilities.scss"],"names":[],"mappings":"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","file":"admin.css"} \ No newline at end of file diff --git a/docs/hooks.md b/docs/hooks.md index 8c615633..3b146fd7 100644 --- a/docs/hooks.md +++ b/docs/hooks.md @@ -418,7 +418,7 @@ Argument | Type | Description `$url` | `null\|string` | Redirect URL. `$payment` | `\Pronamic\WordPress\Pay\Payments\Payment` | Payment. -Source: [src/Plugin.php](../src/Plugin.php), [line 1207](../src/Plugin.php#L1207-L1213) +Source: [src/Plugin.php](../src/Plugin.php), [line 1201](../src/Plugin.php#L1201-L1207) ### `pronamic_gateway_configuration_display_value` diff --git a/js/dist/admin.js b/js/dist/admin.js index 98640a07..cde037e6 100644 --- a/js/dist/admin.js +++ b/js/dist/admin.js @@ -233,6 +233,61 @@ } ); }; + /** + * Pronamic Pay post status. + */ + var PronamicPayPostStatus = function( element ) { + var $element = $( element ); + + // Post Status edit click. + $element.siblings( 'a.edit-pronamic-pay-post-status' ).on( 'click', function( event ) { + if ( $element.is( ':hidden' ) ) { + $element.slideDown( 'fast', function() { $element.find( 'select' ).trigger( 'focus' ); } ); + + $( this ).hide(); + } + + event.preventDefault(); + } ); + + // Save post status changes and hide options. + $element.find( '.save-pronamic-pay-post-status' ).on( 'click', function( event ) { + $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + + $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + + event.preventDefault(); + } ); + + // Cancel post status editing and hide options. + $element.find( '.cancel-pronamic-pay-post-status' ).on( 'click', function( event ) { + $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + + $( '#pronamic-pay-post-status' ).val( $( '#hidden_pronamic_pay_post_status' ).val() ); + + $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + + event.preventDefault(); + } ); + }; + + /** + * jQuery plugin - Pronamic Pay post status + */ + $.fn.pronamicPayPostStatus = function() { + return this.each( function() { + var $this = $( this ); + + if ( $this.data( 'pronamic-pay-post-status' ) ) { + return; + } + + var postStatus = new PronamicPayPostStatus( this ); + + $this.data( 'pronamic-pay-post-status', postStatus ); + } ); + }; + /** * Pronamic pay gateway test */ @@ -370,6 +425,7 @@ $( document ).ready( function() { $( '#pronamic-pay-gateway-config-editor' ).pronamicPayGatewayConfigEditor(); $( '#pronamic_payment_form_options').pronamicPayFormOptions(); + $( '#pronamic-pay-post-status-select' ).pronamicPayPostStatus(); $( '#pronamic_gateway_test').pronamicPayGatewayTest(); $( '.pronamic-pay-tabs' ).pronamicPayTabs(); diff --git a/js/src/admin.js b/js/src/admin.js index 98640a07..cde037e6 100644 --- a/js/src/admin.js +++ b/js/src/admin.js @@ -233,6 +233,61 @@ } ); }; + /** + * Pronamic Pay post status. + */ + var PronamicPayPostStatus = function( element ) { + var $element = $( element ); + + // Post Status edit click. + $element.siblings( 'a.edit-pronamic-pay-post-status' ).on( 'click', function( event ) { + if ( $element.is( ':hidden' ) ) { + $element.slideDown( 'fast', function() { $element.find( 'select' ).trigger( 'focus' ); } ); + + $( this ).hide(); + } + + event.preventDefault(); + } ); + + // Save post status changes and hide options. + $element.find( '.save-pronamic-pay-post-status' ).on( 'click', function( event ) { + $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + + $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + + event.preventDefault(); + } ); + + // Cancel post status editing and hide options. + $element.find( '.cancel-pronamic-pay-post-status' ).on( 'click', function( event ) { + $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + + $( '#pronamic-pay-post-status' ).val( $( '#hidden_pronamic_pay_post_status' ).val() ); + + $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + + event.preventDefault(); + } ); + }; + + /** + * jQuery plugin - Pronamic Pay post status + */ + $.fn.pronamicPayPostStatus = function() { + return this.each( function() { + var $this = $( this ); + + if ( $this.data( 'pronamic-pay-post-status' ) ) { + return; + } + + var postStatus = new PronamicPayPostStatus( this ); + + $this.data( 'pronamic-pay-post-status', postStatus ); + } ); + }; + /** * Pronamic pay gateway test */ @@ -370,6 +425,7 @@ $( document ).ready( function() { $( '#pronamic-pay-gateway-config-editor' ).pronamicPayGatewayConfigEditor(); $( '#pronamic_payment_form_options').pronamicPayFormOptions(); + $( '#pronamic-pay-post-status-select' ).pronamicPayPostStatus(); $( '#pronamic_gateway_test').pronamicPayGatewayTest(); $( '.pronamic-pay-tabs' ).pronamicPayTabs(); diff --git a/scss/admin/_meta-box-update.scss b/scss/admin/_meta-box-update.scss index 7da83173..0b0bd41d 100644 --- a/scss/admin/_meta-box-update.scss +++ b/scss/admin/_meta-box-update.scss @@ -25,3 +25,11 @@ text-align: right; } + +#pronamic-pay-status-display { + font-weight: 600; +} + +#pronamic-pay-post-status-select { + margin-top: 3px; +} diff --git a/views/meta-box-payment-info.php b/views/meta-box-payment-info.php index efa428e3..fc4bdfc6 100644 --- a/views/meta-box-payment-info.php +++ b/views/meta-box-payment-info.php @@ -25,32 +25,37 @@ date->format_i18n() ); ?> - - - - - - get_status_label(); + get_failure_reason(); + + if ( PaymentStatus::FAILURE === $payment->get_status() && null !== $failure_reason ) : + + ?> - echo \esc_html( ( null === $status_label ) ? '—' : $status_label ); + + + + + + get_failure_reason(); + $status_label = $payment->get_status_label(); - if ( PaymentStatus::FAILURE === $payment->get_status() && null !== $failure_reason ) : + echo \esc_html( ( null === $status_label ) ? '—' : $status_label ); printf( ' — %s', esc_html( $failure_reason ) ); - endif; + ?> + + + + - ?> - - diff --git a/views/meta-box-payment-update.php b/views/meta-box-payment-update.php index e9c489cb..4b122133 100644 --- a/views/meta-box-payment-update.php +++ b/views/meta-box-payment-update.php @@ -10,7 +10,6 @@ use Pronamic\WordPress\Pay\Core\PaymentMethods; use Pronamic\WordPress\Pay\Payments\PaymentPostType; -use Pronamic\WordPress\Pay\Plugin; if ( ! isset( $post ) ) { return; @@ -24,6 +23,8 @@ return; } +ksort( $states ); + // WordPress by default doesn't allow `post_author` values of `0`, that's why we use a dash (`-`). // @link https://github.com/WordPress/WordPress/blob/4.9.5/wp-admin/includes/post.php#L56-L64. $post_author = get_post_field( 'post_author' ); @@ -33,139 +34,168 @@
-

- - -

- - get_gateway(); - - /** - * Check status button. - */ - if ( null !== $gateway && $gateway->supports( 'payment_status_request' ) ) { - // Only show button if gateway exists and status check is supported. - $action_url = wp_nonce_url( - add_query_arg( - array( - 'post' => $post->ID, - 'action' => 'edit', - 'pronamic_pay_check_status' => true, - ), - admin_url( 'post.php' ) - ), - 'pronamic_payment_check_status_' . $post->ID - ); - printf( - '

%s

', - esc_url( $action_url ), - esc_html__( 'Check status', 'pronamic_ideal' ) - ); - } - - /** - * Create invoice for reserved payment. - */ - if ( $gateway && $gateway->supports( 'reservation_payments' ) && 'payment_reserved' === get_post_status( $post->ID ) ) { - // Only show button if gateway exists and reservation payments are supported. - $action_url = wp_nonce_url( - add_query_arg( - array( - 'post' => $post->ID, - 'action' => 'edit', - 'pronamic_pay_create_invoice' => true, - ), - admin_url( 'post.php' ) - ), - 'pronamic_payment_create_invoice_' . $post->ID - ); + - $link_text = sprintf( - /* translators: %s: payment method name */ - __( 'Create %1$s invoice', 'pronamic_ideal' ), - PaymentMethods::get_name( $payment->get_payment_method() ) - ); + + + + - printf( - '

%s

', - esc_url( $action_url ), - esc_html( $link_text ) - ); - } - - /** - * Cancel payment reservations. - */ - if ( $gateway && $gateway->supports( 'reservation_payments' ) && 'payment_reserved' === get_post_status( $post->ID ) ) { - // Only show button if gateway exists and reservation payments are supported. - $action_url = wp_nonce_url( - add_query_arg( - array( - 'post' => $post->ID, - 'action' => 'edit', - 'pronamic_pay_cancel_reservation' => true, - ), - admin_url( 'post.php' ) - ), - 'pronamic_payment_cancel_reservation_' . $post->ID - ); +
+ + + + + + +
+
+ + get_gateway(); + + /** + * Check status button. + */ + if ( null !== $gateway && $gateway->supports( 'payment_status_request' ) ) { + // Only show button if gateway exists and status check is supported. + $action_url = wp_nonce_url( + add_query_arg( + array( + 'post' => $post->ID, + 'action' => 'edit', + 'pronamic_pay_check_status' => true, + ), + admin_url( 'post.php' ) ), - admin_url( 'post.php' ) - ), - 'pronamic_payment_ga_track_' . $post->ID - ); + 'pronamic_payment_check_status_' . $post->ID + ); + + printf( + '

%s

', + esc_url( $action_url ), + esc_html__( 'Check status', 'pronamic_ideal' ) + ); + } + + /** + * Create invoice for reserved payment. + */ + if ( $gateway && $gateway->supports( 'reservation_payments' ) && 'payment_reserved' === get_post_status( $post->ID ) ) { + // Only show button if gateway exists and reservation payments are supported. + $action_url = wp_nonce_url( + add_query_arg( + array( + 'post' => $post->ID, + 'action' => 'edit', + 'pronamic_pay_create_invoice' => true, + ), + admin_url( 'post.php' ) + ), + 'pronamic_payment_create_invoice_' . $post->ID + ); + + $link_text = sprintf( + /* translators: %s: payment method name */ + __( 'Create %1$s invoice', 'pronamic_ideal' ), + PaymentMethods::get_name( $payment->get_payment_method() ) + ); + + printf( + '

%s

', + esc_url( $action_url ), + esc_html( $link_text ) + ); + } + + /** + * Cancel payment reservations. + */ + if ( $gateway && $gateway->supports( 'reservation_payments' ) && 'payment_reserved' === get_post_status( $post->ID ) ) { + // Only show button if gateway exists and reservation payments are supported. + $action_url = wp_nonce_url( + add_query_arg( + array( + 'post' => $post->ID, + 'action' => 'edit', + 'pronamic_pay_cancel_reservation' => true, + ), + admin_url( 'post.php' ) + ), + 'pronamic_payment_cancel_reservation_' . $post->ID + ); + + $link_text = sprintf( + /* translators: %s: payment method name */ + __( 'Cancel %1$s reservation', 'pronamic_ideal' ), + PaymentMethods::get_name( $payment->get_payment_method() ) + ); + + printf( + '

%s

', + esc_url( $action_url ), + esc_html( $link_text ) + ); + } + + /** + * Send to Google Analytics button. + */ + $can_track = pronamic_pay_plugin()->google_analytics_ecommerce->valid_payment( $payment ); + + if ( $can_track ) { + // Only show button for payments that can be tracked. + $action_url = wp_nonce_url( + add_query_arg( + array( + 'post' => $post->ID, + 'action' => 'edit', + 'pronamic_pay_ga_track' => true, + ), + admin_url( 'post.php' ) + ), + 'pronamic_payment_ga_track_' . $post->ID + ); - printf( - '

%s

', - esc_url( $action_url ), - esc_html__( 'Send to Google Analytics', 'pronamic_ideal' ) - ); - } + printf( + '

%s

', + esc_url( $action_url ), + esc_html__( 'Send to Google Analytics', 'pronamic_ideal' ) + ); + } - ?> + ?> +
diff --git a/views/meta-box-subscription-info.php b/views/meta-box-subscription-info.php index 5bf64acf..64e5bf86 100644 --- a/views/meta-box-subscription-info.php +++ b/views/meta-box-subscription-info.php @@ -32,24 +32,6 @@ - - - - - - get_id() ) ); - - if ( isset( $status_object, $status_object->label ) ) { - echo esc_html( $status_object->label ); - } else { - echo '—'; - } - - ?> - - diff --git a/views/meta-box-subscription-update.php b/views/meta-box-subscription-update.php index 83bfc9a5..101a0d20 100644 --- a/views/meta-box-subscription-update.php +++ b/views/meta-box-subscription-update.php @@ -9,6 +9,7 @@ */ use Pronamic\WordPress\Pay\Subscriptions\SubscriptionPostType; +use Pronamic\WordPress\Pay\Subscriptions\SubscriptionStatus; if ( ! isset( $post ) ) { return; @@ -16,6 +17,8 @@ $states = SubscriptionPostType::get_states(); +ksort( $states ); + // WordPress by default doesn't allow `post_author` values of `0`, that's why we use a dash (`-`). // @link https://github.com/WordPress/WordPress/blob/4.9.5/wp-admin/includes/post.php#L56-L64. $post_author = get_post_field( 'post_author' ); @@ -25,23 +28,66 @@
-

- - -

+ + + + post_status ) : ?> + + + + + + +
+ + + + + + +
+ + +
+
From 74669857fe523586c7be71d399bc178bb8e57f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 16:38:46 +0100 Subject: [PATCH 39/87] Make `mode` property visibility protected. --- src/Core/ModeTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/ModeTrait.php b/src/Core/ModeTrait.php index 2daebab2..2323cc70 100644 --- a/src/Core/ModeTrait.php +++ b/src/Core/ModeTrait.php @@ -24,7 +24,7 @@ trait ModeTrait { * * @var string */ - private $mode = 'live'; + protected $mode = 'live'; /** * Set mode. From 79f5b64c879808e165302ca9f423dcf10e702215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 16:39:14 +0100 Subject: [PATCH 40/87] Only query active subscriptions for follow-up payments. --- src/Subscriptions/SubscriptionsFollowUpPaymentsController.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Subscriptions/SubscriptionsFollowUpPaymentsController.php b/src/Subscriptions/SubscriptionsFollowUpPaymentsController.php index a6c4d59d..067ecae3 100644 --- a/src/Subscriptions/SubscriptionsFollowUpPaymentsController.php +++ b/src/Subscriptions/SubscriptionsFollowUpPaymentsController.php @@ -388,8 +388,6 @@ private function get_subscriptions_wp_query_that_require_follow_up_payment( $arg */ 'posts_per_page' => 100, 'post_status' => array( - 'subscr_pending', - 'subscr_failed', 'subscr_active', ), 'meta_query' => array( From 6261864630a9fea27267aa57efac599a7505455c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 16:39:52 +0100 Subject: [PATCH 41/87] Put subscriptions on hold when payment failed. --- src/Subscriptions/SubscriptionsModule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionsModule.php b/src/Subscriptions/SubscriptionsModule.php index 32a4ee15..dd6bc045 100644 --- a/src/Subscriptions/SubscriptionsModule.php +++ b/src/Subscriptions/SubscriptionsModule.php @@ -160,7 +160,7 @@ public function payment_status_update( $payment ) { * @link https://www.europeanpaymentscouncil.eu/document-library/guidance-documents/guidance-reason-codes-sepa-direct-debit-r-transactions * @link https://github.com/pronamic/wp-pronamic-ideal/commit/48449417eac49eb6a93480e3b523a396c7db9b3d#diff-6712c698c6b38adfa7190a4be983a093 */ - $status_update = SubscriptionStatus::FAILURE; + $status_update = SubscriptionStatus::ON_HOLD; break; case PaymentStatus::CANCELLED: From 39431d6275172c85d7567bec7d899375a5184db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 16:40:15 +0100 Subject: [PATCH 42/87] Simplify subscription cancellation. --- views/subscription-cancel.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/views/subscription-cancel.php b/views/subscription-cancel.php index 3cf73713..9f23215c 100644 --- a/views/subscription-cancel.php +++ b/views/subscription-cancel.php @@ -45,11 +45,9 @@ // Subscription details. require __DIR__ . '/subscription-details.php'; - $is_active = in_array( $subscription->get_status(), array( SubscriptionStatus::ACTIVE, SubscriptionStatus::FAILURE, SubscriptionStatus::EXPIRED, SubscriptionStatus::ON_HOLD, SubscriptionStatus::OPEN ), true ); - ?> - + get_status() ) : ?>

@@ -58,7 +56,7 @@

- + get_status() ) : ?>
From 5de364a3204d3b8d8c5c574563a44188a26ff8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 25 Mar 2022 20:05:40 +0100 Subject: [PATCH 43/87] Only query active subscriptions for subscription notifications. --- src/Subscriptions/SubscriptionsNotificationsController.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionsNotificationsController.php b/src/Subscriptions/SubscriptionsNotificationsController.php index 3760231a..c0f4f6e7 100644 --- a/src/Subscriptions/SubscriptionsNotificationsController.php +++ b/src/Subscriptions/SubscriptionsNotificationsController.php @@ -275,7 +275,6 @@ private function get_subscriptions_wp_query_that_require_notification( $args = a */ 'posts_per_page' => 100, 'post_status' => array( - 'subscr_pending', 'subscr_active', ), 'meta_query' => array( From 28aefd79b0851255495f57b19bf2775c7880fe78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 28 Mar 2022 14:17:58 +0200 Subject: [PATCH 44/87] Remove unused 'Status' column from subscription phases meta box. --- views/meta-box-subscription-phases.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/views/meta-box-subscription-phases.php b/views/meta-box-subscription-phases.php index 3178ebac..740691a1 100644 --- a/views/meta-box-subscription-phases.php +++ b/views/meta-box-subscription-phases.php @@ -23,9 +23,6 @@ - @@ -50,7 +47,6 @@ ?> - From d9fe23e223791643c625ac77dd7515a99947eca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 28 Mar 2022 14:25:27 +0200 Subject: [PATCH 45/87] Only show next payment (delivery) date in subscription info meta box if subscription is active. --- views/meta-box-subscription-info.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/meta-box-subscription-info.php b/views/meta-box-subscription-info.php index 64e5bf86..65a5758a 100644 --- a/views/meta-box-subscription-info.php +++ b/views/meta-box-subscription-info.php @@ -134,8 +134,8 @@ get_status(), array( SubscriptionStatus::CANCELLED, SubscriptionStatus::COMPLETED, SubscriptionStatus::EXPIRED ), true ) ) : + // Show next payment (delivery) date if subscription is active. + if ( SubscriptionStatus::ACTIVE === $subscription->get_status() ) : ?> From 75f6df98e32562f13e4ae2b7ffd42a348b7e7872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 28 Mar 2022 14:30:22 +0200 Subject: [PATCH 46/87] Uppercase first letter of payment and subscription source text. --- src/Payments/Payment.php | 2 +- src/Subscriptions/Subscription.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Payments/Payment.php b/src/Payments/Payment.php index 88181941..33d9dca7 100644 --- a/src/Payments/Payment.php +++ b/src/Payments/Payment.php @@ -418,7 +418,7 @@ public function get_edit_payment_url() { */ public function get_source_text() { $pieces = array( - $this->get_source(), + \ucfirst( (string) $this->get_source() ), $this->get_source_id(), ); diff --git a/src/Subscriptions/Subscription.php b/src/Subscriptions/Subscription.php index e1470c2f..07d70f35 100644 --- a/src/Subscriptions/Subscription.php +++ b/src/Subscriptions/Subscription.php @@ -141,7 +141,7 @@ public function add_note( $note ) { */ public function get_source_text() { $pieces = array( - $this->get_source(), + \ucfirst( (string) $this->get_source() ), $this->get_source_id(), ); From 39a2d70aa4d22fcc63d2f643592b92819f3fbebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 28 Mar 2022 15:05:31 +0200 Subject: [PATCH 47/87] Update `http://` URL to `https://`. --- views/page-dashboard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/page-dashboard.php b/views/page-dashboard.php index 2e73ac38..301b1570 100644 --- a/views/page-dashboard.php +++ b/views/page-dashboard.php @@ -423,7 +423,7 @@ __( 'http://www.pronamic.eu/', 'pronamic_ideal' ), 'url' => 'http://feeds.feedburner.com/pronamic', From d709bfe3bfe66a9907749763fe32a80976ad293b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 28 Mar 2022 16:16:29 +0200 Subject: [PATCH 48/87] Only display trial, alignment and proration columns in subscription phases when applicable. --- views/meta-box-subscription-phases.php | 77 ++++++++++++++++++-------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/views/meta-box-subscription-phases.php b/views/meta-box-subscription-phases.php index 740691a1..e3a88ec0 100644 --- a/views/meta-box-subscription-phases.php +++ b/views/meta-box-subscription-phases.php @@ -19,6 +19,23 @@ + is_trial() ) { + $has_trial = true; + } + + if ( $phase->is_alignment() || $phase->is_prorated() ) { + $has_alignment = true; + } + } + + ?> +
- -
get_amount()->format_i18n() ); ?>
@@ -28,10 +45,19 @@ - - - - + + + + + + + + + + + + + @@ -103,34 +129,37 @@ ?> - - - - echo esc_html( $phase->is_alignment() ? __( 'Yes', 'pronamic_ideal' ) : __( 'No', 'pronamic_ideal' ) ); + - ?> - - + echo esc_html( $phase->is_alignment() ? __( 'Yes', 'pronamic_ideal' ) : __( 'No', 'pronamic_ideal' ) ); + + ?> + + + + From a96d2c9078a68a8c6900fb65e1736e5e5bd25466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 28 Mar 2022 16:18:35 +0200 Subject: [PATCH 49/87] Update minified version of admin script (91ff3946). --- js/dist/admin.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/dist/admin.min.js b/js/dist/admin.min.js index 987b3627..25a63869 100644 --- a/js/dist/admin.min.js +++ b/js/dist/admin.min.js @@ -1 +1 @@ -!function(t){var a=function(a){var i=this,e=t(a),n={};n.variantId=e.find("#pronamic_gateway_id"),n.extraSettings=e.find("div.extra-settings"),n.sectionHeaders=e.find(".gateway-config-section-header"),n.tabs=e.find(".pronamic-pay-tabs"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateFields=function(){i.selectedVariant=n.variantId.find("option:selected"),i.settings=i.selectedVariant.data("pronamic-pay-settings"),e.find(".extra-settings").hide(),i.settingElements=[],t.isArray(i.settings)&&t.each(i.settings,(function(t,a){e.find(".setting-"+a).show()})),e.find(".setting-"+i.selectedVariant.val()).show();var a=i.selectedVariant.text().split(" - ")[0].replace(/ \(.*\)/,"");n.tabItems.find(":visible").first().text(a).click(),t("#pronamic-pay-gateway-description").html(i.selectedVariant.attr("data-gateway-description"))},this.updateRowBackgroundColor=function(){var t=n.extraSettings.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.initTabs=function(){t.each(n.sectionHeaders,(function(a,i){var e=t(i),s=e.find("h4").text(),o=e.parents("div")[0].className;n.tabItems.append(t("
  • "+s+"
  • ").addClass(o).removeClass("pronamic-pay-tab"))})),n.tabItems.next().after(n.tabItems),n.tabItems.find("li").click(i.showTabSettings)},this.showTabSettings=function(){var a=t(this);n.extraSettings.hide().eq(a.index()).show()};var s=function(){t.ajax({url:pronamicPayGatewayAdmin.rest_url,method:"GET",beforeSend:function(t){t.setRequestHeader("X-WP-Nonce",pronamicPayGatewayAdmin.nonce)},data:{gateway_id:t("#pronamic_gateway_id").val(),gateway_mode:t("#pronamic_ideal_mode").val()}}).done((function(a){t("#pronamic-pay-gateway-settings").html(a.meta_boxes.settings),t("#pronamic-pay-gateway-settings .pronamic-pay-tabs").pronamicPayTabs(),t("#pronamic-pay-gateway-settings .pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))};t("#pronamic_gateway_id").change(s),t("#pronamic_ideal_mode").change(s),i.initTabs(),i.updateFields(),n.variantId.change(i.updateFields)};t.fn.pronamicPayGatewayConfigEditor=function(){return this.each((function(){var i=t(this);if(!i.data("pronamic-pay-gateway-config-editor")){var e=new a(this);i.data("pronamic-pay-gateway-config-editor",e)}}))};var i=function(a){var i=this,e=t(a),n={};n.tabItems=e.find("ul.pronamic-pay-tabs-items"),n.tabs=e.find(".pronamic-pay-tab"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateRowBackgroundColor=function(){var t=n.tabs.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.showTab=function(){var a=t(this);n.tabItems.find("li").removeClass("active"),a.addClass("active"),n.tabs.hide().eq(a.index()).show(),i.updateRowBackgroundColor(),i.visibleTabItems=n.tabItems.find("li:visible"),i.activeTabItem=a},this.responsiveTabs=function(){if(t(window).width()>960)n.tabs.hide(),i.activeTabItem?i.activeTabItem.click():n.tabItems.find("li:visible").first().click();else{if(!i.visibleTabItems)return;n.tabs.hide(),t.each(i.visibleTabItems,(function(a,i){n.tabs.eq(t(i).index()).show()}))}},n.tabItems.find("li").click(i.showTab),n.tabItems.find("li:visible").first().click(),t(window).resize(i.responsiveTabs)};t.fn.pronamicPayTabs=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-tabs")){var e=new i(this);a.data("pronamic-pay-tabs",e)}}))};var e=function(a){var i=t(a),e={};e.paymentMethods=i.find('select[name="pronamic_pay_test_payment_method"]'),this.updateInputVisibility=function(){var a=e.paymentMethods.val();""!==a&&i.find(".pronamic-pay-test-payment-method").hide().filter("."+a).show(),1===e.paymentMethods.find("option:selected").data("is-recurring")?t("#pronamic-pay-test-subscription").parents("tr").show():(t("#pronamic-pay-test-subscription").parents("tr").hide(),t("#pronamic-pay-test-subscription").prop("checked",!1).trigger("change"))},this.updateInputVisibility(),e.paymentMethods.change(this.updateInputVisibility),i.on("keydown","input, select",(function(t){13===t.keyCode&&(t.preventDefault(),i.find('input[name="test_pay_gateway"]').click())}))};t.fn.pronamicPayGatewayTest=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-gateway-test")){var i=new e(this);a.data("pronamic-pay-gateway-test",i)}}))};var n=function(a){var i=this,e=t(a),n={};n.amountMethod=e.find('select[name="_pronamic_payment_form_amount_method"]'),this.updateAmountsVisibility=function(){var t=n.amountMethod.val();"choices_only"===t||"choices_and_input"===t?e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").show():e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").hide()},this.maybeAddAmountChoice=function(){if(n.amountChoices=e.find('input[name="_pronamic_payment_form_amount_choices[]"]'),0===n.amountChoices.filter((function(){return""===this.value})).length){var t=n.amountChoices.last().closest("div"),a=t.clone(),i="_pronamic_payment_form_amount_choice_"+n.amountChoices.length;a.find("input").attr("id",i).val(""),a.find("label").attr("for",i),t.after(a)}},i.updateAmountsVisibility(),n.amountMethod.change(i.updateAmountsVisibility),e.on("keyup",'input[name="_pronamic_payment_form_amount_choices[]"]',(function(){i.maybeAddAmountChoice()}))};t.fn.pronamicPayFormOptions=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-forms-options")){var i=new n(this);a.data("pronamic-pay-form-options",i)}}))},t(document).ready((function(){t("#pronamic-pay-gateway-config-editor").pronamicPayGatewayConfigEditor(),t("#pronamic_payment_form_options").pronamicPayFormOptions(),t("#pronamic_gateway_test").pronamicPayGatewayTest(),t(".pronamic-pay-tabs").pronamicPayTabs(),t(".pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))}(jQuery); \ No newline at end of file +!function(t){var a=function(a){var i=this,e=t(a),n={};n.variantId=e.find("#pronamic_gateway_id"),n.extraSettings=e.find("div.extra-settings"),n.sectionHeaders=e.find(".gateway-config-section-header"),n.tabs=e.find(".pronamic-pay-tabs"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateFields=function(){i.selectedVariant=n.variantId.find("option:selected"),i.settings=i.selectedVariant.data("pronamic-pay-settings"),e.find(".extra-settings").hide(),i.settingElements=[],t.isArray(i.settings)&&t.each(i.settings,(function(t,a){e.find(".setting-"+a).show()})),e.find(".setting-"+i.selectedVariant.val()).show();var a=i.selectedVariant.text().split(" - ")[0].replace(/ \(.*\)/,"");n.tabItems.find(":visible").first().text(a).click(),t("#pronamic-pay-gateway-description").html(i.selectedVariant.attr("data-gateway-description"))},this.updateRowBackgroundColor=function(){var t=n.extraSettings.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.initTabs=function(){t.each(n.sectionHeaders,(function(a,i){var e=t(i),s=e.find("h4").text(),o=e.parents("div")[0].className;n.tabItems.append(t("
  • "+s+"
  • ").addClass(o).removeClass("pronamic-pay-tab"))})),n.tabItems.next().after(n.tabItems),n.tabItems.find("li").click(i.showTabSettings)},this.showTabSettings=function(){var a=t(this);n.extraSettings.hide().eq(a.index()).show()};var s=function(){t.ajax({url:pronamicPayGatewayAdmin.rest_url,method:"GET",beforeSend:function(t){t.setRequestHeader("X-WP-Nonce",pronamicPayGatewayAdmin.nonce)},data:{gateway_id:t("#pronamic_gateway_id").val(),gateway_mode:t("#pronamic_ideal_mode").val()}}).done((function(a){t("#pronamic-pay-gateway-settings").html(a.meta_boxes.settings),t("#pronamic-pay-gateway-settings .pronamic-pay-tabs").pronamicPayTabs(),t("#pronamic-pay-gateway-settings .pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))};t("#pronamic_gateway_id").change(s),t("#pronamic_ideal_mode").change(s),i.initTabs(),i.updateFields(),n.variantId.change(i.updateFields)};t.fn.pronamicPayGatewayConfigEditor=function(){return this.each((function(){var i=t(this);if(!i.data("pronamic-pay-gateway-config-editor")){var e=new a(this);i.data("pronamic-pay-gateway-config-editor",e)}}))};var i=function(a){var i=this,e=t(a),n={};n.tabItems=e.find("ul.pronamic-pay-tabs-items"),n.tabs=e.find(".pronamic-pay-tab"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateRowBackgroundColor=function(){var t=n.tabs.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.showTab=function(){var a=t(this);n.tabItems.find("li").removeClass("active"),a.addClass("active"),n.tabs.hide().eq(a.index()).show(),i.updateRowBackgroundColor(),i.visibleTabItems=n.tabItems.find("li:visible"),i.activeTabItem=a},this.responsiveTabs=function(){if(t(window).width()>960)n.tabs.hide(),i.activeTabItem?i.activeTabItem.click():n.tabItems.find("li:visible").first().click();else{if(!i.visibleTabItems)return;n.tabs.hide(),t.each(i.visibleTabItems,(function(a,i){n.tabs.eq(t(i).index()).show()}))}},n.tabItems.find("li").click(i.showTab),n.tabItems.find("li:visible").first().click(),t(window).resize(i.responsiveTabs)};t.fn.pronamicPayTabs=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-tabs")){var e=new i(this);a.data("pronamic-pay-tabs",e)}}))};var e=function(a){var i=t(a);i.siblings("a.edit-pronamic-pay-post-status").on("click",(function(a){i.is(":hidden")&&(i.slideDown("fast",(function(){i.find("select").trigger("focus")})),t(this).hide()),a.preventDefault()})),i.find(".save-pronamic-pay-post-status").on("click",(function(a){i.slideUp("fast").siblings("a.edit-pronamic-pay-post-status").show().trigger("focus"),t("#pronamic-pay-status-display").text(t("#pronamic-pay-post-status option:selected").text()),a.preventDefault()})),i.find(".cancel-pronamic-pay-post-status").on("click",(function(a){i.slideUp("fast").siblings("a.edit-pronamic-pay-post-status").show().trigger("focus"),t("#pronamic-pay-post-status").val(t("#hidden_pronamic_pay_post_status").val()),t("#pronamic-pay-status-display").text(t("#pronamic-pay-post-status option:selected").text()),a.preventDefault()}))};t.fn.pronamicPayPostStatus=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-post-status")){var i=new e(this);a.data("pronamic-pay-post-status",i)}}))};var n=function(a){var i=t(a),e={};e.paymentMethods=i.find('select[name="pronamic_pay_test_payment_method"]'),this.updateInputVisibility=function(){var a=e.paymentMethods.val();""!==a&&i.find(".pronamic-pay-test-payment-method").hide().filter("."+a).show(),1===e.paymentMethods.find("option:selected").data("is-recurring")?t("#pronamic-pay-test-subscription").parents("tr").show():(t("#pronamic-pay-test-subscription").parents("tr").hide(),t("#pronamic-pay-test-subscription").prop("checked",!1).trigger("change"))},this.updateInputVisibility(),e.paymentMethods.change(this.updateInputVisibility),i.on("keydown","input, select",(function(t){13===t.keyCode&&(t.preventDefault(),i.find('input[name="test_pay_gateway"]').click())}))};t.fn.pronamicPayGatewayTest=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-gateway-test")){var i=new n(this);a.data("pronamic-pay-gateway-test",i)}}))};var s=function(a){var i=this,e=t(a),n={};n.amountMethod=e.find('select[name="_pronamic_payment_form_amount_method"]'),this.updateAmountsVisibility=function(){var t=n.amountMethod.val();"choices_only"===t||"choices_and_input"===t?e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").show():e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").hide()},this.maybeAddAmountChoice=function(){if(n.amountChoices=e.find('input[name="_pronamic_payment_form_amount_choices[]"]'),0===n.amountChoices.filter((function(){return""===this.value})).length){var t=n.amountChoices.last().closest("div"),a=t.clone(),i="_pronamic_payment_form_amount_choice_"+n.amountChoices.length;a.find("input").attr("id",i).val(""),a.find("label").attr("for",i),t.after(a)}},i.updateAmountsVisibility(),n.amountMethod.change(i.updateAmountsVisibility),e.on("keyup",'input[name="_pronamic_payment_form_amount_choices[]"]',(function(){i.maybeAddAmountChoice()}))};t.fn.pronamicPayFormOptions=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-forms-options")){var i=new s(this);a.data("pronamic-pay-form-options",i)}}))},t(document).ready((function(){t("#pronamic-pay-gateway-config-editor").pronamicPayGatewayConfigEditor(),t("#pronamic_payment_form_options").pronamicPayFormOptions(),t("#pronamic-pay-post-status-select").pronamicPayPostStatus(),t("#pronamic_gateway_test").pronamicPayGatewayTest(),t(".pronamic-pay-tabs").pronamicPayTabs(),t(".pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))}(jQuery); \ No newline at end of file From 661103d68518aa3e2e209a563dfcada512de8290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Wed, 30 Mar 2022 16:39:33 +0200 Subject: [PATCH 50/87] Allow manually updating subscription next payment date (pronamic/wp-pronamic-pay#315). --- css/admin.css | 7 +- css/admin.css.map | 2 +- js/dist/admin.js | 163 ++++++++++++++++-- js/dist/admin.min.js | 2 +- js/src/admin.js | 163 ++++++++++++++++-- scss/admin/_meta-box-update.scss | 7 +- .../SubscriptionsDataStoreCPT.php | 32 +++- views/meta-box-payment-update.php | 10 +- views/meta-box-subscription-update.php | 99 ++++++++++- 9 files changed, 430 insertions(+), 55 deletions(-) diff --git a/css/admin.css b/css/admin.css index 0ffee749..aa782709 100644 --- a/css/admin.css +++ b/css/admin.css @@ -268,7 +268,6 @@ body.post-type-pronamic_payment #post-body-content, body.post-type-pronamic_pay_ .pronamic-pay-inner { margin: 6px 0 0; - padding: 0 12px 12px; } .pronamic-pay-major-actions { @@ -282,11 +281,13 @@ body.post-type-pronamic_payment #post-body-content, body.post-type-pronamic_pay_ text-align: right; } -#pronamic-pay-status-display { +#pronamic-pay-post-status-display, +#pronamic-pay-next-payment-date-display { font-weight: 600; } -#pronamic-pay-post-status-select { +#pronamic-pay-post-status-input, +#pronamic-pay-next-payment-date-input { margin-top: 3px; } diff --git a/css/admin.css.map b/css/admin.css.map index 44869103..f423d02e 100644 --- a/css/admin.css.map +++ b/css/admin.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../fonts/src/_variables.scss","../scss/admin/_buttons.scss","../scss/admin/_chart.scss","../scss/admin/_variables.scss","../scss/admin/_dashboard-widget-payments.scss","../scss/admin/_edit-form-post.scss","../scss/admin/_forms.scss","../scss/admin/_icons.scss","../scss/admin/_lists.scss","../scss/admin/_meta-box-gateway-config.scss","../scss/admin/_meta-box-gateway-test.scss","../scss/admin/_meta-box-payment-log.scss","../scss/admin/_meta-box-subscription-info.scss","../scss/admin/_meta-box-update.scss","../scss/admin/_settings.scss","../scss/admin/_tables.scss","../scss/admin/_tabs.scss","../scss/admin/_text.scss","../scss/admin/_tip.scss","../scss/admin/_utilities.scss"],"names":[],"mappings":"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","file":"admin.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../fonts/src/_variables.scss","../scss/admin/_buttons.scss","../scss/admin/_chart.scss","../scss/admin/_variables.scss","../scss/admin/_dashboard-widget-payments.scss","../scss/admin/_edit-form-post.scss","../scss/admin/_forms.scss","../scss/admin/_icons.scss","../scss/admin/_lists.scss","../scss/admin/_meta-box-gateway-config.scss","../scss/admin/_meta-box-gateway-test.scss","../scss/admin/_meta-box-payment-log.scss","../scss/admin/_meta-box-subscription-info.scss","../scss/admin/_meta-box-update.scss","../scss/admin/_settings.scss","../scss/admin/_tables.scss","../scss/admin/_tabs.scss","../scss/admin/_text.scss","../scss/admin/_tip.scss","../scss/admin/_utilities.scss"],"names":[],"mappings":"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","file":"admin.css"} \ No newline at end of file diff --git a/js/dist/admin.js b/js/dist/admin.js index cde037e6..63d3150c 100644 --- a/js/dist/admin.js +++ b/js/dist/admin.js @@ -236,38 +236,145 @@ /** * Pronamic Pay post status. */ - var PronamicPayPostStatus = function( element ) { + var PronamicPayPostEdit = function( element, elementId ) { + var obj = this; var $element = $( element ); + var $input = $element.find( 'select, input:not([type="hidden"])' ); - // Post Status edit click. - $element.siblings( 'a.edit-pronamic-pay-post-status' ).on( 'click', function( event ) { - if ( $element.is( ':hidden' ) ) { - $element.slideDown( 'fast', function() { $element.find( 'select' ).trigger( 'focus' ); } ); + this.hideOptions = function() { + $element.slideUp( 'fast' ).siblings( 'a.edit-' + elementId ).show().trigger( 'focus' ); + }; - $( this ).hide(); + this.updateDisplayText = function() { + var text = $( '#' + elementId + '-display' )[0].innerHTML; + + var tagName = $input.prop( 'tagName' ).toLowerCase(); + + var type = 'input' === tagName ? $input.prop( 'type' ) : tagName; + + switch ( type ) { + case 'date' : + /** + * Language-sensitive date formatting. + * + * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat + */ + var intlDate = new Intl.DateTimeFormat( + [], + { + 'weekday': 'short', + 'day': 'numeric', + 'month': 'short', + 'year': 'numeric' + } + ); + + var inputValue = $input.val(); + + if ( '' !== inputValue ) { + text = intlDate.format( new Date( inputValue ) ); + } + + break; + case 'select' : + text = $input.find( 'option:selected' ).text(); + + break; } - event.preventDefault(); - } ); + $( '#' + elementId + '-display' ).text( text ); + }; + + this.validateDateInput = function() { + var minDate = $input.attr( 'min' ); + + var inputDate = $input.val(); + + if ( undefined === minDate ) { + return; + } + + minDate = new Date( minDate ); + + inputDate = new Date( inputDate ); + + var $error = $( '#' + elementId + '-error' ); + + var isValidInput = inputDate >= minDate; - // Save post status changes and hide options. - $element.find( '.save-pronamic-pay-post-status' ).on( 'click', function( event ) { - $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + if ( isValidInput ) { + $error.hide(); + } else { + $error.show(); + } - $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + $element.find( '.save-' + elementId ).attr( 'disabled', ! isValidInput ); + }; + // Edit click. + $element.siblings( 'a.edit-' + elementId ).on( 'click', function( event ) { event.preventDefault(); + + if ( ! $element.is( ':hidden' ) ) { + return; + } + + var $error = $( '#' + elementId + '-error' ); + + if ( $error.length > 0 && ! $error.is( ':hidden' ) ) { + $element.find( '.save-' + elementId ).attr( 'disabled', true ); + + $error.hide(); + } + + var dataMin = $input.data( 'min' ); + + if ( undefined !== dataMin && dataMin !== '' ) { + $input.attr( 'min', dataMin ); + } + + $element.slideDown( 'fast', function() { + $input.trigger( 'focus' ); + } ); + + $( this ).hide(); + + obj.validateDateInput(); } ); - // Cancel post status editing and hide options. - $element.find( '.cancel-pronamic-pay-post-status' ).on( 'click', function( event ) { - $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + // Validate date input on changes. + $element.find( 'input[type="date"][data-min!=""][data-min]' ).on( 'change', obj.validateDateInput ); + + // Save changes and hide options. + $element.find( '.save-' + elementId ).on( 'click', function( event ) { + event.preventDefault(); + + if ( $( this ).is( '[disabled]' ) ) { + return; + } - $( '#pronamic-pay-post-status' ).val( $( '#hidden_pronamic_pay_post_status' ).val() ); + obj.hideOptions(); - $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + obj.updateDisplayText(); + } ); + // Cancel editing and hide options. + $element.find( '.cancel-' + elementId ).on( 'click', function( event ) { event.preventDefault(); + + obj.hideOptions(); + + var originalValue = $( '#hidden_' + elementId.replace( /-/g, '_' ) ).val(); + + $( '#' + elementId ).val( originalValue ); + + var dataMin = $input.data( 'min' ); + + if ( undefined !== dataMin && dataMin !== '' ) { + $input.removeAttr( 'min' ); + } + + obj.updateDisplayText(); } ); }; @@ -282,12 +389,29 @@ return; } - var postStatus = new PronamicPayPostStatus( this ); + var postStatus = new PronamicPayPostEdit( this, 'pronamic-pay-post-status' ); $this.data( 'pronamic-pay-post-status', postStatus ); } ); }; + /** + * jQuery plugin - Pronamic Pay next payment date + */ + $.fn.pronamicPayNextPaymentDate = function() { + return this.each( function() { + var $this = $( this ); + + if ( $this.data( 'pronamic-pay-next-payment-date' ) ) { + return; + } + + var nextPaymentDate = new PronamicPayPostEdit( this, 'pronamic-pay-next-payment-date' ); + + $this.data( 'pronamic-pay-next-payment-date', nextPaymentDate ); + } ); + }; + /** * Pronamic pay gateway test */ @@ -425,7 +549,8 @@ $( document ).ready( function() { $( '#pronamic-pay-gateway-config-editor' ).pronamicPayGatewayConfigEditor(); $( '#pronamic_payment_form_options').pronamicPayFormOptions(); - $( '#pronamic-pay-post-status-select' ).pronamicPayPostStatus(); + $( '#pronamic-pay-post-status-input' ).pronamicPayPostStatus(); + $( '#pronamic-pay-next-payment-date-input' ).pronamicPayNextPaymentDate(); $( '#pronamic_gateway_test').pronamicPayGatewayTest(); $( '.pronamic-pay-tabs' ).pronamicPayTabs(); diff --git a/js/dist/admin.min.js b/js/dist/admin.min.js index 25a63869..659a3e72 100644 --- a/js/dist/admin.min.js +++ b/js/dist/admin.min.js @@ -1 +1 @@ -!function(t){var a=function(a){var i=this,e=t(a),n={};n.variantId=e.find("#pronamic_gateway_id"),n.extraSettings=e.find("div.extra-settings"),n.sectionHeaders=e.find(".gateway-config-section-header"),n.tabs=e.find(".pronamic-pay-tabs"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateFields=function(){i.selectedVariant=n.variantId.find("option:selected"),i.settings=i.selectedVariant.data("pronamic-pay-settings"),e.find(".extra-settings").hide(),i.settingElements=[],t.isArray(i.settings)&&t.each(i.settings,(function(t,a){e.find(".setting-"+a).show()})),e.find(".setting-"+i.selectedVariant.val()).show();var a=i.selectedVariant.text().split(" - ")[0].replace(/ \(.*\)/,"");n.tabItems.find(":visible").first().text(a).click(),t("#pronamic-pay-gateway-description").html(i.selectedVariant.attr("data-gateway-description"))},this.updateRowBackgroundColor=function(){var t=n.extraSettings.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.initTabs=function(){t.each(n.sectionHeaders,(function(a,i){var e=t(i),s=e.find("h4").text(),o=e.parents("div")[0].className;n.tabItems.append(t("
  • "+s+"
  • ").addClass(o).removeClass("pronamic-pay-tab"))})),n.tabItems.next().after(n.tabItems),n.tabItems.find("li").click(i.showTabSettings)},this.showTabSettings=function(){var a=t(this);n.extraSettings.hide().eq(a.index()).show()};var s=function(){t.ajax({url:pronamicPayGatewayAdmin.rest_url,method:"GET",beforeSend:function(t){t.setRequestHeader("X-WP-Nonce",pronamicPayGatewayAdmin.nonce)},data:{gateway_id:t("#pronamic_gateway_id").val(),gateway_mode:t("#pronamic_ideal_mode").val()}}).done((function(a){t("#pronamic-pay-gateway-settings").html(a.meta_boxes.settings),t("#pronamic-pay-gateway-settings .pronamic-pay-tabs").pronamicPayTabs(),t("#pronamic-pay-gateway-settings .pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))};t("#pronamic_gateway_id").change(s),t("#pronamic_ideal_mode").change(s),i.initTabs(),i.updateFields(),n.variantId.change(i.updateFields)};t.fn.pronamicPayGatewayConfigEditor=function(){return this.each((function(){var i=t(this);if(!i.data("pronamic-pay-gateway-config-editor")){var e=new a(this);i.data("pronamic-pay-gateway-config-editor",e)}}))};var i=function(a){var i=this,e=t(a),n={};n.tabItems=e.find("ul.pronamic-pay-tabs-items"),n.tabs=e.find(".pronamic-pay-tab"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateRowBackgroundColor=function(){var t=n.tabs.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.showTab=function(){var a=t(this);n.tabItems.find("li").removeClass("active"),a.addClass("active"),n.tabs.hide().eq(a.index()).show(),i.updateRowBackgroundColor(),i.visibleTabItems=n.tabItems.find("li:visible"),i.activeTabItem=a},this.responsiveTabs=function(){if(t(window).width()>960)n.tabs.hide(),i.activeTabItem?i.activeTabItem.click():n.tabItems.find("li:visible").first().click();else{if(!i.visibleTabItems)return;n.tabs.hide(),t.each(i.visibleTabItems,(function(a,i){n.tabs.eq(t(i).index()).show()}))}},n.tabItems.find("li").click(i.showTab),n.tabItems.find("li:visible").first().click(),t(window).resize(i.responsiveTabs)};t.fn.pronamicPayTabs=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-tabs")){var e=new i(this);a.data("pronamic-pay-tabs",e)}}))};var e=function(a){var i=t(a);i.siblings("a.edit-pronamic-pay-post-status").on("click",(function(a){i.is(":hidden")&&(i.slideDown("fast",(function(){i.find("select").trigger("focus")})),t(this).hide()),a.preventDefault()})),i.find(".save-pronamic-pay-post-status").on("click",(function(a){i.slideUp("fast").siblings("a.edit-pronamic-pay-post-status").show().trigger("focus"),t("#pronamic-pay-status-display").text(t("#pronamic-pay-post-status option:selected").text()),a.preventDefault()})),i.find(".cancel-pronamic-pay-post-status").on("click",(function(a){i.slideUp("fast").siblings("a.edit-pronamic-pay-post-status").show().trigger("focus"),t("#pronamic-pay-post-status").val(t("#hidden_pronamic_pay_post_status").val()),t("#pronamic-pay-status-display").text(t("#pronamic-pay-post-status option:selected").text()),a.preventDefault()}))};t.fn.pronamicPayPostStatus=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-post-status")){var i=new e(this);a.data("pronamic-pay-post-status",i)}}))};var n=function(a){var i=t(a),e={};e.paymentMethods=i.find('select[name="pronamic_pay_test_payment_method"]'),this.updateInputVisibility=function(){var a=e.paymentMethods.val();""!==a&&i.find(".pronamic-pay-test-payment-method").hide().filter("."+a).show(),1===e.paymentMethods.find("option:selected").data("is-recurring")?t("#pronamic-pay-test-subscription").parents("tr").show():(t("#pronamic-pay-test-subscription").parents("tr").hide(),t("#pronamic-pay-test-subscription").prop("checked",!1).trigger("change"))},this.updateInputVisibility(),e.paymentMethods.change(this.updateInputVisibility),i.on("keydown","input, select",(function(t){13===t.keyCode&&(t.preventDefault(),i.find('input[name="test_pay_gateway"]').click())}))};t.fn.pronamicPayGatewayTest=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-gateway-test")){var i=new n(this);a.data("pronamic-pay-gateway-test",i)}}))};var s=function(a){var i=this,e=t(a),n={};n.amountMethod=e.find('select[name="_pronamic_payment_form_amount_method"]'),this.updateAmountsVisibility=function(){var t=n.amountMethod.val();"choices_only"===t||"choices_and_input"===t?e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").show():e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").hide()},this.maybeAddAmountChoice=function(){if(n.amountChoices=e.find('input[name="_pronamic_payment_form_amount_choices[]"]'),0===n.amountChoices.filter((function(){return""===this.value})).length){var t=n.amountChoices.last().closest("div"),a=t.clone(),i="_pronamic_payment_form_amount_choice_"+n.amountChoices.length;a.find("input").attr("id",i).val(""),a.find("label").attr("for",i),t.after(a)}},i.updateAmountsVisibility(),n.amountMethod.change(i.updateAmountsVisibility),e.on("keyup",'input[name="_pronamic_payment_form_amount_choices[]"]',(function(){i.maybeAddAmountChoice()}))};t.fn.pronamicPayFormOptions=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-forms-options")){var i=new s(this);a.data("pronamic-pay-form-options",i)}}))},t(document).ready((function(){t("#pronamic-pay-gateway-config-editor").pronamicPayGatewayConfigEditor(),t("#pronamic_payment_form_options").pronamicPayFormOptions(),t("#pronamic-pay-post-status-select").pronamicPayPostStatus(),t("#pronamic_gateway_test").pronamicPayGatewayTest(),t(".pronamic-pay-tabs").pronamicPayTabs(),t(".pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))}(jQuery); \ No newline at end of file +!function(t){var a=function(a){var i=this,e=t(a),n={};n.variantId=e.find("#pronamic_gateway_id"),n.extraSettings=e.find("div.extra-settings"),n.sectionHeaders=e.find(".gateway-config-section-header"),n.tabs=e.find(".pronamic-pay-tabs"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateFields=function(){i.selectedVariant=n.variantId.find("option:selected"),i.settings=i.selectedVariant.data("pronamic-pay-settings"),e.find(".extra-settings").hide(),i.settingElements=[],t.isArray(i.settings)&&t.each(i.settings,(function(t,a){e.find(".setting-"+a).show()})),e.find(".setting-"+i.selectedVariant.val()).show();var a=i.selectedVariant.text().split(" - ")[0].replace(/ \(.*\)/,"");n.tabItems.find(":visible").first().text(a).click(),t("#pronamic-pay-gateway-description").html(i.selectedVariant.attr("data-gateway-description"))},this.updateRowBackgroundColor=function(){var t=n.extraSettings.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.initTabs=function(){t.each(n.sectionHeaders,(function(a,i){var e=t(i),s=e.find("h4").text(),o=e.parents("div")[0].className;n.tabItems.append(t("
  • "+s+"
  • ").addClass(o).removeClass("pronamic-pay-tab"))})),n.tabItems.next().after(n.tabItems),n.tabItems.find("li").click(i.showTabSettings)},this.showTabSettings=function(){var a=t(this);n.extraSettings.hide().eq(a.index()).show()};var s=function(){t.ajax({url:pronamicPayGatewayAdmin.rest_url,method:"GET",beforeSend:function(t){t.setRequestHeader("X-WP-Nonce",pronamicPayGatewayAdmin.nonce)},data:{gateway_id:t("#pronamic_gateway_id").val(),gateway_mode:t("#pronamic_ideal_mode").val()}}).done((function(a){t("#pronamic-pay-gateway-settings").html(a.meta_boxes.settings),t("#pronamic-pay-gateway-settings .pronamic-pay-tabs").pronamicPayTabs(),t("#pronamic-pay-gateway-settings .pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))};t("#pronamic_gateway_id").change(s),t("#pronamic_ideal_mode").change(s),i.initTabs(),i.updateFields(),n.variantId.change(i.updateFields)};t.fn.pronamicPayGatewayConfigEditor=function(){return this.each((function(){var i=t(this);if(!i.data("pronamic-pay-gateway-config-editor")){var e=new a(this);i.data("pronamic-pay-gateway-config-editor",e)}}))};var i=function(a){var i=this,e=t(a),n={};n.tabItems=e.find("ul.pronamic-pay-tabs-items"),n.tabs=e.find(".pronamic-pay-tab"),n.tabItems=e.find("ul.pronamic-pay-tabs-items"),this.updateRowBackgroundColor=function(){var t=n.tabs.find(".form-table tr");t.removeClass("even"),t.filter(":visible:even").addClass("even")},this.showTab=function(){var a=t(this);n.tabItems.find("li").removeClass("active"),a.addClass("active"),n.tabs.hide().eq(a.index()).show(),i.updateRowBackgroundColor(),i.visibleTabItems=n.tabItems.find("li:visible"),i.activeTabItem=a},this.responsiveTabs=function(){if(t(window).width()>960)n.tabs.hide(),i.activeTabItem?i.activeTabItem.click():n.tabItems.find("li:visible").first().click();else{if(!i.visibleTabItems)return;n.tabs.hide(),t.each(i.visibleTabItems,(function(a,i){n.tabs.eq(t(i).index()).show()}))}},n.tabItems.find("li").click(i.showTab),n.tabItems.find("li:visible").first().click(),t(window).resize(i.responsiveTabs)};t.fn.pronamicPayTabs=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-tabs")){var e=new i(this);a.data("pronamic-pay-tabs",e)}}))};var e=function(a,i){var e=this,n=t(a),s=n.find('select, input:not([type="hidden"])');this.hideOptions=function(){n.slideUp("fast").siblings("a.edit-"+i).show().trigger("focus")},this.updateDisplayText=function(){var a=t("#"+i+"-display")[0].innerHTML,e=s.prop("tagName").toLowerCase();switch("input"===e?s.prop("type"):e){case"date":var n=new Intl.DateTimeFormat([],{weekday:"short",day:"numeric",month:"short",year:"numeric"}),o=s.val();""!==o&&(a=n.format(new Date(o)));break;case"select":a=s.find("option:selected").text()}t("#"+i+"-display").text(a)},this.validateDateInput=function(){var a=s.attr("min"),e=s.val();if(void 0!==a){a=new Date(a),e=new Date(e);var o=t("#"+i+"-error"),r=e>=a;r?o.hide():o.show(),n.find(".save-"+i).attr("disabled",!r)}},n.siblings("a.edit-"+i).on("click",(function(a){if(a.preventDefault(),n.is(":hidden")){var o=t("#"+i+"-error");o.length>0&&!o.is(":hidden")&&(n.find(".save-"+i).attr("disabled",!0),o.hide());var r=s.data("min");void 0!==r&&""!==r&&s.attr("min",r),n.slideDown("fast",(function(){s.trigger("focus")})),t(this).hide(),e.validateDateInput()}})),n.find('input[type="date"][data-min!=""][data-min]').on("change",e.validateDateInput),n.find(".save-"+i).on("click",(function(a){a.preventDefault(),t(this).is("[disabled]")||(e.hideOptions(),e.updateDisplayText())})),n.find(".cancel-"+i).on("click",(function(a){a.preventDefault(),e.hideOptions();var n=t("#hidden_"+i.replace(/-/g,"_")).val();t("#"+i).val(n);var o=s.data("min");void 0!==o&&""!==o&&s.removeAttr("min"),e.updateDisplayText()}))};t.fn.pronamicPayPostStatus=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-post-status")){var i=new e(this,"pronamic-pay-post-status");a.data("pronamic-pay-post-status",i)}}))},t.fn.pronamicPayNextPaymentDate=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-next-payment-date")){var i=new e(this,"pronamic-pay-next-payment-date");a.data("pronamic-pay-next-payment-date",i)}}))};var n=function(a){var i=t(a),e={};e.paymentMethods=i.find('select[name="pronamic_pay_test_payment_method"]'),this.updateInputVisibility=function(){var a=e.paymentMethods.val();""!==a&&i.find(".pronamic-pay-test-payment-method").hide().filter("."+a).show(),1===e.paymentMethods.find("option:selected").data("is-recurring")?t("#pronamic-pay-test-subscription").parents("tr").show():(t("#pronamic-pay-test-subscription").parents("tr").hide(),t("#pronamic-pay-test-subscription").prop("checked",!1).trigger("change"))},this.updateInputVisibility(),e.paymentMethods.change(this.updateInputVisibility),i.on("keydown","input, select",(function(t){13===t.keyCode&&(t.preventDefault(),i.find('input[name="test_pay_gateway"]').click())}))};t.fn.pronamicPayGatewayTest=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-gateway-test")){var i=new n(this);a.data("pronamic-pay-gateway-test",i)}}))};var s=function(a){var i=this,e=t(a),n={};n.amountMethod=e.find('select[name="_pronamic_payment_form_amount_method"]'),this.updateAmountsVisibility=function(){var t=n.amountMethod.val();"choices_only"===t||"choices_and_input"===t?e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").show():e.find('input[name="_pronamic_payment_form_amount_choices[]"]').closest("div").hide()},this.maybeAddAmountChoice=function(){if(n.amountChoices=e.find('input[name="_pronamic_payment_form_amount_choices[]"]'),0===n.amountChoices.filter((function(){return""===this.value})).length){var t=n.amountChoices.last().closest("div"),a=t.clone(),i="_pronamic_payment_form_amount_choice_"+n.amountChoices.length;a.find("input").attr("id",i).val(""),a.find("label").attr("for",i),t.after(a)}},i.updateAmountsVisibility(),n.amountMethod.change(i.updateAmountsVisibility),e.on("keyup",'input[name="_pronamic_payment_form_amount_choices[]"]',(function(){i.maybeAddAmountChoice()}))};t.fn.pronamicPayFormOptions=function(){return this.each((function(){var a=t(this);if(!a.data("pronamic-pay-forms-options")){var i=new s(this);a.data("pronamic-pay-form-options",i)}}))},t(document).ready((function(){t("#pronamic-pay-gateway-config-editor").pronamicPayGatewayConfigEditor(),t("#pronamic_payment_form_options").pronamicPayFormOptions(),t("#pronamic-pay-post-status-input").pronamicPayPostStatus(),t("#pronamic-pay-next-payment-date-input").pronamicPayNextPaymentDate(),t("#pronamic_gateway_test").pronamicPayGatewayTest(),t(".pronamic-pay-tabs").pronamicPayTabs(),t(".pronamic-pay-tip").each((function(){tippy(this,{content:t(this).attr("title"),arrow:!0,theme:"pronamic-pay"})}))}))}(jQuery); \ No newline at end of file diff --git a/js/src/admin.js b/js/src/admin.js index cde037e6..63d3150c 100644 --- a/js/src/admin.js +++ b/js/src/admin.js @@ -236,38 +236,145 @@ /** * Pronamic Pay post status. */ - var PronamicPayPostStatus = function( element ) { + var PronamicPayPostEdit = function( element, elementId ) { + var obj = this; var $element = $( element ); + var $input = $element.find( 'select, input:not([type="hidden"])' ); - // Post Status edit click. - $element.siblings( 'a.edit-pronamic-pay-post-status' ).on( 'click', function( event ) { - if ( $element.is( ':hidden' ) ) { - $element.slideDown( 'fast', function() { $element.find( 'select' ).trigger( 'focus' ); } ); + this.hideOptions = function() { + $element.slideUp( 'fast' ).siblings( 'a.edit-' + elementId ).show().trigger( 'focus' ); + }; - $( this ).hide(); + this.updateDisplayText = function() { + var text = $( '#' + elementId + '-display' )[0].innerHTML; + + var tagName = $input.prop( 'tagName' ).toLowerCase(); + + var type = 'input' === tagName ? $input.prop( 'type' ) : tagName; + + switch ( type ) { + case 'date' : + /** + * Language-sensitive date formatting. + * + * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat + */ + var intlDate = new Intl.DateTimeFormat( + [], + { + 'weekday': 'short', + 'day': 'numeric', + 'month': 'short', + 'year': 'numeric' + } + ); + + var inputValue = $input.val(); + + if ( '' !== inputValue ) { + text = intlDate.format( new Date( inputValue ) ); + } + + break; + case 'select' : + text = $input.find( 'option:selected' ).text(); + + break; } - event.preventDefault(); - } ); + $( '#' + elementId + '-display' ).text( text ); + }; + + this.validateDateInput = function() { + var minDate = $input.attr( 'min' ); + + var inputDate = $input.val(); + + if ( undefined === minDate ) { + return; + } + + minDate = new Date( minDate ); + + inputDate = new Date( inputDate ); + + var $error = $( '#' + elementId + '-error' ); + + var isValidInput = inputDate >= minDate; - // Save post status changes and hide options. - $element.find( '.save-pronamic-pay-post-status' ).on( 'click', function( event ) { - $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + if ( isValidInput ) { + $error.hide(); + } else { + $error.show(); + } - $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + $element.find( '.save-' + elementId ).attr( 'disabled', ! isValidInput ); + }; + // Edit click. + $element.siblings( 'a.edit-' + elementId ).on( 'click', function( event ) { event.preventDefault(); + + if ( ! $element.is( ':hidden' ) ) { + return; + } + + var $error = $( '#' + elementId + '-error' ); + + if ( $error.length > 0 && ! $error.is( ':hidden' ) ) { + $element.find( '.save-' + elementId ).attr( 'disabled', true ); + + $error.hide(); + } + + var dataMin = $input.data( 'min' ); + + if ( undefined !== dataMin && dataMin !== '' ) { + $input.attr( 'min', dataMin ); + } + + $element.slideDown( 'fast', function() { + $input.trigger( 'focus' ); + } ); + + $( this ).hide(); + + obj.validateDateInput(); } ); - // Cancel post status editing and hide options. - $element.find( '.cancel-pronamic-pay-post-status' ).on( 'click', function( event ) { - $element.slideUp( 'fast' ).siblings( 'a.edit-pronamic-pay-post-status' ).show().trigger( 'focus' ); + // Validate date input on changes. + $element.find( 'input[type="date"][data-min!=""][data-min]' ).on( 'change', obj.validateDateInput ); + + // Save changes and hide options. + $element.find( '.save-' + elementId ).on( 'click', function( event ) { + event.preventDefault(); + + if ( $( this ).is( '[disabled]' ) ) { + return; + } - $( '#pronamic-pay-post-status' ).val( $( '#hidden_pronamic_pay_post_status' ).val() ); + obj.hideOptions(); - $( '#pronamic-pay-status-display' ).text( $( '#pronamic-pay-post-status option:selected' ).text() ); + obj.updateDisplayText(); + } ); + // Cancel editing and hide options. + $element.find( '.cancel-' + elementId ).on( 'click', function( event ) { event.preventDefault(); + + obj.hideOptions(); + + var originalValue = $( '#hidden_' + elementId.replace( /-/g, '_' ) ).val(); + + $( '#' + elementId ).val( originalValue ); + + var dataMin = $input.data( 'min' ); + + if ( undefined !== dataMin && dataMin !== '' ) { + $input.removeAttr( 'min' ); + } + + obj.updateDisplayText(); } ); }; @@ -282,12 +389,29 @@ return; } - var postStatus = new PronamicPayPostStatus( this ); + var postStatus = new PronamicPayPostEdit( this, 'pronamic-pay-post-status' ); $this.data( 'pronamic-pay-post-status', postStatus ); } ); }; + /** + * jQuery plugin - Pronamic Pay next payment date + */ + $.fn.pronamicPayNextPaymentDate = function() { + return this.each( function() { + var $this = $( this ); + + if ( $this.data( 'pronamic-pay-next-payment-date' ) ) { + return; + } + + var nextPaymentDate = new PronamicPayPostEdit( this, 'pronamic-pay-next-payment-date' ); + + $this.data( 'pronamic-pay-next-payment-date', nextPaymentDate ); + } ); + }; + /** * Pronamic pay gateway test */ @@ -425,7 +549,8 @@ $( document ).ready( function() { $( '#pronamic-pay-gateway-config-editor' ).pronamicPayGatewayConfigEditor(); $( '#pronamic_payment_form_options').pronamicPayFormOptions(); - $( '#pronamic-pay-post-status-select' ).pronamicPayPostStatus(); + $( '#pronamic-pay-post-status-input' ).pronamicPayPostStatus(); + $( '#pronamic-pay-next-payment-date-input' ).pronamicPayNextPaymentDate(); $( '#pronamic_gateway_test').pronamicPayGatewayTest(); $( '.pronamic-pay-tabs' ).pronamicPayTabs(); diff --git a/scss/admin/_meta-box-update.scss b/scss/admin/_meta-box-update.scss index 0b0bd41d..0e121a66 100644 --- a/scss/admin/_meta-box-update.scss +++ b/scss/admin/_meta-box-update.scss @@ -9,7 +9,6 @@ .pronamic-pay-inner { margin: 6px 0 0; - padding: 0 12px 12px; } .pronamic-pay-major-actions { @@ -26,10 +25,12 @@ text-align: right; } -#pronamic-pay-status-display { +#pronamic-pay-post-status-display, +#pronamic-pay-next-payment-date-display { font-weight: 600; } -#pronamic-pay-post-status-select { +#pronamic-pay-post-status-input, +#pronamic-pay-next-payment-date-input { margin-top: 3px; } diff --git a/src/Subscriptions/SubscriptionsDataStoreCPT.php b/src/Subscriptions/SubscriptionsDataStoreCPT.php index 3117334f..96e0f6ba 100644 --- a/src/Subscriptions/SubscriptionsDataStoreCPT.php +++ b/src/Subscriptions/SubscriptionsDataStoreCPT.php @@ -10,8 +10,8 @@ namespace Pronamic\WordPress\Pay\Subscriptions; -use DatePeriod; use Pronamic\WordPress\DateTime\DateTime; +use Pronamic\WordPress\DateTime\DateTimeImmutable; use Pronamic\WordPress\DateTime\DateTimeZone; use Pronamic\WordPress\Money\Money; use Pronamic\WordPress\Pay\Payments\LegacyPaymentsDataStoreCPT; @@ -222,6 +222,36 @@ private function update_subscription_form_post_array( $subscription, $postarr ) if ( ! check_admin_referer( 'pronamic_subscription_update', 'pronamic_subscription_update_nonce' ) ) { return; } + + // Next payment date. + if ( \array_key_exists( 'hidden_pronamic_pay_next_payment_date', $postarr ) && \array_key_exists( 'pronamic_subscription_next_payment_date', $postarr ) ) { + $old_value = $postarr['hidden_pronamic_pay_next_payment_date']; + + $new_value = $postarr['pronamic_subscription_next_payment_date']; + + $current_phase = $subscription->get_current_phase(); + + if ( null !== $current_phase && ! empty( $new_value ) && $old_value !== $new_value ) { + $new_date = new DateTimeImmutable( $new_value ); + + $next_date = $current_phase->get_next_date(); + + $updated_date = null === $next_date ? clone $new_date : clone $next_date; + + $updated_date = $updated_date->setDate( (int) $new_date->format( 'Y' ), (int) $new_date->format( 'm' ), (int) $new_date->format( 'd' ) ); + + $current_phase->set_next_date( $updated_date ); + + $note = \sprintf( + /* translators: %1: old formatted date, %2: new formatted date */ + \__( 'Next payment date updated from %1$s to %2$s.', 'pronamic_ideal' ), + null === $next_date ? '' : $next_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ), + $updated_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ) + ); + + $subscription->add_note( $note ); + } + } } /** diff --git a/views/meta-box-payment-update.php b/views/meta-box-payment-update.php index 4b122133..d8b836d8 100644 --- a/views/meta-box-payment-update.php +++ b/views/meta-box-payment-update.php @@ -39,7 +39,7 @@
    -
    +
    %s

    ', + '', esc_url( $action_url ), esc_html__( 'Check status', 'pronamic_ideal' ) ); @@ -132,7 +132,7 @@ ); printf( - '

    %s

    ', + '', esc_url( $action_url ), esc_html( $link_text ) ); @@ -162,7 +162,7 @@ ); printf( - '

    %s

    ', + '', esc_url( $action_url ), esc_html( $link_text ) ); @@ -188,7 +188,7 @@ ); printf( - '

    %s

    ', + '', esc_url( $action_url ), esc_html__( 'Send to Google Analytics', 'pronamic_ideal' ) ); diff --git a/views/meta-box-subscription-update.php b/views/meta-box-subscription-update.php index 101a0d20..70e958f2 100644 --- a/views/meta-box-subscription-update.php +++ b/views/meta-box-subscription-update.php @@ -8,8 +8,10 @@ * @package Pronamic\WordPress\Pay */ +use Pronamic\WordPress\Pay\Plugin; use Pronamic\WordPress\Pay\Subscriptions\SubscriptionPostType; use Pronamic\WordPress\Pay\Subscriptions\SubscriptionStatus; +use Pronamic\WordPress\Pay\Util; if ( ! isset( $post ) ) { return; @@ -24,6 +26,8 @@ $post_author = get_post_field( 'post_author' ); $post_author = empty( $post_author ) ? '-' : $post_author; +$subscription = \get_pronamic_subscription( (int) get_the_ID() ); + ?> @@ -33,7 +37,7 @@
    -
    +
    - + post_status ) : ?> @@ -53,7 +57,7 @@ -
    +
    + + + 'pronamic-pay-next-payment-date', + 'name' => 'pronamic_subscription_next_payment_date', + 'type' => 'date', + 'value' => null === $next_payment_date ? '' : $next_payment_date->format( 'Y-m-d' ), + 'data-min' => ( new DateTimeImmutable( 'tomorrow' ) )->format( 'Y-m-d' ), + ); + + \printf( + '', + /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ + Util::array_to_html_attributes( $atts ) + ); + + ?> + + + +
    + + get_status() ) { + $class = null !== $next_payment_date && $next_payment_date >= $tomorrow ? 'hidden' : ''; + } + + ?> + +
    +

    +
    +
    From 59deeac4f639cf0efd07c5e1a0b7ff884d6af0a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Thu, 31 Mar 2022 16:26:59 +0200 Subject: [PATCH 51/87] Disable manually changing next payment date for subscriptions with WooCommerce (pronamic/wp-pronamic-pay#315). --- views/meta-box-subscription-update.php | 93 ++++++++++++++------------ 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/views/meta-box-subscription-update.php b/views/meta-box-subscription-update.php index 70e958f2..9d0219c9 100644 --- a/views/meta-box-subscription-update.php +++ b/views/meta-box-subscription-update.php @@ -120,66 +120,75 @@
    -
    - - $next_payment_date = null === $subscription ? null : $subscription->get_next_payment_date(); +
    + + $next_payment_date = $subscription->get_next_payment_date(); - - - + ?> - format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ) ); ?> + + + - - - - + format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ) ); ?> -
    - - + get_source() ) : ?> - + + + - $atts = array( - 'id' => 'pronamic-pay-next-payment-date', - 'name' => 'pronamic_subscription_next_payment_date', - 'type' => 'date', - 'value' => null === $next_payment_date ? '' : $next_payment_date->format( 'Y-m-d' ), - 'data-min' => ( new DateTimeImmutable( 'tomorrow' ) )->format( 'Y-m-d' ), - ); + - \printf( - '', - /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ - Util::array_to_html_attributes( $atts ) - ); +
    + + - ?> + - -
    + $atts = array( + 'id' => 'pronamic-pay-next-payment-date', + 'name' => 'pronamic_subscription_next_payment_date', + 'type' => 'date', + 'value' => null === $next_payment_date ? '' : $next_payment_date->format( 'Y-m-d' ), + 'data-min' => ( new DateTimeImmutable( 'tomorrow' ) )->format( 'Y-m-d' ), + ); - ', + /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ + Util::array_to_html_attributes( $atts ) + ); - $tomorrow = new DateTimeImmutable( 'tomorrow midnight', new DateTimeZone( Plugin::TIMEZONE ) ); + ?> - $class = 'hidden'; + + +
    - if ( null !== $subscription && SubscriptionStatus::ACTIVE === $subscription->get_status() ) { - $class = null !== $next_payment_date && $next_payment_date >= $tomorrow ? 'hidden' : ''; - } + + $tomorrow = new DateTimeImmutable( 'tomorrow midnight', new DateTimeZone( Plugin::TIMEZONE ) ); + + $class = 'hidden'; -
    -

    + if ( null !== $subscription && SubscriptionStatus::ACTIVE === $subscription->get_status() ) { + $class = null !== $next_payment_date && $next_payment_date >= $tomorrow ? 'hidden' : ''; + } + + ?> + +
    +

    +
    -
    + + +
    From 2c9a6bf800da9c14fd353663ef5d853916bcdf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Thu, 31 Mar 2022 16:41:38 +0200 Subject: [PATCH 52/87] Fix possible fatal error on retrieval of issuers. --- src/Core/Gateway.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Core/Gateway.php b/src/Core/Gateway.php index 2d7fc871..c3941fe6 100644 --- a/src/Core/Gateway.php +++ b/src/Core/Gateway.php @@ -184,7 +184,11 @@ public function get_transient_issuers() { $result = get_transient( $transient ); if ( is_wp_error( $result ) || false === $result ) { - $issuers = $this->get_issuers(); + try { + $issuers = $this->get_issuers(); + } catch ( \Exception $e ) { + $issuers = null; + } if ( ! empty( $issuers ) ) { // 60 * 60 * 24 = 24 hours = 1 day From a54901d73d6f7d4f312905ed7c95a7e941f72872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 1 Apr 2022 11:44:17 +0200 Subject: [PATCH 53/87] Update minified admin style. --- css/admin.css | 18 ++++++++++++------ css/admin.min.css | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/css/admin.css b/css/admin.css index aa782709..dbe529c7 100644 --- a/css/admin.css +++ b/css/admin.css @@ -25,13 +25,18 @@ } .pronamic-pay-chart-legend li { border-right: 5px solid #aaa; - box-shadow: inset 0 -1px 0 0 #e5e5e5; + -webkit-box-shadow: inset 0 -1px 0 0 #e5e5e5; + box-shadow: inset 0 -1px 0 0 #e5e5e5; color: #aaa; display: block; margin: 0; padding: 1em; - transition-duration: 0.5s; + -webkit-transition-duration: 0.5s; + transition-duration: 0.5s; + -webkit-transition-property: border, padding, -webkit-box-shadow; + transition-property: border, padding, -webkit-box-shadow; transition-property: border, box-shadow, padding; + transition-property: border, box-shadow, padding, -webkit-box-shadow; } .pronamic-pay-chart-legend li.completed-count { border-right-color: #dbe1e3; @@ -53,7 +58,8 @@ } .pronamic-pay-chart-legend li:hover { border-right-color: #23282f; - box-shadow: inset 0 -1px 0 0 #e5e5e5, inset 300px 0 0 #f9f9f9; + -webkit-box-shadow: inset 0 -1px 0 0 #e5e5e5, inset 300px 0 0 #f9f9f9; + box-shadow: inset 0 -1px 0 0 #e5e5e5, inset 300px 0 0 #f9f9f9; padding-left: 1.5em; } .pronamic-pay-chart-legend strong { @@ -74,7 +80,8 @@ } .pronamic-pay-status-list li { border-top: 1px solid #eee; - box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; color: #aaa; float: left; margin: 0; @@ -87,6 +94,7 @@ font-size: 12px; padding: 9px 12px; position: relative; + -webkit-transition: color ease 0.5s; transition: color ease 0.5s; } .pronamic-pay-status-list li a strong { @@ -478,5 +486,3 @@ body.post-type-pronamic_payment #post-body-content, body.post-type-pronamic_pay_ .pronamic-pay-cloack { display: none; } - -/*# sourceMappingURL=admin.css.map */ diff --git a/css/admin.min.css b/css/admin.min.css index d5379549..a157f8ac 100644 --- a/css/admin.min.css +++ b/css/admin.min.css @@ -1 +1 @@ -.pronamic-pay-btn-link{line-height:26px;padding:0 10px 1px}.postbox .pronamic-pay-chart-with-sidebar{padding:12px 12px 12px 249px}.pronamic-pay-chart-sidebar{float:left;margin-left:-237px;width:225px}.pronamic-pay-chart-legend{background:#fff;border-color:#e5e5e5;border-style:solid;border-width:1px 0 0 1px;list-style:none;margin:0 0 1em;padding:0}.pronamic-pay-chart-legend li{border-right:5px solid #aaa;-webkit-box-shadow:inset 0 -1px 0 0 #e5e5e5;box-shadow:inset 0 -1px 0 0 #e5e5e5;color:#aaa;display:block;margin:0;padding:1em;-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transition-property:border,padding,-webkit-box-shadow;transition-property:border,padding,-webkit-box-shadow;transition-property:border,box-shadow,padding;transition-property:border,box-shadow,padding,-webkit-box-shadow}.pronamic-pay-chart-legend li.completed-count{border-right-color:#dbe1e3}.pronamic-pay-chart-legend li.pending-sum{border-right-color:#b1d4ea}.pronamic-pay-chart-legend li.completed-sum{border-right-color:#3498db}.pronamic-pay-chart-legend li.cancelled-sum{border-right-color:#f1c40f}.pronamic-pay-chart-legend li.expired-sum{border-right-color:#dbe1e3}.pronamic-pay-chart-legend li.failed-sum{border-right-color:#e74c3c}.pronamic-pay-chart-legend li:hover{border-right-color:#23282f;-webkit-box-shadow:inset 0 -1px 0 0 #e5e5e5,inset 300px 0 0 #f9f9f9;box-shadow:inset 0 -1px 0 0 #e5e5e5,inset 300px 0 0 #f9f9f9;padding-left:1.5em}.pronamic-pay-chart-legend strong{color:#444;display:block;font-size:1.618em;font-weight:400;line-height:1.2em}.postbox .inside .pronamic-pay-status-widget{margin:-12px}.pronamic-pay-status-list{margin-bottom:0;overflow:hidden}.pronamic-pay-status-list li{border-top:1px solid #eee;-webkit-box-sizing:border-box;box-sizing:border-box;color:#aaa;float:left;margin:0;padding:0;width:50%}.pronamic-pay-status-list li a{color:#aaa;display:block;font-size:12px;padding:9px 12px;position:relative;-webkit-transition:color .5s ease;transition:color .5s ease}.pronamic-pay-status-list li a strong{color:#0073aa;display:block;font-size:18px;font-weight:400;line-height:1.2em}.pronamic-pay-status-list li a:hover,.pronamic-pay-status-list li a:hover:before,.pronamic-pay-status-list li a:hover strong{color:#00a0d2}.pronamic-pay-status-list li:first-child{border-top:0;width:100%}.pronamic-pay-status-list li:nth-child(2n){border-right:1px solid #eee}body.post-type-pronamic_pay_subscr #post-body-content,body.post-type-pronamic_payment #post-body-content{margin-bottom:0}.pronamic-pay-form-control-lg,.pronamic-pay-shortcode-input{width:100%}.pronamic-pay-form-control-file-button [type=file]{border:0;clip:rect(0,0,0,0);margin:-1px;padding:0;overflow:hidden;position:absolute;width:1px;height:1px}.pronamic-pay-icon{position:relative;text-indent:-9999px;width:1em;height:1em}.pronamic-pay-icon:after{content:"\f10b";display:block;font-family:Pronamic Pay Icons;position:absolute;top:0;left:0;speak:none;text-indent:0;width:100%;height:100%}.pronamic-pay-icon-pending:after{color:#ffba00;content:"\f10a"}.pronamic-pay-icon-cancelled:after{color:#a00;content:"\f106"}.pronamic-pay-icon-processing:after{color:#73a724;content:"\f10b"}.pronamic-pay-icon-completed:after{color:#2ea2cc;content:"\f107"}.pronamic-pay-icon-refunded:after{color:#999;content:"\f10c"}.pronamic-pay-icon-failed:after{color:#d0c21f;content:"\f108"}.pronamic-pay-icon-on-hold:after{color:#999;content:"\f109"}.pronamic-pay-icon-recurring:after{color:#999;content:"\f105"}.pronamic-pay-icon-recurring-first:after{color:#2ea2cc;content:"\f105"}.pronamic-pay-icon-question-mark:after{color:#999;content:"\f104"}.pronamic-pay-payment-methods.form-table.widefat{border-right:0;border-bottom:0;border-left:0;margin:-15px -10px;width:calc(100% + 20px)}.pronamic-pay-payment-methods thead th:first-of-type{width:60%}.pronamic-pay-payment-methods .pronamic-pay-icon{line-height:inherit}.pronamic-pay-payment-methods .pronamic-pay-icon-completed:after{color:#73a724}.pronamic-pay-payment-methods .pronamic-pay-icon-cancelled:after{color:#aaa}@media screen and (max-width:782px){.pronamic-pay-payment-methods.form-table th{display:table-cell}.pronamic-pay-payment-methods.form-table th:first-of-type{width:50%}.pronamic-pay-payment-methods.form-table td{display:table-cell}}.gateway-config-section-header h4{margin:0}.gateway-config-section-header p{margin:0 0 1em}.gateway-config-section-header p:last-child{margin-bottom:0}.pronamic-pay-test-payment-method td label{display:none}#pronamic_payment_log.postbox .inside{margin:0;padding:0}#pronamic_payment_log .comments-box{border:0}#pronamic_subscription.postbox input[name=pronamic_subscription_amount]{vertical-align:initial}#pronamic_payment_update .inside,#pronamic_subscription_update .inside{margin:0;padding:0}.pronamic-pay-inner{margin:6px 0 0;padding:0 12px 12px}.pronamic-pay-major-actions{background:#f5f5f5;border-top:1px solid #ddd;padding:10px}.pronamic-pay-action{float:right;text-align:right}.pronamic-pay-settings select{width:25em}.pronamic-pay-table-responsive{overflow-x:auto}.pronamic-pay-table thead th{font-weight:700}.pronamic-pay-table .deprecated a,.pronamic-pay-table .deprecated td{color:#aaa}.pronamic-pay-table td p{margin:0 0 1em}.pronamic-pay-table td p:last-child{margin-bottom:0}.postbox .pronamic-pay-table{border:0}.form-table .even,.pronamic-pay-table-striped tbody tr:nth-of-type(odd){background:#f9f9f9}#pronamic_payment .form-table td a{display:inline-block;overflow:hidden;width:350px;text-overflow:ellipsis;white-space:nowrap}.pronamic-pay-status-table{margin-top:2em}.pronamic-pay-status-table tbody th:first-child{width:20%}.widefat .column-pronamic_payment_status,.widefat .column-pronamic_payment_subscription,.widefat .column-pronamic_subscription_status{width:1em}.widefat .column-pronamic_payment_method,.widefat .column-pronamic_subscription_method{width:2.5em}@media only screen and (max-width:782px){.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status{display:table-cell}.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status:before,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription:before,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status:before,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status:before,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription:before,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status:before{display:none}.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_subscription_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_subscription_status{display:table-cell!important}}.pronamic-pay-tabs-items{border-bottom:1px solid #e5e5e5;display:block;float:left;margin:3px 0 0;width:100%}.pronamic-pay-tabs-items li{background:#e5e5e5;border-right:1px solid #e5e5e5;border-left:1px solid #e5e5e5;cursor:pointer;display:block;float:left;margin:0 5px -1px 0;padding:8px 15px}.pronamic-pay-tabs-items li.active{background:#fff;border-top:3px solid #008ec2;margin-top:-3px}.admin-color-fresh .pronamic-pay-tabs-items li.active{border-top-color:#2271b1}.admin-color-light .pronamic-pay-tabs-items li.active{border-top-color:#888}.admin-color-modern .pronamic-pay-tabs-items li.active{border-top-color:#3858e9}.admin-color-blue .pronamic-pay-tabs-items li.active{border-top-color:#096484}.admin-color-coffee .pronamic-pay-tabs-items li.active{border-top-color:#c7a589}.admin-color-ectoplasm .pronamic-pay-tabs-items li.active{border-top-color:#a3b745}.admin-color-midnight .pronamic-pay-tabs-items li.active{border-top-color:#e14d43}.admin-color-ocean .pronamic-pay-tabs-items li.active{border-top-color:#9ebaa0}.admin-color-sunrise .pronamic-pay-tabs-items li.active{border-top-color:#dd823b}.pronamic-pay-tab{border:1px solid #e5e5e5;border-top:0;clear:both}.pronamic-pay-tab .form-table{margin-top:0}.pronamic-pay-tab .form-table th{padding-left:10px}.pronamic-pay-tab-block{padding:15px 10px}@media only screen and (max-width:960px){.pronamic-pay-tabs-items{display:none}.pronamic-pay-tab,.pronamic-pay-tab .form-table{border:0}}@media only screen and (max-width:782px){.pronamic-pay-tab .form-table td,.pronamic-pay-tab .form-table th{padding:11px}}.pronamic-pay-text-success{color:green}.pronamic-pay-text-danger{color:red}.pronamic-pay-text-warning{color:orange}:not(a).pronamic-pay-tip{color:#777;cursor:help}.form-table th .pronamic-pay-tip{float:right}.pronamic-pay-cloack{display:none} +.pronamic-pay-btn-link{line-height:26px;padding:0 10px 1px}.postbox .pronamic-pay-chart-with-sidebar{padding:12px 12px 12px 249px}.pronamic-pay-chart-sidebar{float:left;margin-left:-237px;width:225px}.pronamic-pay-chart-legend{background:#fff;border-color:#e5e5e5;border-style:solid;border-width:1px 0 0 1px;list-style:none;margin:0 0 1em;padding:0}.pronamic-pay-chart-legend li{border-right:5px solid #aaa;-webkit-box-shadow:inset 0 -1px 0 0 #e5e5e5;box-shadow:inset 0 -1px 0 0 #e5e5e5;color:#aaa;display:block;margin:0;padding:1em;-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transition-property:border,padding,-webkit-box-shadow;transition-property:border,padding,-webkit-box-shadow;transition-property:border,box-shadow,padding;transition-property:border,box-shadow,padding,-webkit-box-shadow}.pronamic-pay-chart-legend li.completed-count{border-right-color:#dbe1e3}.pronamic-pay-chart-legend li.pending-sum{border-right-color:#b1d4ea}.pronamic-pay-chart-legend li.completed-sum{border-right-color:#3498db}.pronamic-pay-chart-legend li.cancelled-sum{border-right-color:#f1c40f}.pronamic-pay-chart-legend li.expired-sum{border-right-color:#dbe1e3}.pronamic-pay-chart-legend li.failed-sum{border-right-color:#e74c3c}.pronamic-pay-chart-legend li:hover{border-right-color:#23282f;-webkit-box-shadow:inset 0 -1px 0 0 #e5e5e5,inset 300px 0 0 #f9f9f9;box-shadow:inset 0 -1px 0 0 #e5e5e5,inset 300px 0 0 #f9f9f9;padding-left:1.5em}.pronamic-pay-chart-legend strong{color:#444;display:block;font-size:1.618em;font-weight:400;line-height:1.2em}.postbox .inside .pronamic-pay-status-widget{margin:-12px}.pronamic-pay-status-list{margin-bottom:0;overflow:hidden}.pronamic-pay-status-list li{border-top:1px solid #eee;-webkit-box-sizing:border-box;box-sizing:border-box;color:#aaa;float:left;margin:0;padding:0;width:50%}.pronamic-pay-status-list li a{color:#aaa;display:block;font-size:12px;padding:9px 12px;position:relative;-webkit-transition:color .5s ease;transition:color .5s ease}.pronamic-pay-status-list li a strong{color:#0073aa;display:block;font-size:18px;font-weight:400;line-height:1.2em}.pronamic-pay-status-list li a:hover,.pronamic-pay-status-list li a:hover:before,.pronamic-pay-status-list li a:hover strong{color:#00a0d2}.pronamic-pay-status-list li:first-child{border-top:0;width:100%}.pronamic-pay-status-list li:nth-child(2n){border-right:1px solid #eee}body.post-type-pronamic_pay_subscr #post-body-content,body.post-type-pronamic_payment #post-body-content{margin-bottom:0}.pronamic-pay-form-control-lg,.pronamic-pay-shortcode-input{width:100%}.pronamic-pay-form-control-file-button [type=file]{border:0;clip:rect(0,0,0,0);margin:-1px;padding:0;overflow:hidden;position:absolute;width:1px;height:1px}.pronamic-pay-icon{position:relative;text-indent:-9999px;width:1em;height:1em}.pronamic-pay-icon:after{content:"\f10b";display:block;font-family:Pronamic Pay Icons;position:absolute;top:0;left:0;speak:none;text-indent:0;width:100%;height:100%}.pronamic-pay-icon-pending:after{color:#ffba00;content:"\f10a"}.pronamic-pay-icon-cancelled:after{color:#a00;content:"\f106"}.pronamic-pay-icon-processing:after{color:#73a724;content:"\f10b"}.pronamic-pay-icon-completed:after{color:#2ea2cc;content:"\f107"}.pronamic-pay-icon-refunded:after{color:#999;content:"\f10c"}.pronamic-pay-icon-failed:after{color:#d0c21f;content:"\f108"}.pronamic-pay-icon-on-hold:after{color:#999;content:"\f109"}.pronamic-pay-icon-recurring:after{color:#999;content:"\f105"}.pronamic-pay-icon-recurring-first:after{color:#2ea2cc;content:"\f105"}.pronamic-pay-icon-question-mark:after{color:#999;content:"\f104"}.pronamic-pay-payment-methods.form-table.widefat{border-right:0;border-bottom:0;border-left:0;margin:-15px -10px;width:calc(100% + 20px)}.pronamic-pay-payment-methods thead th:first-of-type{width:60%}.pronamic-pay-payment-methods .pronamic-pay-icon{line-height:inherit}.pronamic-pay-payment-methods .pronamic-pay-icon-completed:after{color:#73a724}.pronamic-pay-payment-methods .pronamic-pay-icon-cancelled:after{color:#aaa}@media screen and (max-width:782px){.pronamic-pay-payment-methods.form-table th{display:table-cell}.pronamic-pay-payment-methods.form-table th:first-of-type{width:50%}.pronamic-pay-payment-methods.form-table td{display:table-cell}}.gateway-config-section-header h4{margin:0}.gateway-config-section-header p{margin:0 0 1em}.gateway-config-section-header p:last-child{margin-bottom:0}.pronamic-pay-test-payment-method td label{display:none}#pronamic_payment_log.postbox .inside{margin:0;padding:0}#pronamic_payment_log .comments-box{border:0}#pronamic_subscription.postbox input[name=pronamic_subscription_amount]{vertical-align:initial}#pronamic_payment_update .inside,#pronamic_subscription_update .inside{margin:0;padding:0}.pronamic-pay-inner{margin:6px 0 0}.pronamic-pay-major-actions{background:#f5f5f5;border-top:1px solid #ddd;padding:10px}.pronamic-pay-action{float:right;text-align:right}#pronamic-pay-next-payment-date-display,#pronamic-pay-post-status-display{font-weight:600}#pronamic-pay-next-payment-date-input,#pronamic-pay-post-status-input{margin-top:3px}.pronamic-pay-settings select{width:25em}.pronamic-pay-table-responsive{overflow-x:auto}.pronamic-pay-table thead th{font-weight:700}.pronamic-pay-table .deprecated a,.pronamic-pay-table .deprecated td{color:#aaa}.pronamic-pay-table td p{margin:0 0 1em}.pronamic-pay-table td p:last-child{margin-bottom:0}.postbox .pronamic-pay-table{border:0}.form-table .even,.pronamic-pay-table-striped tbody tr:nth-of-type(odd){background:#f9f9f9}#pronamic_payment .form-table td a{display:inline-block;overflow:hidden;width:350px;text-overflow:ellipsis;white-space:nowrap}.pronamic-pay-status-table{margin-top:2em}.pronamic-pay-status-table tbody th:first-child{width:20%}.widefat .column-pronamic_payment_status,.widefat .column-pronamic_payment_subscription,.widefat .column-pronamic_subscription_status{width:1em}.widefat .column-pronamic_payment_method,.widefat .column-pronamic_subscription_method{width:2.5em}@media only screen and (max-width:782px){.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status{display:table-cell}.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status:before,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription:before,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status:before,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_status:before,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_payment_subscription:before,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items) td:not(.column-primary).column-pronamic_subscription_status:before{display:none}.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_pay_subscr:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_subscription_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_status,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_payment_subscription,.wp-list-table tr.type-pronamic_payment:not(.inline-edit-row):not(.no-items).is-expanded td:not(.hidden).column-pronamic_subscription_status{display:table-cell!important}}.pronamic-pay-tabs-items{border-bottom:1px solid #e5e5e5;display:block;float:left;margin:3px 0 0;width:100%}.pronamic-pay-tabs-items li{background:#e5e5e5;border-right:1px solid #e5e5e5;border-left:1px solid #e5e5e5;cursor:pointer;display:block;float:left;margin:0 5px -1px 0;padding:8px 15px}.pronamic-pay-tabs-items li.active{background:#fff;border-top:3px solid #008ec2;margin-top:-3px}.admin-color-fresh .pronamic-pay-tabs-items li.active{border-top-color:#2271b1}.admin-color-light .pronamic-pay-tabs-items li.active{border-top-color:#888}.admin-color-modern .pronamic-pay-tabs-items li.active{border-top-color:#3858e9}.admin-color-blue .pronamic-pay-tabs-items li.active{border-top-color:#096484}.admin-color-coffee .pronamic-pay-tabs-items li.active{border-top-color:#c7a589}.admin-color-ectoplasm .pronamic-pay-tabs-items li.active{border-top-color:#a3b745}.admin-color-midnight .pronamic-pay-tabs-items li.active{border-top-color:#e14d43}.admin-color-ocean .pronamic-pay-tabs-items li.active{border-top-color:#9ebaa0}.admin-color-sunrise .pronamic-pay-tabs-items li.active{border-top-color:#dd823b}.pronamic-pay-tab{border:1px solid #e5e5e5;border-top:0;clear:both}.pronamic-pay-tab .form-table{margin-top:0}.pronamic-pay-tab .form-table th{padding-left:10px}.pronamic-pay-tab-block{padding:15px 10px}@media only screen and (max-width:960px){.pronamic-pay-tabs-items{display:none}.pronamic-pay-tab,.pronamic-pay-tab .form-table{border:0}}@media only screen and (max-width:782px){.pronamic-pay-tab .form-table td,.pronamic-pay-tab .form-table th{padding:11px}}.pronamic-pay-text-success{color:green}.pronamic-pay-text-danger{color:red}.pronamic-pay-text-warning{color:orange}:not(a).pronamic-pay-tip{color:#777;cursor:help}.form-table th .pronamic-pay-tip{float:right}.pronamic-pay-cloack{display:none} From cd9e2facdb0645f2eef5d614f559dfcb65fc2a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 1 Apr 2022 11:51:52 +0200 Subject: [PATCH 54/87] Also remove time from next payment date of WooCommerce subscriptions. --- views/meta-box-subscription-payments.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/meta-box-subscription-payments.php b/views/meta-box-subscription-payments.php index 458543d8..33449c1f 100644 --- a/views/meta-box-subscription-payments.php +++ b/views/meta-box-subscription-payments.php @@ -88,7 +88,7 @@ sprintf( /* translators: %s: next payment date */ __( 'Will be created on %s', 'pronamic_ideal' ), - \esc_html( $next_payment_date->format_i18n() ) + \esc_html( $next_payment_date->format_i18n( __( 'D j M Y', 'pronamic_ideal' ) ) ) ) ); From 3c8d911c9f856e8c918340a8db4127cc1d4aa43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Fri, 1 Apr 2022 12:06:12 +0200 Subject: [PATCH 55/87] Update status class names in payment update meta box. --- views/meta-box-payment-update.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/meta-box-payment-update.php b/views/meta-box-payment-update.php index d8b836d8..b3f5dfd8 100644 --- a/views/meta-box-payment-update.php +++ b/views/meta-box-payment-update.php @@ -50,14 +50,14 @@ ?> - + -
    +
    - @@ -120,15 +119,6 @@ ?> - From 1bb1c3075da8a815ae02e76d119c09a8d39e8c98 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 09:42:29 +0200 Subject: [PATCH 74/87] No longer store next date in phase JSON. --- src/Subscriptions/SubscriptionPhase.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionPhase.php b/src/Subscriptions/SubscriptionPhase.php index b4a0b924..1f54eb9d 100644 --- a/src/Subscriptions/SubscriptionPhase.php +++ b/src/Subscriptions/SubscriptionPhase.php @@ -534,7 +534,6 @@ public function jsonSerialize() { 'sequence_number' => $this->get_sequence_number(), 'start_date' => $this->start_date->format( \DATE_ATOM ), 'end_date' => ( null === $this->end_date ) ? null : $this->end_date->format( \DATE_ATOM ), - 'next_date' => ( null === $this->next_date ) ? null : $this->next_date->format( \DATE_ATOM ), 'interval' => $this->interval->get_specification(), 'amount' => $this->amount->jsonSerialize(), // Numbers. From b53913ead67f723188d1422ce04197b4ecc42208 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 09:46:09 +0200 Subject: [PATCH 75/87] Store and load next payment date. --- src/Subscriptions/Subscription.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Subscriptions/Subscription.php b/src/Subscriptions/Subscription.php index 9b644568..e0364b61 100644 --- a/src/Subscriptions/Subscription.php +++ b/src/Subscriptions/Subscription.php @@ -593,6 +593,12 @@ public static function from_json( $json, $subscription = null ) { $subscription->set_activated_at( $activated_at ); + if ( \property_exists( $json, 'next_payment_date' ) ) { + if ( null !== $json->next_payment_date ) { + $subscription->set_next_payment_date( new DateTimeImmutable( $json->next_payment_date ) ); + } + } + return $subscription; } @@ -614,6 +620,8 @@ public function get_json() { $properties['activated_at'] = $this->get_activated_at()->format( \DATE_ATOM ); + $properties['next_payment_date'] = ( null === $this->next_payment_date ) ? null : $this->next_payment_date->format( \DATE_ATOM ); + $object = (object) $properties; return $object; From 3580600eadcfcd7eb36e16409b6492c375f9c326 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 10:05:08 +0200 Subject: [PATCH 76/87] Update subscription.json --- tests/json/subscription.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/json/subscription.json b/tests/json/subscription.json index 0a6ea04a..4ffe46af 100644 --- a/tests/json/subscription.json +++ b/tests/json/subscription.json @@ -2,5 +2,6 @@ "id": 1, "mode": "live", "phases": [], - "activated_at": "2005-05-05T00:00:00+00:00" + "activated_at": "2005-05-05T00:00:00+00:00", + "next_payment_date": null } From 221de86adde562fce78a3827ace11eab80a5de6f Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 10:18:45 +0200 Subject: [PATCH 77/87] Update SubscriptionPhase.php --- src/Subscriptions/SubscriptionPhase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionPhase.php b/src/Subscriptions/SubscriptionPhase.php index 1f54eb9d..829ad655 100644 --- a/src/Subscriptions/SubscriptionPhase.php +++ b/src/Subscriptions/SubscriptionPhase.php @@ -225,7 +225,7 @@ public function get_next_date() { * @return void */ public function set_next_date( $next_date ) { - $this->next_date = ( null === $next_date ) ? null : DateTimeImmutable::create_from_interface( $next_date ); + $this->subscription->set_next_payment_date( $next_date ); } /** From 211fbf78e727730c3a32af2e69ef0270601f0b30 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 10:38:50 +0200 Subject: [PATCH 78/87] Fix test. --- src/Subscriptions/SubscriptionPhase.php | 2 +- src/Subscriptions/SubscriptionPhasesTrait.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionPhase.php b/src/Subscriptions/SubscriptionPhase.php index 829ad655..3a66c9a5 100644 --- a/src/Subscriptions/SubscriptionPhase.php +++ b/src/Subscriptions/SubscriptionPhase.php @@ -215,7 +215,7 @@ public function get_next_date() { /** * Ok. */ - return $this->next_date; + return $this->subscription->get_next_payment_date(); } /** diff --git a/src/Subscriptions/SubscriptionPhasesTrait.php b/src/Subscriptions/SubscriptionPhasesTrait.php index 4fa39945..b5dc463c 100644 --- a/src/Subscriptions/SubscriptionPhasesTrait.php +++ b/src/Subscriptions/SubscriptionPhasesTrait.php @@ -57,6 +57,10 @@ public function set_phases( $phases ) { public function add_phase( SubscriptionPhase $phase ) { $this->phases[] = $phase; + if ( null === $this->next_payment_date ) { + $this->next_payment_date = $phase->get_start_date(); + } + $phase->set_sequence_number( \count( $this->phases ) ); } From 32de2376442b00b5e180c27e20129fd19bbc5d3f Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 11:02:17 +0200 Subject: [PATCH 79/87] Fix tests. --- src/Subscriptions/Subscription.php | 8 ++++++++ tests/src/Subscriptions/SubscriptionPhasesTraitTest.php | 6 ++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Subscriptions/Subscription.php b/src/Subscriptions/Subscription.php index e0364b61..2a1c6477 100644 --- a/src/Subscriptions/Subscription.php +++ b/src/Subscriptions/Subscription.php @@ -423,6 +423,14 @@ public function get_next_payment_date() { * @return void */ public function set_next_payment_date( $date ) { + $end_date = $this->get_end_date(); + + if ( null !== $end_date && $date >= $end_date ) { + $this->next_payment_date = null; + + return; + } + $this->next_payment_date = ( null === $date ) ? null : DateTimeImmutable::create_from_interface( $date ); } diff --git a/tests/src/Subscriptions/SubscriptionPhasesTraitTest.php b/tests/src/Subscriptions/SubscriptionPhasesTraitTest.php index f511f265..2c22eed3 100644 --- a/tests/src/Subscriptions/SubscriptionPhasesTraitTest.php +++ b/tests/src/Subscriptions/SubscriptionPhasesTraitTest.php @@ -80,14 +80,12 @@ public function test_current_period_definition() { $subscription = $this->new_subscription(); $phase_1 = $this->new_phase( $subscription ); + $phase_2 = $this->new_phase( $subscription ); + $phase_3 = $this->new_phase( $subscription ); $phase_1->set_total_periods( 1 ); $phase_1->set_periods_created( 1 ); - $phase_2 = $this->new_phase( $subscription ); - - $phase_3 = $this->new_phase( $subscription ); - $current_phase = $subscription->get_current_phase(); $this->assertEquals( $phase_2, $current_phase ); From 964c0275ccddb5b4777e5ba81a87262e7335e7e6 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 11:07:12 +0200 Subject: [PATCH 80/87] Remove subscription phases trait. --- src/Subscriptions/Subscription.php | 239 +++++++++++++++- src/Subscriptions/SubscriptionPhasesTrait.php | 260 ------------------ .../SubscriptionPhasesTraitTest.php | 117 -------- tests/src/Subscriptions/SubscriptionTest.php | 93 +++++++ 4 files changed, 330 insertions(+), 379 deletions(-) delete mode 100644 src/Subscriptions/SubscriptionPhasesTrait.php delete mode 100644 tests/src/Subscriptions/SubscriptionPhasesTraitTest.php diff --git a/src/Subscriptions/Subscription.php b/src/Subscriptions/Subscription.php index 2a1c6477..8a9072a4 100644 --- a/src/Subscriptions/Subscription.php +++ b/src/Subscriptions/Subscription.php @@ -14,6 +14,7 @@ use Pronamic\WordPress\DateTime\DateTime; use Pronamic\WordPress\DateTime\DateTimeInterface; use Pronamic\WordPress\DateTime\DateTimeImmutable; +use Pronamic\WordPress\Money\Money; use Pronamic\WordPress\Pay\Payments\PaymentInfo; use Pronamic\WordPress\Pay\Payments\PaymentStatus; use Pronamic\WordPress\Pay\Payments\Payment; @@ -27,8 +28,6 @@ * @since 1.0.0 */ class Subscription extends PaymentInfo implements \JsonSerializable { - use SubscriptionPhasesTrait; - /** * The status of this subscription, for example 'Success'. * @@ -48,6 +47,13 @@ class Subscription extends PaymentInfo implements \JsonSerializable { */ private $activated_at; + /** + * Phases. + * + * @var SubscriptionPhase[] + */ + private $phases = array(); + /** * Construct and initialize subscription object. * @@ -663,4 +669,233 @@ public function get_activated_at() { public function set_activated_at( DateTime $activated_at ) { $this->activated_at = $activated_at; } + + /** + * Get phases. + * + * @return array + */ + public function get_phases() { + return $this->phases; + } + + /** + * Set phases. + * + * @param array $phases Phases. + * @return void + */ + public function set_phases( $phases ) { + $this->phases = $phases; + } + + /** + * Add the specified phase to this subscription. + * + * @param SubscriptionPhase $phase Phase. + * @return void + */ + public function add_phase( SubscriptionPhase $phase ) { + $this->phases[] = $phase; + + if ( null === $this->next_payment_date ) { + $this->next_payment_date = $phase->get_start_date(); + } + + $phase->set_sequence_number( \count( $this->phases ) ); + } + + /** + * Create new phase for this subscription. + * + * @param \DateTimeInterface $start_date Start date. + * @param string $interval_spec Interval specification. + * @param Money $amount Amount. + * @return SubscriptionPhase + */ + public function new_phase( $start_date, $interval_spec, $amount ) { + $interval = new SubscriptionInterval( $interval_spec ); + + $phase = new SubscriptionPhase( $this, $start_date, $interval, $amount ); + + $this->add_phase( $phase ); + + return $phase; + } + + /** + * Check if all the periods within the subscription phases are created. + * + * @return bool True if all created, false otherwise. + */ + public function all_periods_created() { + foreach ( $this->phases as $phase ) { + if ( ! $phase->all_periods_created() ) { + return false; + } + } + + return true; + } + + /** + * Check if this subscription is infinite. + * + * @return bool True if infinite, false otherwise. + */ + public function is_infinite() { + foreach ( $this->phases as $phase ) { + if ( $phase->is_infinite() ) { + return true; + } + } + + return false; + } + + /** + * Get current phase or null if all completed. + * + * @return SubscriptionPhase|null + */ + public function get_current_phase() { + foreach ( $this->phases as $phase ) { + if ( $phase->all_periods_created() ) { + continue; + } + + if ( $phase->is_canceled() ) { + continue; + } + + return $phase; + } + + return null; + } + + /** + * Get phase for display. + * + * @return SubscriptionPhase|null + */ + public function get_display_phase() { + // Get first uncompleted regular phase. + foreach ( $this->phases as $phase ) { + // Skip trial phases. + if ( $phase->is_trial() ) { + continue; + } + + // Skip prorated phases. + if ( $phase->is_prorated() ) { + continue; + } + + if ( ! $phase->all_periods_created() ) { + return $phase; + } + } + + // Get first regular phase. + foreach ( $this->phases as $phase ) { + // Skip trial phases. + if ( $phase->is_trial() ) { + continue; + } + + // Skip prorated phases. + if ( $phase->is_prorated() ) { + continue; + } + + return $phase; + } + + // Get first phase. + foreach ( $this->phases as $phase ) { + return $phase; + } + + return null; + } + + /** + * Check if subscription is in a trial period. + * + * @return bool True if current period definition is a trial, false otherwise. + */ + public function in_trial_period() { + $current_phase = $this->get_current_phase(); + + if ( null === $current_phase ) { + return false; + } + + return $current_phase->is_trial(); + } + + /** + * Get the next period. + * + * @return SubscriptionPeriod|null + */ + public function get_next_period() { + $current_phase = $this->get_current_phase(); + + if ( null === $current_phase ) { + return null; + } + + return $current_phase->get_next_period(); + } + + /** + * Next period. + * + * @return SubscriptionPeriod|null + */ + public function next_period() { + $current_phase = $this->get_current_phase(); + + if ( null === $current_phase ) { + return null; + } + + return $current_phase->next_period(); + } + + /** + * Get phase by sequence number. + * + * @param int $sequence_number Sequence number. + * @return SubscriptionPhase|null + */ + public function get_phase_by_sequence_number( $sequence_number ) { + /** + * PHP arrays are zero-based indexed, sequence number starts from 1. + */ + $key = $sequence_number - 1; + + if ( array_key_exists( $key, $this->phases ) ) { + return $this->phases[ $key ]; + } + + return null; + } + + /** + * Get end date. + * + * @return DateTimeImmutable|null + */ + public function get_end_date() { + $end_phase = \end( $this->phases ); + + if ( false === $end_phase ) { + return null; + } + + return $end_phase->get_end_date(); + } } diff --git a/src/Subscriptions/SubscriptionPhasesTrait.php b/src/Subscriptions/SubscriptionPhasesTrait.php deleted file mode 100644 index b5dc463c..00000000 --- a/src/Subscriptions/SubscriptionPhasesTrait.php +++ /dev/null @@ -1,260 +0,0 @@ - - * @copyright 2005-2022 Pronamic - * @license GPL-3.0-or-later - * @package Pronamic\WordPress\Pay\Subscriptions - */ - -namespace Pronamic\WordPress\Pay\Subscriptions; - -use Pronamic\WordPress\DateTime\DateTime; -use Pronamic\WordPress\DateTime\DateTimeImmutable; -use Pronamic\WordPress\Money\Money; - -/** - * Subscription Phases Trait - * - * @author Remco Tolsma - * @version 2.5.0 - * @since 2.5.0 - */ -trait SubscriptionPhasesTrait { - /** - * Phases. - * - * @var SubscriptionPhase[] - */ - private $phases = array(); - - /** - * Get phases. - * - * @return array - */ - public function get_phases() { - return $this->phases; - } - - /** - * Set phases. - * - * @param array $phases Phases. - * @return void - */ - public function set_phases( $phases ) { - $this->phases = $phases; - } - - /** - * Add the specified phase to this subscription. - * - * @param SubscriptionPhase $phase Phase. - * @return void - */ - public function add_phase( SubscriptionPhase $phase ) { - $this->phases[] = $phase; - - if ( null === $this->next_payment_date ) { - $this->next_payment_date = $phase->get_start_date(); - } - - $phase->set_sequence_number( \count( $this->phases ) ); - } - - /** - * Create new phase for this subscription. - * - * @param \DateTimeInterface $start_date Start date. - * @param string $interval_spec Interval specification. - * @param Money $amount Amount. - * @return SubscriptionPhase - */ - public function new_phase( $start_date, $interval_spec, $amount ) { - $interval = new SubscriptionInterval( $interval_spec ); - - $phase = new SubscriptionPhase( $this, $start_date, $interval, $amount ); - - $this->add_phase( $phase ); - - return $phase; - } - - /** - * Check if all the periods within the subscription phases are created. - * - * @return bool True if all created, false otherwise. - */ - public function all_periods_created() { - foreach ( $this->phases as $phase ) { - if ( ! $phase->all_periods_created() ) { - return false; - } - } - - return true; - } - - /** - * Check if this subscription is infinite. - * - * @return bool True if infinite, false otherwise. - */ - public function is_infinite() { - foreach ( $this->phases as $phase ) { - if ( $phase->is_infinite() ) { - return true; - } - } - - return false; - } - - /** - * Get current phase or null if all completed. - * - * @return SubscriptionPhase|null - */ - public function get_current_phase() { - foreach ( $this->phases as $phase ) { - if ( $phase->all_periods_created() ) { - continue; - } - - if ( $phase->is_canceled() ) { - continue; - } - - return $phase; - } - - return null; - } - - /** - * Get phase for display. - * - * @return SubscriptionPhase|null - */ - public function get_display_phase() { - // Get first uncompleted regular phase. - foreach ( $this->phases as $phase ) { - // Skip trial phases. - if ( $phase->is_trial() ) { - continue; - } - - // Skip prorated phases. - if ( $phase->is_prorated() ) { - continue; - } - - if ( ! $phase->all_periods_created() ) { - return $phase; - } - } - - // Get first regular phase. - foreach ( $this->phases as $phase ) { - // Skip trial phases. - if ( $phase->is_trial() ) { - continue; - } - - // Skip prorated phases. - if ( $phase->is_prorated() ) { - continue; - } - - return $phase; - } - - // Get first phase. - foreach ( $this->phases as $phase ) { - return $phase; - } - - return null; - } - - /** - * Check if subscription is in a trial period. - * - * @return bool True if current period definition is a trial, false otherwise. - */ - public function in_trial_period() { - $current_phase = $this->get_current_phase(); - - if ( null === $current_phase ) { - return false; - } - - return $current_phase->is_trial(); - } - - /** - * Get the next period. - * - * @return SubscriptionPeriod|null - */ - public function get_next_period() { - $current_phase = $this->get_current_phase(); - - if ( null === $current_phase ) { - return null; - } - - return $current_phase->get_next_period(); - } - - /** - * Next period. - * - * @return SubscriptionPeriod|null - */ - public function next_period() { - $current_phase = $this->get_current_phase(); - - if ( null === $current_phase ) { - return null; - } - - return $current_phase->next_period(); - } - - /** - * Get phase by sequence number. - * - * @param int $sequence_number Sequence number. - * @return SubscriptionPhase|null - */ - public function get_phase_by_sequence_number( $sequence_number ) { - /** - * PHP arrays are zero-based indexed, sequence number starts from 1. - */ - $key = $sequence_number - 1; - - if ( array_key_exists( $key, $this->phases ) ) { - return $this->phases[ $key ]; - } - - return null; - } - - /** - * Get end date. - * - * @return DateTimeImmutable|null - */ - public function get_end_date() { - $end_phase = \end( $this->phases ); - - if ( false === $end_phase ) { - return null; - } - - return $end_phase->get_end_date(); - } -} diff --git a/tests/src/Subscriptions/SubscriptionPhasesTraitTest.php b/tests/src/Subscriptions/SubscriptionPhasesTraitTest.php deleted file mode 100644 index 2c22eed3..00000000 --- a/tests/src/Subscriptions/SubscriptionPhasesTraitTest.php +++ /dev/null @@ -1,117 +0,0 @@ - - * @copyright 2005-2022 Pronamic - * @license GPL-3.0-or-later - * @package Pronamic\WordPress\Pay\Payments - */ - -namespace Pronamic\WordPress\Pay\Subscriptions; - -use Pronamic\WordPress\Money\Money; -use Pronamic\WordPress\Money\TaxedMoney; -use Yoast\PHPUnitPolyfills\TestCases\TestCase; - -/** - * Subscription Phases Trait Test - * - * @author Remco Tolsma - * @version 2.5.0 - */ -class SubscriptionPhasesTraitTest extends TestCase { - /** - * Create new subscription. - * - * @return Subscription - * @throws \Exception Throws exception on invalid date interval. - */ - private function new_subscription() { - $subscription = new Subscription(); - - return $subscription; - } - - /** - * New phase for subscription. - * - * @param Subscription $subscription Subscription. - * @return SubscriptionPhase - * @throws \Exception Throws exception on invalid date interval. - */ - private function new_phase( $subscription ) { - $phase = $subscription->new_phase( new \DateTimeImmutable(), 'P1W', new TaxedMoney( 50, 'EUR' ) ); - - return $phase; - } - - /** - * Test new period definition. - */ - public function test_new_period_definition() { - $subscription = $this->new_subscription(); - - $phase_1 = $this->new_phase( $subscription ); - - $this->assertInstanceOf( SubscriptionPhase::class, $phase_1 ); - - $phase_2 = $this->new_phase( $subscription ); - - $this->assertInstanceOf( SubscriptionPhase::class, $phase_2 ); - } - - /** - * Test infinite. - */ - public function test_infinite() { - $subscription = $this->new_subscription(); - - $phase_1 = $this->new_phase( $subscription ); - $phase_2 = $this->new_phase( $subscription ); - - $this->assertTrue( $subscription->is_infinite() ); - } - - /** - * Test current period definition. - */ - public function test_current_period_definition() { - $subscription = $this->new_subscription(); - - $phase_1 = $this->new_phase( $subscription ); - $phase_2 = $this->new_phase( $subscription ); - $phase_3 = $this->new_phase( $subscription ); - - $phase_1->set_total_periods( 1 ); - $phase_1->set_periods_created( 1 ); - - $current_phase = $subscription->get_current_phase(); - - $this->assertEquals( $phase_2, $current_phase ); - } - - /** - * Test in trial period. - */ - public function test_in_trial_period() { - $subscription = $this->new_subscription(); - - $phase_1 = $this->new_phase( $subscription ); - $phase_2 = $this->new_phase( $subscription ); - $phase_3 = $this->new_phase( $subscription ); - - $current_phase = $subscription->get_current_phase(); - - $this->assertFalse( $subscription->in_trial_period() ); - - $phase_1->set_trial( true ); - - $this->assertTrue( $subscription->in_trial_period() ); - - $phase_1->set_total_periods( 1 ); - $phase_1->set_periods_created( 1 ); - - $this->assertFalse( $subscription->in_trial_period() ); - } -} diff --git a/tests/src/Subscriptions/SubscriptionTest.php b/tests/src/Subscriptions/SubscriptionTest.php index 4f07b81e..cc9d6ee5 100644 --- a/tests/src/Subscriptions/SubscriptionTest.php +++ b/tests/src/Subscriptions/SubscriptionTest.php @@ -178,4 +178,97 @@ public function test_new_period() { $this->assertEquals( '2005-06-05', $period->get_end_date()->format( 'Y-m-d' ) ); $this->assertEquals( 89.95, $period->get_amount()->get_value() ); } + /** + * Create new subscription. + * + * @return Subscription + * @throws \Exception Throws exception on invalid date interval. + */ + private function new_subscription() { + $subscription = new Subscription(); + + return $subscription; + } + + /** + * New phase for subscription. + * + * @param Subscription $subscription Subscription. + * @return SubscriptionPhase + * @throws \Exception Throws exception on invalid date interval. + */ + private function new_phase( $subscription ) { + $phase = $subscription->new_phase( new \DateTimeImmutable(), 'P1W', new TaxedMoney( 50, 'EUR' ) ); + + return $phase; + } + + /** + * Test new period definition. + */ + public function test_new_period_definition() { + $subscription = $this->new_subscription(); + + $phase_1 = $this->new_phase( $subscription ); + + $this->assertInstanceOf( SubscriptionPhase::class, $phase_1 ); + + $phase_2 = $this->new_phase( $subscription ); + + $this->assertInstanceOf( SubscriptionPhase::class, $phase_2 ); + } + + /** + * Test infinite. + */ + public function test_infinite() { + $subscription = $this->new_subscription(); + + $phase_1 = $this->new_phase( $subscription ); + $phase_2 = $this->new_phase( $subscription ); + + $this->assertTrue( $subscription->is_infinite() ); + } + + /** + * Test current period definition. + */ + public function test_current_period_definition() { + $subscription = $this->new_subscription(); + + $phase_1 = $this->new_phase( $subscription ); + $phase_2 = $this->new_phase( $subscription ); + $phase_3 = $this->new_phase( $subscription ); + + $phase_1->set_total_periods( 1 ); + $phase_1->set_periods_created( 1 ); + + $current_phase = $subscription->get_current_phase(); + + $this->assertEquals( $phase_2, $current_phase ); + } + + /** + * Test in trial period. + */ + public function test_in_trial_period() { + $subscription = $this->new_subscription(); + + $phase_1 = $this->new_phase( $subscription ); + $phase_2 = $this->new_phase( $subscription ); + $phase_3 = $this->new_phase( $subscription ); + + $current_phase = $subscription->get_current_phase(); + + $this->assertFalse( $subscription->in_trial_period() ); + + $phase_1->set_trial( true ); + + $this->assertTrue( $subscription->in_trial_period() ); + + $phase_1->set_total_periods( 1 ); + $phase_1->set_periods_created( 1 ); + + $this->assertFalse( $subscription->in_trial_period() ); + } } From 7f76b3f9a0b6a8839f042f49fad6752f7ad93d18 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 11:11:41 +0200 Subject: [PATCH 81/87] Update SubscriptionsDataStoreCPT.php --- src/Subscriptions/SubscriptionsDataStoreCPT.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionsDataStoreCPT.php b/src/Subscriptions/SubscriptionsDataStoreCPT.php index d1b18f82..7e1a5e9d 100644 --- a/src/Subscriptions/SubscriptionsDataStoreCPT.php +++ b/src/Subscriptions/SubscriptionsDataStoreCPT.php @@ -617,7 +617,7 @@ protected function read_post_meta( $subscription ) { } // Set next date. - $next_date = $this->get_meta_date( $id, 'next_payment_date' ); + $next_date = $this->get_meta_date( $id, 'next_payment' ); $subscription->set_next_payment_date( $next_date ); From a5f1fe7893fe02d1ac685731d4735cfad27d5b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 11 Apr 2022 11:27:54 +0200 Subject: [PATCH 82/87] Coding standards. --- src/Subscriptions/Subscription.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Subscriptions/Subscription.php b/src/Subscriptions/Subscription.php index 8a9072a4..cf564d97 100644 --- a/src/Subscriptions/Subscription.php +++ b/src/Subscriptions/Subscription.php @@ -54,6 +54,13 @@ class Subscription extends PaymentInfo implements \JsonSerializable { */ private $phases = array(); + /** + * Next payment date. + * + * @var DateTimeImmutable|null + */ + private $next_payment_date; + /** * Construct and initialize subscription object. * @@ -425,7 +432,7 @@ public function get_next_payment_date() { /** * Set the next payment date of this subscription. * - * @param $date Date. + * @param DateTimeInterface $date Date. * @return void */ public function set_next_payment_date( $date ) { From e37c9cbd4af1480f4a1c5d4114777b679164da50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 11 Apr 2022 11:28:39 +0200 Subject: [PATCH 83/87] Update next payment date in subscription instead of current phase on manual edit. --- .../SubscriptionsDataStoreCPT.php | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Subscriptions/SubscriptionsDataStoreCPT.php b/src/Subscriptions/SubscriptionsDataStoreCPT.php index 7e1a5e9d..c7f71a1f 100644 --- a/src/Subscriptions/SubscriptionsDataStoreCPT.php +++ b/src/Subscriptions/SubscriptionsDataStoreCPT.php @@ -229,27 +229,27 @@ private function update_subscription_form_post_array( $subscription, $postarr ) $new_value = $postarr['pronamic_subscription_next_payment_date']; - $current_phase = $subscription->get_current_phase(); - - if ( null !== $current_phase && ! empty( $new_value ) && $old_value !== $new_value ) { + if ( ! empty( $new_value ) && $old_value !== $new_value ) { $new_date = new DateTimeImmutable( $new_value ); - $next_date = $current_phase->get_next_date(); + $next_payment_date = $subscription->get_next_payment_date(); - $updated_date = null === $next_date ? clone $new_date : clone $next_date; + $updated_date = null === $next_payment_date ? clone $new_date : clone $next_payment_date; $updated_date = $updated_date->setDate( (int) $new_date->format( 'Y' ), (int) $new_date->format( 'm' ), (int) $new_date->format( 'd' ) ); - $current_phase->set_next_date( $updated_date ); + if ( false !== $updated_date ) { + $subscription->set_next_payment_date( $updated_date ); - $note = \sprintf( + $note = \sprintf( /* translators: %1: old formatted date, %2: new formatted date */ - \__( 'Next payment date updated from %1$s to %2$s.', 'pronamic_ideal' ), - null === $next_date ? '' : $next_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ), - $updated_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ) - ); + \__( 'Next payment date updated from %1$s to %2$s.', 'pronamic_ideal' ), + null === $next_payment_date ? '' : $next_payment_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ), + $updated_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ) + ); - $subscription->add_note( $note ); + $subscription->add_note( $note ); + } } } } From 6ab12f2c8ebcc3e6a97745068a0ff622e6b2c56a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reu=CC=88el=20van=20der=20Steege?= Date: Mon, 11 Apr 2022 11:40:34 +0200 Subject: [PATCH 84/87] Coding standards. --- src/Subscriptions/SubscriptionsDataStoreCPT.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Subscriptions/SubscriptionsDataStoreCPT.php b/src/Subscriptions/SubscriptionsDataStoreCPT.php index c7f71a1f..38f6e231 100644 --- a/src/Subscriptions/SubscriptionsDataStoreCPT.php +++ b/src/Subscriptions/SubscriptionsDataStoreCPT.php @@ -242,7 +242,7 @@ private function update_subscription_form_post_array( $subscription, $postarr ) $subscription->set_next_payment_date( $updated_date ); $note = \sprintf( - /* translators: %1: old formatted date, %2: new formatted date */ + /* translators: %1: old formatted date, %2: new formatted date */ \__( 'Next payment date updated from %1$s to %2$s.', 'pronamic_ideal' ), null === $next_payment_date ? '' : $next_payment_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ), $updated_date->format_i18n( \__( 'D j M Y', 'pronamic_ideal' ) ) From 5677c598542ab9c89fc8ed0643f3644232486355 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 13:01:20 +0200 Subject: [PATCH 85/87] Update SubscriptionPhase.php --- src/Subscriptions/SubscriptionPhase.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Subscriptions/SubscriptionPhase.php b/src/Subscriptions/SubscriptionPhase.php index 3a66c9a5..5cbc970b 100644 --- a/src/Subscriptions/SubscriptionPhase.php +++ b/src/Subscriptions/SubscriptionPhase.php @@ -73,17 +73,6 @@ class SubscriptionPhase implements \JsonSerializable { */ private $end_date; - /** - * The start date of the next period, also known as: - * - Billing cycle anchor (billing_cycle_anchor). - * - Period anchor. - * - * @link https://stripe.com/docs/billing/subscriptions/billing-cycle - * @link https://stripe.com/docs/api/subscriptions/create#create_subscription-billing_cycle_anchor - * @var DateTimeImmutable|null - */ - private $next_date; - /** * Alignment rate. * @@ -308,14 +297,16 @@ public function set_total_periods( $total_periods ) { * @return int */ public function get_periods_created() { - if ( null === $this->next_date ) { + $next_date = $this->subscription->get_next_payment_date(); + + if ( null === $next_date ) { return 0; } $period = new \DatePeriod( new \DateTimeImmutable( $this->start_date->format( 'Y-m-d 00:00:00' ) ), $this->interval, - new \DateTimeImmutable( $this->next_date->format( 'Y-m-d 00:00:00' ) ) + new \DateTimeImmutable( $next_date->format( 'Y-m-d 00:00:00' ) ) ); return \iterator_count( $period ); From 6f5d86372426d917fe6bc1376b202d75d772122c Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 14:54:45 +0200 Subject: [PATCH 86/87] Remove publishing actions div. --- views/meta-box-subscription-update.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/views/meta-box-subscription-update.php b/views/meta-box-subscription-update.php index b99f41c3..c6e70626 100644 --- a/views/meta-box-subscription-update.php +++ b/views/meta-box-subscription-update.php @@ -32,10 +32,6 @@
    -
    -
    -
    -
    From 5417c7031b3b8e3b0f2e097878d1e54d701bf609 Mon Sep 17 00:00:00 2001 From: Remco Tolsma <869674+remcotolsma@users.noreply.github.com> Date: Mon, 11 Apr 2022 15:32:48 +0200 Subject: [PATCH 87/87] Working in 4.1.0. --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d648041..1d646843 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ This projects adheres to [Semantic Versioning](http://semver.org/) and [Keep a C ## [Unreleased][unreleased] - Updated https://github.com/pronamic/wp-pay-logos to version `1.7.1`. +## [4.1.0] - 2022-04-11 +### Added +- Added a user interface to change a subscription's next payment date. +- Added a count badge in the WordPress admin menu for the number of subscriptions on hold. + +### Changed +- The next payment date is now stored in the subscription and no longer in the subscription phases. + +### Removed +- The general / global gateway integration mode setting for test or live mode is removed. +- Sorting payments by customer or transaction number in the WordPress admin dashboard has been removed. + ## [4.0.2] - 2022-02-16 - Changed minimum PHP version requirement to `7.4` ([pronamic/wp-pronamic-pay#274](https://github.com/pronamic/wp-pronamic-pay/issues/274)). - Changed follow-up payments query to subscriptions which needed renewal in past 24 hours only. diff --git a/package.json b/package.json index 8c92b895..34876439 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@wp-pay/core", - "version": "4.0.2", + "version": "4.1.0", "description": "Core components for the WordPress payment processing library.", "repository": { "type": "git",
    - get_periods_created() ); + - ?> - - + is_trial() ? __( 'Yes', 'pronamic_ideal' ) : __( 'No', 'pronamic_ideal' ) ); + echo esc_html( $phase->is_trial() ? __( 'Yes', 'pronamic_ideal' ) : __( 'No', 'pronamic_ideal' ) ); - ?> - - + - - echo esc_html( $phase->is_prorated() ? __( 'Yes', 'pronamic_ideal' ) : __( 'No', 'pronamic_ideal' ) ); + + - + is_prorated() ? __( 'Yes', 'pronamic_ideal' ) : __( 'No', 'pronamic_ideal' ) ); + + ?> +
    - get_next_date(); - - echo esc_html( null === $next_date ? '—' : ( new \Pronamic\WordPress\DateTime\DateTime( '@' . $next_date->getTimestamp() ) )->format_i18n( __( 'D j M Y', 'pronamic_ideal' ) ) ); - - ?> -