From 6723b5d5cb835575fb30e99179b40b0d9a076185 Mon Sep 17 00:00:00 2001 From: Andrew Lima Date: Tue, 12 Nov 2024 11:05:25 +0200 Subject: [PATCH 01/12] Make next payment date translatable * ENHANCEMENT: Adjusted the `format_subscription_date` to be translatable and reworked the logic to support this. --- classes/class-pmpro-subscription.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/classes/class-pmpro-subscription.php b/classes/class-pmpro-subscription.php index 3233b3de6..f6958330e 100644 --- a/classes/class-pmpro-subscription.php +++ b/classes/class-pmpro-subscription.php @@ -783,22 +783,24 @@ private function format_subscription_date( $date, $format = 'timestamp', $local_ // Get date in WP local timezone. if ( $local_time ) { - if( 'U' === $format ){ - // When formatting using the epoch, the date must already consider the timezone offset. - // Then, first apply a simple format to add the timezone. - $date = get_date_from_gmt( $date ); + + $date = get_date_from_gmt( $date ); + + // If it's not a timestamp, conver it to one for the date_i18n function. + if ( ! is_numeric( $date ) ) { + $date = strtotime( $date ); } - return get_date_from_gmt( $date, $format ); + return date_i18n( $format, $date, true ); } - // Allow timestamps. + // If it's not a timestamp, conver it to one for the date_i18n function. if ( ! is_numeric( $date ) ) { $date = strtotime( $date ); } - // Get date in GMT timezone. - return gmdate( $format, $date ); + $date = gmdate( $date ); + return date_i18n( $format, $date, true ); } /** From 49bfc6a1d5b659f2b76ee8c0e3893fd071f343c3 Mon Sep 17 00:00:00 2001 From: Andrew Lima Date: Tue, 12 Nov 2024 11:08:26 +0200 Subject: [PATCH 02/12] Rework is_numeric. It's not needed --- classes/class-pmpro-subscription.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/classes/class-pmpro-subscription.php b/classes/class-pmpro-subscription.php index f6958330e..040d86087 100644 --- a/classes/class-pmpro-subscription.php +++ b/classes/class-pmpro-subscription.php @@ -783,14 +783,7 @@ private function format_subscription_date( $date, $format = 'timestamp', $local_ // Get date in WP local timezone. if ( $local_time ) { - - $date = get_date_from_gmt( $date ); - - // If it's not a timestamp, conver it to one for the date_i18n function. - if ( ! is_numeric( $date ) ) { - $date = strtotime( $date ); - } - + $date = strtotime( get_date_from_gmt( $date ) ); return date_i18n( $format, $date, true ); } From 12809189d93e5bd9a83371f1f4b8b2b2a32a48e1 Mon Sep 17 00:00:00 2001 From: Andrew Lima Date: Tue, 12 Nov 2024 11:10:29 +0200 Subject: [PATCH 03/12] Update class-pmpro-subscription.php --- classes/class-pmpro-subscription.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/class-pmpro-subscription.php b/classes/class-pmpro-subscription.php index 040d86087..88f21840c 100644 --- a/classes/class-pmpro-subscription.php +++ b/classes/class-pmpro-subscription.php @@ -784,7 +784,7 @@ private function format_subscription_date( $date, $format = 'timestamp', $local_ // Get date in WP local timezone. if ( $local_time ) { $date = strtotime( get_date_from_gmt( $date ) ); - return date_i18n( $format, $date, true ); + return date_i18n( $format, $date ); } // If it's not a timestamp, conver it to one for the date_i18n function. @@ -793,7 +793,7 @@ private function format_subscription_date( $date, $format = 'timestamp', $local_ } $date = gmdate( $date ); - return date_i18n( $format, $date, true ); + return date_i18n( $format, $date ); } /** From cee06265796ca71b49988f014a87b82e76ab901c Mon Sep 17 00:00:00 2001 From: Andrew Lima Date: Mon, 25 Nov 2024 15:53:32 +0200 Subject: [PATCH 04/12] Fixes to use wp_date instead --- classes/class-pmpro-subscription.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/classes/class-pmpro-subscription.php b/classes/class-pmpro-subscription.php index 88f21840c..c7c3f7c2e 100644 --- a/classes/class-pmpro-subscription.php +++ b/classes/class-pmpro-subscription.php @@ -780,20 +780,19 @@ private function format_subscription_date( $date, $format = 'timestamp', $local_ } elseif ( 'date_format' === $format ) { $format = get_option( 'date_format' ); } - // Get date in WP local timezone. if ( $local_time ) { - $date = strtotime( get_date_from_gmt( $date ) ); - return date_i18n( $format, $date ); + // wp_date() returns time in local timezone by default. + return wp_date( $format, strtotime( $date ) ); } - // If it's not a timestamp, conver it to one for the date_i18n function. + // If it's not a timestamp, convert it to one. if ( ! is_numeric( $date ) ) { $date = strtotime( $date ); } - $date = gmdate( $date ); - return date_i18n( $format, $date ); + // Get date in GMT timezone. + return wp_date( $format, $date, new DateTimezone('GMT') ); } /** From 3956e82ae0bcea9bbbf500a4bf5791619dd77689 Mon Sep 17 00:00:00 2001 From: maximilianoRicoTabo Date: Thu, 28 Nov 2024 17:15:56 -0300 Subject: [PATCH 05/12] [BUGFIX] * Copy discount link should copy the code to the clipboard instead of open edit page --- .../class-pmpro-discount-code-list-table.php | 15 ++----- js/pmpro-admin.js | 40 +++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/classes/class-pmpro-discount-code-list-table.php b/classes/class-pmpro-discount-code-list-table.php index 209aaaf4b..d4d7386b8 100644 --- a/classes/class-pmpro-discount-code-list-table.php +++ b/classes/class-pmpro-discount-code-list-table.php @@ -410,18 +410,9 @@ public function column_discount_code( $item ) { esc_html__( 'Edit', 'paid-memberships-pro' ) ), 'copy' => sprintf( - '%3$s', - esc_attr__( 'Copy', 'paid-memberships-pro' ), - esc_url( - add_query_arg( - [ - 'page' => 'pmpro-discountcodes', - 'edit' => - 1, - 'copy' => $item->id, - ], - admin_url( 'admin.php' ) - ) - ), + '', + esc_attr__( 'Copy code to the clipboard', 'paid-memberships-pro' ), + esc_attr__('pmpro_copy_discount_code button-link edit-filters', 'paid-memberships-pro'), esc_html__( 'Copy', 'paid-memberships-pro' ) ), 'delete' => sprintf( diff --git a/js/pmpro-admin.js b/js/pmpro-admin.js index 16467385d..78a15eef6 100644 --- a/js/pmpro-admin.js +++ b/js/pmpro-admin.js @@ -1002,3 +1002,43 @@ function pmpro_changeTabs( e, inputChanged ) { jQuery(document).ready(function () { jQuery('.pmpro_admin-pmpro-orders select#membership_id').select2(); }); + +jQuery(document).ready(function ($) { + /** + * Copy Discount Code to Clipboard + * + * @param {Event} event The click event + * @returns {void} + * @since TBD + */ + $('.pmpro_copy_discount_code').on('click', function (event) { + // Find first link text + const code = $(this).closest('td').find('a').first().text(); + + // Check for Clipboard API support + if ( ! navigator.clipboard ) { + console.error('Navigator Clipboard API not supported'); + return; + } + + // Create a new Blob object with the discount code + const blob = new Blob([code], { type: 'text/plain' }); + + // Create a ClipboardItem object and write the Blob to the clipboard + navigator.clipboard.write([new ClipboardItem({ 'text/plain': blob })]) + .then(() => { + // Hide copy button and show success message + $(this).hide(); + $(this).after('Copied!'); + + // Remove success message and show copy button after a delay + setTimeout(() => { + $('.success-message').remove(); + $('.pmpro_copy_discount_code').show(); + }, 3000); + }) + .catch(err => { + console.error('Failed to copy code:', err); + }); + }); +}); From 9b3d31a0b00ef138ac318a437ca7627e5e3609ae Mon Sep 17 00:00:00 2001 From: maximilianoRicoTabo Date: Mon, 16 Dec 2024 12:10:00 -0300 Subject: [PATCH 06/12] * Rename copy link to duplicate * Add button / icon that show / hide on hover / blur and let user copy code to the clipboard --- .../class-pmpro-discount-code-list-table.php | 21 +++++++++--- css/admin.css | 11 +++++++ js/pmpro-admin.js | 33 ++++++++++++++++--- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/classes/class-pmpro-discount-code-list-table.php b/classes/class-pmpro-discount-code-list-table.php index d4d7386b8..95365c86a 100644 --- a/classes/class-pmpro-discount-code-list-table.php +++ b/classes/class-pmpro-discount-code-list-table.php @@ -369,6 +369,10 @@ public function column_discount_code( $item ) { ?> code ); ?> +
sprintf( - '', - esc_attr__( 'Copy code to the clipboard', 'paid-memberships-pro' ), - esc_attr__('pmpro_copy_discount_code button-link edit-filters', 'paid-memberships-pro'), - esc_html__( 'Copy', 'paid-memberships-pro' ) + '%3$s', + esc_attr__( 'Copy', 'paid-memberships-pro' ), + esc_url( + add_query_arg( + [ + 'page' => 'pmpro-discountcodes', + 'edit' => - 1, + 'copy' => $item->id, + ], + admin_url( 'admin.php' ) + ) + ), + esc_html__( 'Duplicate', 'paid-memberships-pro' ) ), 'delete' => sprintf( '%3$s', diff --git a/css/admin.css b/css/admin.css index a79bf3f43..f1b75afa8 100644 --- a/css/admin.css +++ b/css/admin.css @@ -1647,6 +1647,17 @@ table.pmprommpu_levels tr.remove_level td {background: #F2DEDE; } -moz-osx-font-smoothing: grayscale; } +.pmpro_admin tr td button.pmpro_copy_discount_code .dashicons:not(.button .dashicons) { + padding-top: unset; + font-size: 14px; + line-height: 1.4; +} + +.pmpro_admin tr td button.pmpro_copy_discount_code:hover { + color: #043959; +} + + /** * Payment Settings */ diff --git a/js/pmpro-admin.js b/js/pmpro-admin.js index 78a15eef6..fbd07a61a 100644 --- a/js/pmpro-admin.js +++ b/js/pmpro-admin.js @@ -1004,20 +1004,45 @@ jQuery(document).ready(function () { }); jQuery(document).ready(function ($) { + + /** + * If it's mouseenter show the clipboard icon hider otherwise + * + * @param {Event} evt The event object + * @returns {void} + * @since TBD + */ + $('table.discountcodes tr').on( "mouseenter mouseleave focus", function ( evt ) { + $(this).find('td.column-discount_code .pmpro_copy_discount_code').hide(); + if (evt.type === 'mouseenter' ) { + $(this).find('.pmpro_copy_discount_code').show(); + } + }); + + /** + * If focus on the code show the clipboard icon for accessibility sake + * + * @param {Event} evt The event object + * @returns {void} + * @since TBD + */ + $('td.column-discount_code a').on( "focus", function ( evt ) { + $(this).closest( 'td' ).find( '.pmpro_copy_discount_code' ).show(); + }); + /** * Copy Discount Code to Clipboard * - * @param {Event} event The click event + * @param {Event} evt The click event * @returns {void} * @since TBD */ - $('.pmpro_copy_discount_code').on('click', function (event) { + $('.pmpro_copy_discount_code').on('click', function ( evt ) { // Find first link text const code = $(this).closest('td').find('a').first().text(); - // Check for Clipboard API support + // Bail if Clipboard API isn't supported if ( ! navigator.clipboard ) { - console.error('Navigator Clipboard API not supported'); return; } From a24549867a79bc22c180cfe68e5cd5b98a670fc4 Mon Sep 17 00:00:00 2001 From: David Parker Date: Tue, 17 Dec 2024 13:02:20 -0500 Subject: [PATCH 07/12] Simplification --- classes/class-pmpro-subscription.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/classes/class-pmpro-subscription.php b/classes/class-pmpro-subscription.php index c7c3f7c2e..7ce7125b3 100644 --- a/classes/class-pmpro-subscription.php +++ b/classes/class-pmpro-subscription.php @@ -780,19 +780,8 @@ private function format_subscription_date( $date, $format = 'timestamp', $local_ } elseif ( 'date_format' === $format ) { $format = get_option( 'date_format' ); } - // Get date in WP local timezone. - if ( $local_time ) { - // wp_date() returns time in local timezone by default. - return wp_date( $format, strtotime( $date ) ); - } - - // If it's not a timestamp, convert it to one. - if ( ! is_numeric( $date ) ) { - $date = strtotime( $date ); - } - // Get date in GMT timezone. - return wp_date( $format, $date, new DateTimezone('GMT') ); + return wp_date( $format, strtotime( $date ), $local_time ? null : new DateTimezone( 'UTC' ) ); } /** From 4fbc860e964dae827fe4d3d439fdc78484c004f2 Mon Sep 17 00:00:00 2001 From: maximilianoRicoTabo Date: Wed, 18 Dec 2024 18:37:57 -0300 Subject: [PATCH 08/12] * If Clipboard API isn't supported remove all copy to clipboard buttons from the DOM * Add further buttons to allow copy to clibboard order ids, subscriptions id, payment and transaction ids. --- .../class-pmpro-discount-code-list-table.php | 2 +- classes/class-pmpro-orders-list-table.php | 17 ++++++- .../class-pmpro-subscriptions-list-table.php | 4 ++ css/admin.css | 4 +- js/pmpro-admin.js | 51 +++++++++++++------ 5 files changed, 59 insertions(+), 19 deletions(-) diff --git a/classes/class-pmpro-discount-code-list-table.php b/classes/class-pmpro-discount-code-list-table.php index 95365c86a..4ebfe7fb9 100644 --- a/classes/class-pmpro-discount-code-list-table.php +++ b/classes/class-pmpro-discount-code-list-table.php @@ -370,7 +370,7 @@ public function column_discount_code( $item ) { ?> code ); ?>
diff --git a/classes/class-pmpro-orders-list-table.php b/classes/class-pmpro-orders-list-table.php index 6804553f4..dc71d0618 100644 --- a/classes/class-pmpro-orders-list-table.php +++ b/classes/class-pmpro-orders-list-table.php @@ -891,6 +891,10 @@ public function column_order_id( $item ) { public function column_order_code( $item ) { ?> code ); ?> +
$value ) { - echo '

' . wp_kses_post( $value ) . '

'; + echo '

' . + wp_kses_post( $value ); + //we don't want to show the copy button for the empty column + if( $key !== 'none') { + ?> + + '; } } diff --git a/classes/class-pmpro-subscriptions-list-table.php b/classes/class-pmpro-subscriptions-list-table.php index 84f1aca51..c582ccae8 100644 --- a/classes/class-pmpro-subscriptions-list-table.php +++ b/classes/class-pmpro-subscriptions-list-table.php @@ -449,6 +449,10 @@ public function column_default( $item, $column_name ) { public function column_id( $item ) { ?> get_subscription_transaction_id() ); ?> +

{ $('.success-message').remove(); - $('.pmpro_copy_discount_code').show(); + $('.pmpro_copy_to_clipboard').show(); }, 3000); }) .catch(err => { From a615678f1e6f10d902b15bc7d16259d54522f81a Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Fri, 10 Jan 2025 11:43:33 -0500 Subject: [PATCH 09/12] Removing references to PayPal from the Membership Billing page --- pages/billing.php | 11 +---------- preheaders/billing.php | 5 +---- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/pages/billing.php b/pages/billing.php index 47b05e092..b9df80ca5 100644 --- a/pages/billing.php +++ b/pages/billing.php @@ -13,7 +13,7 @@ ?>
- -
-

- -

-
-

login to PayPal here to update your billing information.', 'paid-memberships-pro' ), array( 'a' => array( 'href' => array() ) ) );?>

-
-
diff --git a/preheaders/billing.php b/preheaders/billing.php index 19779bc0d..6e61a7403 100644 --- a/preheaders/billing.php +++ b/preheaders/billing.php @@ -56,13 +56,10 @@ $current_user->membership_level = $pmpro_billing_level; //need to be secure? -global $besecure, $gateway, $show_paypal_link, $show_check_payment_instructions; +global $besecure, $gateway, $show_check_payment_instructions; if (empty($pmpro_billing_order->gateway)) { //no order $besecure = false; -} elseif ($pmpro_billing_order->gateway == "paypalexpress") { - $besecure = get_option("pmpro_use_ssl"); - $show_paypal_link = true; } elseif( $pmpro_billing_order->gateway == 'check' ) { $show_check_payment_instructions = true; } else { From 3717cbb5332dfce15dbf26f87bb9072707de0931 Mon Sep 17 00:00:00 2001 From: David Parker Date: Wed, 15 Jan 2025 14:06:31 -0500 Subject: [PATCH 10/12] Adding custom ranges to the sales and revenue report --- adminpages/reports/sales.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/adminpages/reports/sales.php b/adminpages/reports/sales.php index c9688fd01..95494fb60 100644 --- a/adminpages/reports/sales.php +++ b/adminpages/reports/sales.php @@ -278,6 +278,14 @@ function pmpro_report_sales_page() $startdate = date( 'Y-m-01', strtotime( current_time( 'mysql' ) . ' -12 month' ) ); // Set the end date to the last day of the previous month. $enddate = date('Y-m-t', strtotime( current_time( 'mysql' ) . ' -1 month' ) ); + } else if ( $period === 'custom' ) { + // Set up the report unit to use. + $report_unit = 'DAY'; + $axis_date_format = 'd'; + $tooltip_date_format = get_option( 'date_format' ); + // Set up the start and end dates. + $startdate = sanitize_text_field( $_REQUEST['custom_start_date'] ); + $enddate = sanitize_text_field( $_REQUEST['custom_end_date'] ); } else { // Set up the report unit to use. $report_unit = 'YEAR'; @@ -607,6 +615,7 @@ function pmpro_report_sales_page() + + + + + + + - get_results("SELECT id, name FROM $wpdb->pmpro_membership_levels ORDER BY name"); $levels = pmpro_sort_levels_by_order( $levels ); foreach($levels as $level) { ?> - + - + pmpro_discount_codes "; $sqlQuery .= "ORDER BY id DESC "; $codes = $wpdb->get_results($sqlQuery, OBJECT); if ( ! empty( $codes ) ) { ?> - - + + @@ -185,7 +185,6 @@ function pmpro_report_login_page() } ?> -
diff --git a/adminpages/reports/memberships.php b/adminpages/reports/memberships.php index 2bd0eaa09..f3dcccaee 100644 --- a/adminpages/reports/memberships.php +++ b/adminpages/reports/memberships.php @@ -363,7 +363,7 @@ function pmpro_report_memberships_page() {

- + - + - + - - - -
+ + +
diff --git a/adminpages/reports/sales.php b/adminpages/reports/sales.php index ac35dbea6..328cf483a 100644 --- a/adminpages/reports/sales.php +++ b/adminpages/reports/sales.php @@ -617,7 +617,7 @@ function pmpro_report_sales_page()

- + - + - + - - - -
+ + +
diff --git a/css/admin.css b/css/admin.css index a79bf3f43..13d76fe2a 100644 --- a/css/admin.css +++ b/css/admin.css @@ -3219,21 +3219,26 @@ tr.pmpro_alert { } .pmpro_report-filters { + align-items: start; background-color: #FFF; border: 1px solid var(--pmpro--border--color); border-radius: var(--pmpro--border--radius); box-shadow: var(--pmpro--box-shadow); + display: flex; + flex-direction: column; + flex-wrap: nowrap; + gap: var(--pmpro--spacing--small); margin: 1em 0; padding: calc( var(--pmpro--spacing--medium) / 2 ); } .pmpro_report-filters h3 { - margin: 0 0 .75em 0; + margin: 0; padding: 0; } .pmpro_report-filters .tablenav.top { - align-items: center; + align-items: start; display: flex; flex-wrap: wrap; gap: .5em; @@ -3242,6 +3247,35 @@ tr.pmpro_alert { padding: 0; } +.pmpro_report-filters .tablenav.top .pmpro_report-filter-text { + line-height: 30px; +} + +.pmpro_report-filters .select2-container .select2-selection--multiple { + min-height: auto; +} + +.pmpro_report-filters .select2-container--default .select2-selection--multiple { + border-color: #8c8f94; +} + +.pmpro_report-filters .select2-container--default .select2-selection--multiple .select2-selection__rendered li { + margin: 0; +} + +.pmpro_report-filters .select2-container--default .select2-selection--multiple li.select2-selection__choice { + margin: 3px 3px 0 0; +} + +.pmpro_report-filters .select2-container--default .select2-search--inline .select2-search__field { + line-height: 1.4; + min-height: auto; +} + +.pmpro_report-filters .select2-container--default .select2-search--inline .select2-search__field::placeholder { + color: #2c3338; +} + /* Reports individual page view styles */ #visits-views-logins-form { margin-top: var(--pmpro--spacing--medium);