diff --git a/changelog.txt b/changelog.txt index 6879bff12..1dea43cea 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,14 +1,14 @@ *** Changelog *** -= 1.9.1 - TBD = += 1.9.1 - 2022-07-25 = * Fix - ITEM_TOTAL_MISMATCH error when checking out with multiple products #721 * Fix - Unable to purchase a product with Credit card button in pay for order page #718 * Fix - Pay Later messaging only displayed when smart button is active on the same page #283 * Fix - Pay Later messaging displayed for out of stock variable products or with no variation selected #667 * Fix - Placeholders and card type detection not working for PayPal Card Processing (260) #685 -* Fix - PUI gateway is displayed with unsupported store currency #711 +* Fix - PUI gateway is displayed with unsupported store currency #711 * Fix - Wrong PUI locale sent causing error PAYMENT_SOURCE_CANNOT_BE_USED #741 -* Enhancement - Missing PayPal fee in WC order details for PUI purchase #714 +* Enhancement - Missing PayPal fee in WC order details for PUI purchase #714 * Enhancement - Skip loading of PUI js file on all pages where PUI gateway is not displayed #723 * Enhancement - PUI feature capitalization not consistent #724 diff --git a/modules/ppcp-button/resources/js/button.js b/modules/ppcp-button/resources/js/button.js index b64b5e9d8..4ec22c7d7 100644 --- a/modules/ppcp-button/resources/js/button.js +++ b/modules/ppcp-button/resources/js/button.js @@ -40,9 +40,36 @@ const bootstrap = () => { requiredFields.each((i, input) => { jQuery(input).trigger('validate'); }); - if (jQuery('form.woocommerce-checkout .validate-required.woocommerce-invalid:visible').length) { + const invalidFields = Array.from(jQuery('form.woocommerce-checkout .validate-required.woocommerce-invalid:visible')); + if (invalidFields.length) { + const billingFieldsContainer = document.querySelector('.woocommerce-billing-fields'); + const shippingFieldsContainer = document.querySelector('.woocommerce-shipping-fields'); + + const nameMessageMap = PayPalCommerceGateway.labels.error.required.elements; + const messages = invalidFields.map(el => { + const name = el.querySelector('[name]')?.getAttribute('name'); + if (name && name in nameMessageMap) { + return nameMessageMap[name]; + } + let label = el.querySelector('label').textContent + .replaceAll('*', '') + .trim(); + if (billingFieldsContainer?.contains(el)) { + label = PayPalCommerceGateway.labels.billing_field.replace('%s', label); + } + if (shippingFieldsContainer?.contains(el)) { + label = PayPalCommerceGateway.labels.shipping_field.replace('%s', label); + } + return PayPalCommerceGateway.labels.error.required.field + .replace('%s', `${label}`) + }).filter(s => s.length > 2); + errorHandler.clear(); - errorHandler.message(PayPalCommerceGateway.labels.error.js_validation); + if (messages.length) { + messages.forEach(s => errorHandler.message(s)); + } else { + errorHandler.message(PayPalCommerceGateway.labels.error.required.generic); + } return actions.reject(); } @@ -85,7 +112,7 @@ const bootstrap = () => { PayPalCommerceGateway, renderer, messageRenderer, - ); + );w singleProductBootstrap.init(); } diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index fd465cfc2..ab6a30ffd 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -876,16 +876,31 @@ class SmartButton implements SmartButtonInterface { ), 'messages' => $this->message_values(), 'labels' => array( - 'error' => array( - 'generic' => __( + 'error' => array( + 'generic' => __( 'Something went wrong. Please try again or choose another payment source.', 'woocommerce-paypal-payments' ), - 'js_validation' => __( - 'Required form fields are not filled or invalid.', - 'woocommerce-paypal-payments' + 'required' => array( + 'generic' => __( + 'Required form fields are not filled.', + 'woocommerce-paypal-payments' + ), + // phpcs:ignore WordPress.WP.I18n + 'field' => __( '%s is a required field.', 'woocommerce' ), + 'elements' => array( // Map
=> text for error messages. + 'terms' => __( + 'Please read and accept the terms and conditions to proceed with your order.', + // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch + 'woocommerce' + ), + ), ), ), + // phpcs:ignore WordPress.WP.I18n + 'billing_field' => _x( 'Billing %s', 'checkout-validation', 'woocommerce' ), + // phpcs:ignore WordPress.WP.I18n + 'shipping_field' => _x( 'Shipping %s', 'checkout-validation', 'woocommerce' ), ), 'order_id' => 'pay-now' === $this->context() ? absint( $wp->query_vars['order-pay'] ) : 0, 'single_product_buttons_enabled' => $this->settings->has( 'button_product_enabled' ) && $this->settings->get( 'button_product_enabled' ), diff --git a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php index 32391bb0a..7789779d0 100644 --- a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php +++ b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceHelper.php @@ -22,7 +22,7 @@ use WC_Product_Variation; class PayUponInvoiceHelper { /** - * Ensures date is valid and at least 18 years back. + * Ensures date is valid, at least 18 years back and not older than 100 years. * * @param string $date The date. * @param string $format The date format. @@ -43,6 +43,10 @@ class PayUponInvoiceHelper { return false; } + if ( $date_time < strtotime( '-100 years', time() ) ) { + return false; + } + return true; } diff --git a/tests/PHPUnit/WcGateway/Helper/PayUponInvoiceHelperTest.php b/tests/PHPUnit/WcGateway/Helper/PayUponInvoiceHelperTest.php index 3a1d9bdc0..f470d25ea 100644 --- a/tests/PHPUnit/WcGateway/Helper/PayUponInvoiceHelperTest.php +++ b/tests/PHPUnit/WcGateway/Helper/PayUponInvoiceHelperTest.php @@ -26,6 +26,7 @@ class PayUponInvoiceHelperTest extends TestCase ['1942-02-31', false], ['01-01-1942', false], ['1942-01-01', true], + ['0001-01-01', false], ]; }