├── .nvmrc ├── assets ├── css │ ├── about.css │ ├── admin-empty-state.css │ ├── admin-order-statuses.css │ ├── admin.css │ ├── checkout.css │ ├── modal.css │ ├── view-subscription.css │ └── wcs-upgrade.css ├── images │ ├── add-edit-subscription-screen.png │ ├── admin-change-payment-method.jpg │ ├── ajax-loader.gif │ ├── ajax-loader@2x.gif │ ├── billing-schedules-meta-box.png │ ├── checkout-recurring-totals.png │ ├── drip-downloadable-content.jpg │ ├── gift-subscription.png │ ├── renewal-retry-settings.png │ ├── subscribe-all-the-things.png │ ├── subscription-reports.png │ ├── subscription-suspended-email.jpg │ ├── subscriptions-empty-state.svg │ ├── subscriptions-importer-exporter.png │ ├── view-subscription.png │ └── woocommerce_subscriptions_logo.png └── js │ ├── admin │ ├── admin-pointers.js │ ├── admin.js │ ├── jstz.js │ ├── jstz.min.js │ ├── meta-boxes-coupon.js │ ├── meta-boxes-subscription.js │ ├── moment.js │ ├── moment.min.js │ ├── payment-method-restrictions.js │ └── wcs-meta-boxes-order.js │ ├── frontend │ ├── payment-methods.js │ ├── single-product.js │ ├── view-subscription.js │ └── wcs-cart.js │ ├── modal.js │ └── wcs-upgrade.js ├── build ├── index.asset.php ├── index.css └── index.js ├── changelog.txt ├── includes ├── abstracts │ ├── abstract-wcs-background-repairer.php │ ├── abstract-wcs-background-updater.php │ ├── abstract-wcs-background-upgrader.php │ ├── abstract-wcs-cache-manager.php │ ├── abstract-wcs-customer-store.php │ ├── abstract-wcs-debug-tool-cache-updater.php │ ├── abstract-wcs-debug-tool.php │ ├── abstract-wcs-deprecated-functions-handler.php │ ├── abstract-wcs-dynamic-hook-deprecator.php │ ├── abstract-wcs-hook-deprecator.php │ ├── abstract-wcs-migrator.php │ ├── abstract-wcs-related-order-store.php │ ├── abstract-wcs-scheduler.php │ └── abstract-wcs-table-maker.php ├── admin │ ├── class-wc-subscriptions-admin.php │ ├── class-wcs-admin-empty-list-content-manager.php │ ├── class-wcs-admin-meta-boxes.php │ ├── class-wcs-admin-notice.php │ ├── class-wcs-admin-post-types.php │ ├── class-wcs-admin-product-import-export-manager.php │ ├── class-wcs-admin-system-status.php │ ├── class-wcs-wc-admin-manager.php │ ├── debug-tools │ │ ├── class-wcs-debug-tool-cache-background-updater.php │ │ ├── class-wcs-debug-tool-cache-eraser.php │ │ ├── class-wcs-debug-tool-cache-generator.php │ │ ├── class-wcs-debug-tool-factory.php │ │ └── class-wcs-notifications-debug-tool-processor.php │ ├── meta-boxes │ │ ├── class-wcs-meta-box-related-orders.php │ │ ├── class-wcs-meta-box-schedule.php │ │ ├── class-wcs-meta-box-subscription-data.php │ │ └── views │ │ │ ├── html-related-orders-row.php │ │ │ ├── html-related-orders-table.php │ │ │ ├── html-subscription-schedule.php │ │ │ └── html-unknown-related-orders-row.php │ └── wcs-admin-functions.php ├── class-wc-product-subscription-variation.php ├── class-wc-product-subscription.php ├── class-wc-product-variable-subscription.php ├── class-wc-subscription-item-coupon-pending-switch.php ├── class-wc-subscription-item-fee-pending-switch.php ├── class-wc-subscription-line-item-removed.php ├── class-wc-subscription-line-item-switched.php ├── class-wc-subscription-query-controller.php ├── class-wc-subscription.php ├── class-wc-subscriptions-addresses.php ├── class-wc-subscriptions-cart-validator.php ├── class-wc-subscriptions-cart.php ├── class-wc-subscriptions-change-payment-gateway.php ├── class-wc-subscriptions-checkout.php ├── class-wc-subscriptions-core-plugin.php ├── class-wc-subscriptions-coupon.php ├── class-wc-subscriptions-data-copier.php ├── class-wc-subscriptions-email-notifications.php ├── class-wc-subscriptions-email.php ├── class-wc-subscriptions-extend-store-endpoint.php ├── class-wc-subscriptions-frontend-scripts.php ├── class-wc-subscriptions-manager.php ├── class-wc-subscriptions-order.php ├── class-wc-subscriptions-product.php ├── class-wc-subscriptions-renewal-order.php ├── class-wc-subscriptions-synchroniser.php ├── class-wc-subscriptions-tracker.php ├── class-wcs-action-scheduler-customer-notifications.php ├── class-wcs-action-scheduler.php ├── class-wcs-batch-processing-controller.php ├── class-wcs-blocks-integration.php ├── class-wcs-cached-data-manager.php ├── class-wcs-cart-initial-payment.php ├── class-wcs-cart-renewal.php ├── class-wcs-cart-resubscribe.php ├── class-wcs-change-payment-method-admin.php ├── class-wcs-core-autoloader.php ├── class-wcs-custom-order-item-manager.php ├── class-wcs-dependent-hook-manager.php ├── class-wcs-download-handler.php ├── class-wcs-failed-scheduled-action-manager.php ├── class-wcs-initial-cart-stock-manager.php ├── class-wcs-limiter.php ├── class-wcs-modal.php ├── class-wcs-my-account-auto-renew-toggle.php ├── class-wcs-my-account-payment-methods.php ├── class-wcs-notifications-batch-processor.php ├── class-wcs-object-data-cache-manager-many-to-one.php ├── class-wcs-object-data-cache-manager.php ├── class-wcs-object-sorter.php ├── class-wcs-payment-tokens.php ├── class-wcs-permalink-manager.php ├── class-wcs-post-meta-cache-manager-many-to-one.php ├── class-wcs-post-meta-cache-manager.php ├── class-wcs-query.php ├── class-wcs-remove-item.php ├── class-wcs-renewal-cart-stock-manager.php ├── class-wcs-select2.php ├── class-wcs-sql-transaction.php ├── class-wcs-staging.php ├── class-wcs-template-loader.php ├── class-wcs-user-change-status-handler.php ├── data-stores │ ├── class-wcs-customer-store-cached-cpt.php │ ├── class-wcs-customer-store-cpt.php │ ├── class-wcs-orders-table-data-store-controller.php │ ├── class-wcs-orders-table-subscription-data-store.php │ ├── class-wcs-product-variable-data-store-cpt.php │ ├── class-wcs-related-order-store-cached-cpt.php │ ├── class-wcs-related-order-store-cpt.php │ └── class-wcs-subscription-data-store-cpt.php ├── deprecated │ ├── class-wcs-action-deprecator.php │ ├── class-wcs-deprecated-filter-hooks.php │ ├── class-wcs-dynamic-action-deprecator.php │ ├── class-wcs-dynamic-filter-deprecator.php │ ├── class-wcs-filter-deprecator.php │ └── deprecation-handlers │ │ └── class-wc-subscriptions-deprecation-handler.php ├── emails │ ├── class-wc-subscriptions-email-preview.php │ ├── class-wcs-email-cancelled-subscription.php │ ├── class-wcs-email-completed-renewal-order.php │ ├── class-wcs-email-completed-switch-order.php │ ├── class-wcs-email-customer-notification-auto-renewal.php │ ├── class-wcs-email-customer-notification-auto-trial-expiration.php │ ├── class-wcs-email-customer-notification-manual-renewal.php │ ├── class-wcs-email-customer-notification-manual-trial-expiration.php │ ├── class-wcs-email-customer-notification-subscription-expiration.php │ ├── class-wcs-email-customer-notification.php │ ├── class-wcs-email-customer-on-hold-renewal-order.php │ ├── class-wcs-email-customer-renewal-invoice.php │ ├── class-wcs-email-expired-subscription.php │ ├── class-wcs-email-new-renewal-order.php │ ├── class-wcs-email-new-switch-order.php │ ├── class-wcs-email-on-hold-subscription.php │ └── class-wcs-email-processing-renewal-order.php ├── gateways │ ├── class-wc-subscriptions-core-payment-gateways.php │ ├── class-wc-subscriptions-gateway-restrictions-manager.php │ └── paypal │ │ ├── class-wcs-paypal.php │ │ └── includes │ │ ├── abstracts │ │ └── abstract-wcs-sv-api-base.php │ │ ├── admin │ │ ├── class-wcs-paypal-admin.php │ │ └── class-wcs-paypal-change-payment-method-admin.php │ │ ├── class-wcs-paypal-reference-transaction-api-request.php │ │ ├── class-wcs-paypal-reference-transaction-api-response-billing-agreement.php │ │ ├── class-wcs-paypal-reference-transaction-api-response-checkout.php │ │ ├── class-wcs-paypal-reference-transaction-api-response-payment.php │ │ ├── class-wcs-paypal-reference-transaction-api-response-recurring-payment.php │ │ ├── class-wcs-paypal-reference-transaction-api-response.php │ │ ├── class-wcs-paypal-reference-transaction-api.php │ │ ├── class-wcs-paypal-reference-transaction-ipn-handler.php │ │ ├── class-wcs-paypal-standard-change-payment-method.php │ │ ├── class-wcs-paypal-standard-ipn-failure-handler.php │ │ ├── class-wcs-paypal-standard-ipn-handler.php │ │ ├── class-wcs-paypal-standard-request.php │ │ ├── class-wcs-paypal-standard-switcher.php │ │ ├── class-wcs-paypal-status-manager.php │ │ ├── class-wcs-paypal-supports.php │ │ ├── deprecated │ │ └── class-wc-paypal-standard-subscriptions.php │ │ ├── templates │ │ ├── admin-notices.php │ │ └── html-ipn-failure-notice.php │ │ └── wcs-paypal-functions.php ├── interfaces │ ├── interface-wcs-batch-processor.php │ └── interface-wcs-cache-updater.php ├── legacy │ ├── class-wc-product-subscription-legacy.php │ ├── class-wc-product-subscription-variation-legacy.php │ ├── class-wc-product-variable-subscription-legacy.php │ ├── class-wc-subscription-legacy.php │ ├── class-wcs-array-property-post-meta-black-magic.php │ └── class-wcs-product-legacy.php ├── privacy │ ├── class-wcs-privacy-background-updater.php │ ├── class-wcs-privacy-erasers.php │ ├── class-wcs-privacy-exporters.php │ └── class-wcs-privacy.php ├── upgrades │ ├── class-wc-subscriptions-upgrader.php │ ├── class-wcs-repair-2-0-2.php │ ├── class-wcs-repair-2-0.php │ ├── class-wcs-repair-line-item-has-trial-meta.php │ ├── class-wcs-repair-start-date-metadata.php │ ├── class-wcs-repair-subscription-address-indexes.php │ ├── class-wcs-repair-subtracted-base-tax-line-item-meta.php │ ├── class-wcs-repair-suspended-paypal-subscriptions.php │ ├── class-wcs-upgrade-1-2.php │ ├── class-wcs-upgrade-1-3.php │ ├── class-wcs-upgrade-1-4.php │ ├── class-wcs-upgrade-1-5.php │ ├── class-wcs-upgrade-2-0.php │ ├── class-wcs-upgrade-2-1.php │ ├── class-wcs-upgrade-2-2-7.php │ ├── class-wcs-upgrade-2-2-9.php │ ├── class-wcs-upgrade-3-1-0.php │ ├── class-wcs-upgrade-logger.php │ ├── class-wcs-upgrade-subscription-post-author.php │ └── templates │ │ ├── update-welcome-notice.php │ │ ├── wcs-about-2-0.php │ │ ├── wcs-about.php │ │ ├── wcs-upgrade-in-progress.php │ │ └── wcs-upgrade.php ├── wcs-cart-functions.php ├── wcs-compatibility-functions.php ├── wcs-conditional-functions.php ├── wcs-deprecated-functions.php ├── wcs-formatting-functions.php ├── wcs-helper-functions.php ├── wcs-limit-functions.php ├── wcs-order-functions.php ├── wcs-product-functions.php ├── wcs-renewal-functions.php ├── wcs-resubscribe-functions.php ├── wcs-switch-functions.php ├── wcs-time-functions.php └── wcs-user-functions.php ├── languages ├── woocommerce-subscriptions-fr.mo ├── woocommerce-subscriptions-fr.po └── woocommerce-subscriptions.pot ├── license.txt ├── templates ├── admin │ ├── deprecated │ │ ├── html-variation-price.php │ │ ├── html-variation-synchronisation.php │ │ ├── order-shipping-html.php │ │ └── order-tax-html.php │ ├── html-admin-empty-list-table.php │ ├── html-admin-notice.php │ ├── html-failed-scheduled-action-notice.php │ ├── html-variation-price.php │ ├── html-variation-synchronisation.php │ └── status.php ├── cart │ └── cart-recurring-shipping.php ├── checkout │ ├── form-change-payment-method.php │ ├── recurring-coupon-totals.php │ ├── recurring-fee-totals.php │ ├── recurring-itemized-tax-totals.php │ ├── recurring-subscription-totals.php │ ├── recurring-subtotals.php │ ├── recurring-tax-totals.php │ ├── recurring-totals.php │ └── subscription-receipt.php ├── emails │ ├── admin-new-renewal-order.php │ ├── admin-new-switch-order.php │ ├── admin-payment-retry.php │ ├── cancelled-subscription.php │ ├── customer-completed-renewal-order.php │ ├── customer-completed-switch-order.php │ ├── customer-notification-auto-renewal.php │ ├── customer-notification-auto-trial-ending.php │ ├── customer-notification-expiring-subscription.php │ ├── customer-notification-manual-renewal.php │ ├── customer-notification-manual-trial-ending.php │ ├── customer-on-hold-renewal-order.php │ ├── customer-payment-retry.php │ ├── customer-processing-renewal-order.php │ ├── customer-renewal-invoice.php │ ├── email-order-details.php │ ├── expired-subscription.php │ ├── on-hold-subscription.php │ ├── plain │ │ ├── admin-new-renewal-order.php │ │ ├── admin-new-switch-order.php │ │ ├── admin-payment-retry.php │ │ ├── cancelled-subscription.php │ │ ├── customer-completed-renewal-order.php │ │ ├── customer-completed-switch-order.php │ │ ├── customer-notification-auto-renewal.php │ │ ├── customer-notification-auto-trial-ending.php │ │ ├── customer-notification-expiring-subscription.php │ │ ├── customer-notification-manual-renewal.php │ │ ├── customer-notification-manual-trial-ending.php │ │ ├── customer-on-hold-renewal-order.php │ │ ├── customer-payment-retry.php │ │ ├── customer-processing-renewal-order.php │ │ ├── customer-renewal-invoice.php │ │ ├── email-order-details.php │ │ ├── expired-subscription.php │ │ ├── on-hold-subscription.php │ │ └── subscription-info.php │ └── subscription-info.php ├── html-modal.php ├── myaccount │ ├── my-subscriptions.php │ ├── related-orders.php │ ├── related-subscriptions.php │ ├── subscription-details.php │ ├── subscription-totals-table.php │ ├── subscription-totals.php │ ├── subscriptions.php │ └── view-subscription.php └── single-product │ └── add-to-cart │ ├── subscription.php │ └── variable-subscription.php ├── wcs-functions.php ├── woocommerce-subscriptions-core.php └── wpml-config.xml /.nvmrc: -------------------------------------------------------------------------------- 1 | 16.17.1 2 | -------------------------------------------------------------------------------- /assets/css/admin-empty-state.css: -------------------------------------------------------------------------------- 1 | .woo_subscriptions_empty_state__container { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | align-items: center; 6 | padding: 48px 0; 7 | position: static; 8 | height: 344px; 9 | left: calc(50% - 1240px / 2); 10 | top: 271px; 11 | flex: none; 12 | order: 1; 13 | flex-grow: 0; 14 | margin: 0; 15 | text-align: center; 16 | } 17 | .woo_subscriptions_empty_state__container .woo_subscriptions_empty_state__description { 18 | max-width: 535px; 19 | margin: 15px 0; 20 | } 21 | .woo_subscriptions_empty_state__button_container { 22 | margin: 8px 0; 23 | } 24 | .woo_subscriptions_empty_state__container .woo_subscriptions_empty_state__button_container * + * { 25 | margin-left: 10px; 26 | } 27 | -------------------------------------------------------------------------------- /assets/css/admin-order-statuses.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Pre WC 3.3 support for order status admin styles. 3 | */ 4 | .order-status { 5 | display: -webkit-inline-box; 6 | display: -webkit-inline-flex; 7 | display: -ms-inline-flexbox; 8 | display: inline-flex; 9 | line-height: 2.5em; 10 | color: #777; 11 | background: #e5e5e5; 12 | border-radius: 4px; 13 | border-bottom: 1px solid rgba( 0, 0, 0, 0.05 ); 14 | margin: -0.25em 0; 15 | cursor: inherit !important; 16 | white-space: nowrap; 17 | max-width: 100%; 18 | } 19 | 20 | .order-status.status-completed { 21 | background: #c8d7e1; 22 | color: #2e4453; 23 | } 24 | 25 | .order-status.status-on-hold { 26 | background: #f8dda7; 27 | color: #94660c; 28 | } 29 | 30 | .order-status.status-failed { 31 | background: #eba3a3; 32 | color: #761919; 33 | } 34 | 35 | .order-status.status-processing { 36 | background: #c6e1c6; 37 | color: #5b841b; 38 | } 39 | 40 | .order-status.status-trash { 41 | background: #eba3a3; 42 | color: #761919; 43 | } 44 | 45 | .order-status > span { 46 | margin: 0 1em; 47 | overflow: hidden; 48 | text-overflow: ellipsis; 49 | } 50 | -------------------------------------------------------------------------------- /assets/css/checkout.css: -------------------------------------------------------------------------------- 1 | /* Cart/Checkout Pages */ 2 | .shipping.recurring-total ul { 3 | list-style: none outside; 4 | margin: 0; 5 | padding: 0; 6 | } 7 | .shipping.recurring-total ul li { 8 | margin: 0; 9 | padding: 0.25em 0 0.25em 22px; 10 | text-indent: -22px; 11 | list-style: none outside; 12 | } 13 | .shipping.recurring-total ul li input { 14 | margin: 3px 0.5ex; 15 | } 16 | .shipping.recurring-total ul li label { 17 | display: inline; 18 | } 19 | .shipping.recurring-total ul .amount { 20 | font-weight: 700; 21 | } 22 | .woocommerce-page table.shop_table_responsive tbody .recurring-totals th { 23 | display: table-cell; 24 | } 25 | .woocommerce-page 26 | table.shop_table_responsive 27 | tr.recurring-total 28 | td:not( [data-title] )::before { 29 | content: ''; 30 | } 31 | -------------------------------------------------------------------------------- /assets/css/view-subscription.css: -------------------------------------------------------------------------------- 1 | @media only screen and ( max-width: 768px ) { 2 | .subscription_details .button { 3 | box-sizing: border-box; 4 | margin-bottom: 2px; 5 | padding-left: 0.5rem; 6 | padding-right: 0.5rem; 7 | width: 100%; 8 | max-width: 200px; 9 | text-align: center; 10 | } 11 | } 12 | 13 | .subscription_details .button { 14 | display: inline-block; 15 | margin-bottom: 0.5em; 16 | } 17 | 18 | .subscription-auto-renew-toggle { 19 | margin-left: 5px; 20 | margin-bottom: 2px; 21 | position: relative; 22 | top: 4px; 23 | } 24 | 25 | .subscription-auto-renew-toggle__i { 26 | height: 20px; 27 | width: 32px; 28 | border: 2px solid #00ba8a; 29 | background-color: #00ba8a; 30 | display: inline-block; 31 | text-indent: -9999px; 32 | border-radius: 10em; 33 | position: relative; 34 | margin-top: -1px; 35 | vertical-align: text-top; 36 | } 37 | 38 | .subscription-auto-renew-toggle__i::before { 39 | content: ''; 40 | display: block; 41 | width: 16px; 42 | height: 16px; 43 | background: #fff; 44 | position: absolute; 45 | top: 0; 46 | right: 0; 47 | border-radius: 100%; 48 | } 49 | 50 | .subscription-auto-renew-toggle--off .subscription-auto-renew-toggle__i { 51 | border-color: #999; 52 | background-color: #999; 53 | } 54 | 55 | .subscription-auto-renew-toggle--off 56 | .subscription-auto-renew-toggle__i::before { 57 | right: auto; 58 | left: 0; 59 | } 60 | 61 | .subscription-auto-renew-toggle--loading .subscription-auto-renew-toggle__i { 62 | opacity: 0.5; 63 | } 64 | 65 | .subscription-auto-renew-toggle--hidden { 66 | display: none; 67 | } 68 | .subscription-auto-renew-toggle-disabled-note { 69 | margin-left: 1em; 70 | } 71 | 72 | /** 73 | * Early renewal Modal 74 | **/ 75 | .wcs_early_renew_modal_totals_table { 76 | overflow: scroll; 77 | height: 80%; 78 | margin-bottom: 1em; 79 | } 80 | 81 | .wcs_early_renew_modal_note { 82 | position: sticky; 83 | bottom: 0; 84 | min-width: 100%; 85 | width: 0; 86 | } 87 | 88 | #early_renewal_modal_submit { 89 | width: 100%; 90 | font-size: 1.4em; 91 | text-align: center; 92 | } 93 | -------------------------------------------------------------------------------- /assets/css/wcs-upgrade.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-top: 100px; 3 | padding-bottom: 2em; 4 | } 5 | .help_tip .tooltip { 6 | display: none; 7 | } 8 | .help_tip:hover .tooltip { 9 | display: block; 10 | } 11 | .tooltip { 12 | position: absolute; 13 | width: 480px; 14 | height: 270px; 15 | line-height: 1.5em; 16 | padding: 10px; 17 | font-size: 14px; 18 | text-align: left; 19 | color: rgb( 18, 18, 18 ); 20 | background: rgb( 249, 249, 249 ); 21 | border: 4px solid rgb( 249, 249, 249 ); 22 | border-radius: 5px; 23 | text-shadow: none; 24 | box-shadow: rgba( 0, 0, 0, 0.2 ) 0 0 4px 1px; 25 | margin-top: -332px; 26 | margin-left: 100px; 27 | } 28 | .tooltip::after { 29 | content: ''; 30 | position: absolute; 31 | width: 0; 32 | height: 0; 33 | border-width: 14px; 34 | border-style: solid; 35 | border-color: #f9f9f9 transparent transparent transparent; 36 | top: 292px; 37 | left: 366px; 38 | } 39 | #update-messages, 40 | #update-complete, 41 | #update-error { 42 | display: none; 43 | } 44 | .log-notice { 45 | color: #a0a0a0; 46 | } 47 | p.log-notice { 48 | font-size: 0.8em; 49 | color: #a0a0a0; 50 | } 51 | -------------------------------------------------------------------------------- /assets/images/add-edit-subscription-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/add-edit-subscription-screen.png -------------------------------------------------------------------------------- /assets/images/admin-change-payment-method.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/admin-change-payment-method.jpg -------------------------------------------------------------------------------- /assets/images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/ajax-loader.gif -------------------------------------------------------------------------------- /assets/images/ajax-loader@2x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/ajax-loader@2x.gif -------------------------------------------------------------------------------- /assets/images/billing-schedules-meta-box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/billing-schedules-meta-box.png -------------------------------------------------------------------------------- /assets/images/checkout-recurring-totals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/checkout-recurring-totals.png -------------------------------------------------------------------------------- /assets/images/drip-downloadable-content.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/drip-downloadable-content.jpg -------------------------------------------------------------------------------- /assets/images/gift-subscription.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/gift-subscription.png -------------------------------------------------------------------------------- /assets/images/renewal-retry-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/renewal-retry-settings.png -------------------------------------------------------------------------------- /assets/images/subscribe-all-the-things.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/subscribe-all-the-things.png -------------------------------------------------------------------------------- /assets/images/subscription-reports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/subscription-reports.png -------------------------------------------------------------------------------- /assets/images/subscription-suspended-email.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/subscription-suspended-email.jpg -------------------------------------------------------------------------------- /assets/images/subscriptions-importer-exporter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/subscriptions-importer-exporter.png -------------------------------------------------------------------------------- /assets/images/view-subscription.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/view-subscription.png -------------------------------------------------------------------------------- /assets/images/woocommerce_subscriptions_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/assets/images/woocommerce_subscriptions_logo.png -------------------------------------------------------------------------------- /assets/js/admin/admin-pointers.js: -------------------------------------------------------------------------------- 1 | jQuery( function ( $ ) { 2 | let observer = null; 3 | 4 | if ( arePointersEnabled() ) { 5 | observer = new MutationObserver( showSubscriptionPointers ); 6 | 7 | observer.observe( document.getElementById( 'poststuff' ), { 8 | attributes: true, 9 | childList: true, 10 | characterData: false, 11 | subtree:true, 12 | } ); 13 | } 14 | 15 | $( 'select#product-type' ).on( 'change', function () { 16 | if ( arePointersEnabled() ) { 17 | $( '#product-type' ).pointer( 'close' ); 18 | } 19 | } ); 20 | 21 | $( 22 | '#_subscription_price, #_subscription_period, #_subscription_length' 23 | ).on( 'change', function () { 24 | if ( arePointersEnabled() ) { 25 | $( '.options_group.subscription_pricing' ).pointer( 'close' ); 26 | $( '#product-type' ).pointer( 'close' ); 27 | } 28 | } ); 29 | 30 | function arePointersEnabled() { 31 | if ( $.getParameterByName( 'subscription_pointers' ) == 'true' ) { 32 | return true; 33 | } else { 34 | return false; 35 | } 36 | } 37 | 38 | function showSubscriptionPointers() { 39 | $( '#product-type' ) 40 | .pointer( { 41 | content: WCSPointers.typePointerContent, 42 | position: { 43 | edge: 'left', 44 | align: 'center', 45 | }, 46 | close: function () { 47 | if ( 48 | $( 'select#product-type' ).val() == 49 | WCSubscriptions.productType 50 | ) { 51 | $( 52 | '.options_group.subscription_pricing:not(".subscription_sync")' 53 | ) 54 | .pointer( { 55 | content: WCSPointers.pricePointerContent, 56 | position: 'bottom', 57 | close: function () { 58 | dismissSubscriptionPointer(); 59 | }, 60 | } ) 61 | .pointer( 'open' ); 62 | } 63 | dismissSubscriptionPointer(); 64 | }, 65 | } ) 66 | .pointer( 'open' ); 67 | } 68 | 69 | function dismissSubscriptionPointer() { 70 | $.post( ajaxurl, { 71 | pointer: 'wcs_pointer', 72 | action: 'dismiss-wp-pointer', 73 | } ); 74 | 75 | if ( observer ) { 76 | observer.disconnect(); 77 | } 78 | } 79 | } ); 80 | -------------------------------------------------------------------------------- /assets/js/admin/meta-boxes-coupon.js: -------------------------------------------------------------------------------- 1 | jQuery( function ( $ ) { 2 | 'use strict'; 3 | 4 | var renewals_field = document.querySelector( '.wcs_number_payments_field' ), 5 | $renewals_field = $( renewals_field ); 6 | 7 | /** 8 | * Subscription coupon actions. 9 | * @type {{init: function, type_options: function, move_field: function}} 10 | */ 11 | var wcs_meta_boxes_coupon_actions = { 12 | /** 13 | * Initialize variation actions. 14 | */ 15 | init: function () { 16 | if ( renewals_field ) { 17 | $( document.getElementById( 'discount_type' ) ) 18 | .on( 'change', this.type_options ) 19 | .trigger( 'change' ); 20 | this.move_field(); 21 | } 22 | }, 23 | 24 | /** 25 | * Show/hide fields by coupon type options. 26 | */ 27 | type_options: function () { 28 | var select_val = $( this ).val(); 29 | 30 | switch ( select_val ) { 31 | case 'recurring_fee': 32 | case 'recurring_percent': 33 | $renewals_field.show(); 34 | break; 35 | 36 | default: 37 | $renewals_field.hide(); 38 | break; 39 | } 40 | }, 41 | 42 | /** 43 | * Move the renewal form field in the DOM to a better location. 44 | */ 45 | move_field: function () { 46 | var parent = document.getElementById( 'general_coupon_data' ), 47 | shipping = parent.querySelector( '.free_shipping_field' ); 48 | 49 | parent.insertBefore( renewals_field, shipping ); 50 | }, 51 | }; 52 | 53 | wcs_meta_boxes_coupon_actions.init(); 54 | } ); 55 | -------------------------------------------------------------------------------- /assets/js/admin/wcs-meta-boxes-order.js: -------------------------------------------------------------------------------- 1 | jQuery( function ( $ ) { 2 | $( 'body.post-type-shop_order #post' ).on( 'submit', function () { 3 | if ( 4 | 'wcs_retry_renewal_payment' == 5 | $( 6 | "body.post-type-shop_order select[name='wc_order_action']" 7 | ).val() 8 | ) { 9 | return confirm( 10 | wcs_admin_order_meta_boxes.retry_renewal_payment_action_warning 11 | ); 12 | } 13 | } ); 14 | 15 | $( document ).on( 'change', '#wcs-order-price-lock', function () { 16 | // Block the checkbox element while we update the order. 17 | $( '#wcs_order_price_lock' ).block( { 18 | message: null, 19 | overlayCSS: { 20 | background: '#fff', 21 | opacity: 0.6, 22 | }, 23 | } ); 24 | 25 | var data = { 26 | wcs_order_price_lock: $( '#wcs-order-price-lock' ).is( ':checked' ) 27 | ? 'yes' 28 | : 'no', 29 | order_id: $( '#post_ID' ).val(), 30 | action: 'wcs_order_price_lock', 31 | woocommerce_meta_nonce: $( '#woocommerce_meta_nonce' ).val(), 32 | }; 33 | 34 | $.ajax( { 35 | type: 'post', 36 | url: woocommerce_admin_meta_boxes.ajax_url, 37 | data: data, 38 | complete: function () { 39 | $( '#wcs_order_price_lock' ).unblock(); 40 | }, 41 | } ); 42 | } ); 43 | } ); 44 | -------------------------------------------------------------------------------- /assets/js/frontend/payment-methods.js: -------------------------------------------------------------------------------- 1 | jQuery( function ( $ ) { 2 | /** 3 | * Displays an appropriate error message when the delete token button is clicked for a token used by subscriptions. 4 | */ 5 | $( '.wcs_deletion_error' ).on( 'click', function ( e ) { 6 | e.preventDefault(); 7 | 8 | var notice_content_container = $( '#wcs_delete_token_warning' ).find( 'li' ); 9 | 10 | // For block based WC notices we need to find the notice content container. 11 | if ( $( '#wcs_delete_token_warning' ).find( '.wc-block-components-notice-banner' ).length > 0 ) { 12 | notice_content_container = $( '#wcs_delete_token_warning' ).find( '.wc-block-components-notice-banner__content' ); 13 | } 14 | 15 | // Use the href to determine which notice needs to be displayed. 16 | if ( '#choose_default' === $( this ).attr( 'href' ) ) { 17 | notice_content_container.html( wcs_payment_methods.choose_default_error ); 18 | } else { 19 | notice_content_container.html( wcs_payment_methods.add_method_error ); 20 | } 21 | 22 | // Display the notice. 23 | $( '#wcs_delete_token_warning' ).slideDown(); 24 | } ); 25 | } ); 26 | -------------------------------------------------------------------------------- /assets/js/frontend/single-product.js: -------------------------------------------------------------------------------- 1 | ( function ( document, $ ) { 2 | var $cache = {}; 3 | 4 | /** 5 | * Cache our DOM selectors. 6 | */ 7 | function generate_cache() { 8 | $cache.document = $( document ); 9 | $cache.first_payment_date = $( '.first-payment-date' ); 10 | $cache.is_variable_subscription = 11 | 0 < $( 'div.product-type-variable-subscription' ).length; 12 | } 13 | 14 | /** 15 | * Attach DOM events. 16 | */ 17 | function attach_events() { 18 | if ( $cache.is_variable_subscription ) { 19 | $cache.document.on( 20 | 'found_variation', 21 | update_first_payment_element 22 | ); 23 | $cache.document.on( 'reset_data', clear_first_payment_element ); 24 | } 25 | } 26 | 27 | /** 28 | * Update the variation's first payment element. 29 | * 30 | * @param {jQuery.Event} event 31 | * @param {object} variation_data 32 | */ 33 | function update_first_payment_element( event, variation_data ) { 34 | $cache.first_payment_date.html( variation_data.first_payment_html ); 35 | } 36 | 37 | /** 38 | * Clear the variation's first payment element. 39 | */ 40 | function clear_first_payment_element() { 41 | $cache.first_payment_date.html( '' ); 42 | } 43 | 44 | /** 45 | * Initialise. 46 | */ 47 | function init() { 48 | generate_cache(); 49 | attach_events(); 50 | } 51 | 52 | $( init ); 53 | } )( document, jQuery ); 54 | -------------------------------------------------------------------------------- /assets/js/frontend/wcs-cart.js: -------------------------------------------------------------------------------- 1 | function hide_non_applicable_coupons() { 2 | var coupon_elements = document.getElementsByClassName( 'cart-discount' ); 3 | 4 | for ( var i = 0; i < coupon_elements.length; i++ ) { 5 | if ( 6 | 0 !== 7 | coupon_elements[ i ].getElementsByClassName( 'wcs-hidden-coupon' ) 8 | .length 9 | ) { 10 | coupon_elements[ i ].style.display = 'none'; 11 | } 12 | } 13 | } 14 | 15 | hide_non_applicable_coupons(); 16 | 17 | jQuery( function ( $ ) { 18 | $( document.body ).on( 'updated_cart_totals updated_checkout', function () { 19 | hide_non_applicable_coupons(); 20 | } ); 21 | 22 | /** 23 | * Update all subscriptions shipping methods which inherit the chosen method from the initial 24 | * cart when the customer changes the shipping method. 25 | */ 26 | $( document ).on( 27 | 'change', 28 | 'select.shipping_method, :input[name^=shipping_method]', 29 | function( event ) { 30 | var shipping_method_option = $( event.target ); 31 | var shipping_method_id = shipping_method_option.val(); 32 | var package_index = shipping_method_option.data( 'index' ); 33 | 34 | // We're only interested in the initial cart shipping method options which have int package indexes. 35 | if ( ! Number.isInteger( package_index ) ) { 36 | return; 37 | } 38 | 39 | // Find all recurring cart info elements with the same package index as the changed shipping method. 40 | $( '.recurring-cart-shipping-mapping-info[data-index=' + package_index + ']' ).each( function() { 41 | // Update the corresponding subscription's hidden chosen shipping method. 42 | $( 'input[name="shipping_method[' + $( this ).data( 'recurring_index' ) + ']"]' ).val( shipping_method_id ); 43 | } ); 44 | } 45 | ); 46 | 47 | $( '.payment_methods [name="payment_method"]' ).on( 'click', function () { 48 | if ( $( this ).hasClass( 'supports-payment-method-changes' ) ) { 49 | $( '.update-all-subscriptions-payment-method-wrap' ).show(); 50 | } else { 51 | $( '.update-all-subscriptions-payment-method-wrap' ).hide(); 52 | } 53 | } ); 54 | } ); 55 | -------------------------------------------------------------------------------- /build/index.asset.php: -------------------------------------------------------------------------------- 1 | array('wc-blocks-checkout', 'wc-price-format', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '7e9abfc482fe190e29673f828b33f482'); -------------------------------------------------------------------------------- /build/index.css: -------------------------------------------------------------------------------- 1 | .wcs-recurring-totals-panel{position:relative;padding:1em 0 0}.wcs-recurring-totals-panel::after{border-style:solid;border-width:1px 0;bottom:0;content:"";display:block;left:0;opacity:.3;pointer-events:none;position:absolute;right:0;top:0}.wcs-recurring-totals-panel+.wcs-recurring-totals-panel::after{border-top-width:0}.wcs-recurring-totals-panel .wc-block-components-panel .wc-block-components-totals-item{padding-left:0;padding-right:0}.wcs-recurring-totals-panel .wc-block-components-totals-item__label::first-letter{text-transform:capitalize}.wcs-recurring-totals-panel .wcs-recurring-totals-panel__title .wc-block-components-totals-item__label{font-weight:700}.wcs-recurring-totals-panel__title{margin:0}.wcs-recurring-totals-panel__details .wc-block-components-panel__button,.wcs-recurring-totals-panel__details .wc-block-components-panel__button:hover,.wcs-recurring-totals-panel__details .wc-block-components-panel__button:focus{font-size:.875em}.wcs-recurring-totals-panel__details .wc-block-components-panel__content>.wc-block-components-totals-item:first-child{margin-top:0}.wcs-recurring-totals-panel__details .wc-block-components-panel__content>.wc-block-components-totals-item:last-child{margin-bottom:0}.wcs-recurring-totals-panel__details .wcs-recurring-totals-panel__details-total .wc-block-components-totals-item__label{font-weight:700}.wcs-recurring-totals__subscription-length{float:right} 2 | 3 | -------------------------------------------------------------------------------- /includes/abstracts/abstract-wcs-background-upgrader.php: -------------------------------------------------------------------------------- 1 | scheduled_hook action to start repairing subscriptions in 34 | * @see $this->time_limit seconds (60 seconds by default). 35 | * 36 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3.0 37 | */ 38 | public function schedule_repair() { 39 | $this->schedule_background_update(); 40 | } 41 | 42 | /** 43 | * Add a message to the wcs-upgrade-subscriptions-paypal-suspended log 44 | * 45 | * @param string $message The message to be logged 46 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3.0 47 | */ 48 | protected function log( $message ) { 49 | $this->logger->add( $this->log_handle, $message ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /includes/abstracts/abstract-wcs-cache-manager.php: -------------------------------------------------------------------------------- 1 | init(); 49 | } 50 | 51 | return self::$instance; 52 | } 53 | 54 | /** 55 | * Stub for initialising the class outside the constructor, for things like attaching callbacks to hooks. 56 | */ 57 | protected function init() {} 58 | } 59 | -------------------------------------------------------------------------------- /includes/abstracts/abstract-wcs-debug-tool-cache-updater.php: -------------------------------------------------------------------------------- 1 | System Status > Tools page that need to 6 | * update a cached data store's cache. 7 | * 8 | * @author Prospress 9 | * @category Admin 10 | * @package WooCommerce Subscriptions/Admin 11 | * @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 12 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 13 | */ 14 | 15 | if ( ! defined( 'ABSPATH' ) ) { 16 | exit; 17 | } // Exit if accessed directly 18 | 19 | /** 20 | * WCS_Debug_Tool_Cache_Updater Class 21 | * 22 | * Shared methods for tool on the WooCommerce > System Status > Tools page that need to 23 | * update a cached data store's cache. 24 | */ 25 | abstract class WCS_Debug_Tool_Cache_Updater extends WCS_Debug_Tool { 26 | 27 | /** 28 | * @var mixed $data_Store The store used for updating the cache. 29 | */ 30 | protected $data_store; 31 | 32 | /** 33 | * Attach callbacks and hooks, if the class's data store is using caching. 34 | */ 35 | public function init() { 36 | if ( $this->is_data_store_cached() ) { 37 | parent::init(); 38 | } 39 | } 40 | 41 | /** 42 | * Check if the store is a cache updater, and has methods required to erase or generate cache. 43 | */ 44 | protected function is_data_store_cached() { 45 | return is_a( $this->data_store, 'WCS_Cache_Updater' ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /includes/abstracts/abstract-wcs-debug-tool.php: -------------------------------------------------------------------------------- 1 | System Status > Tools administration screen. 7 | * 8 | * @author Prospress 9 | * @category Admin 10 | * @package WooCommerce Subscriptions/Admin 11 | * @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 12 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 13 | */ 14 | 15 | if ( ! defined( 'ABSPATH' ) ) { 16 | exit; 17 | } // Exit if accessed directly 18 | 19 | /** 20 | * WCS_Debug_Tool Class 21 | * 22 | * Add a debug tool to the WooCommerce > System Status > Tools page. 23 | */ 24 | abstract class WCS_Debug_Tool { 25 | 26 | /** 27 | * @var string $tool_key The key used to add the tool to the array of available tools. 28 | */ 29 | protected $tool_key; 30 | 31 | /** 32 | * @var array $tool_data Data for this tool, containing: 33 | * - 'name': The section name given to the tool 34 | * - 'button': The text displayed on the tool's button 35 | * - 'desc': The long description for the tool. 36 | * - 'callback': The callback used to perform the tool's action. 37 | */ 38 | protected $tool_data; 39 | 40 | /** 41 | * Attach callbacks to hooks and validate required properties are assigned values. 42 | */ 43 | public function init() { 44 | 45 | if ( empty( $this->tool_key ) ) { 46 | throw new RuntimeException( __CLASS__ . ' must assign a tool key to $this->tool_key' ); 47 | } 48 | 49 | if ( empty( $this->tool_data ) ) { 50 | throw new RuntimeException( __CLASS__ . ' must assign an array of data about the tool to $this->tool_data' ); 51 | } 52 | 53 | add_filter( 'woocommerce_debug_tools', array( $this, 'add_debug_tools' ) ); 54 | } 55 | 56 | /** 57 | * Add subscription related tools to display on the WooCommerce > System Status > Tools administration screen 58 | * 59 | * @param array $tools Arrays defining the tools displayed on the System Status screen 60 | * @return array 61 | */ 62 | public function add_debug_tools( $tools ) { 63 | $tools[ $this->tool_key ] = $this->tool_data; 64 | return $tools; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /includes/abstracts/abstract-wcs-dynamic-hook-deprecator.php: -------------------------------------------------------------------------------- 1 | 'old_hook_prefix' */ 15 | protected $deprecated_hook_prefixes = array(); 16 | 17 | /** 18 | * Bootstraps the class and hooks required actions & filters. 19 | * 20 | * We need to use the special 'all' hook here because we don't actually know the full hook names 21 | * in advance, just their prefix. We can't simply hook in to 'plugins_loaded' and check the 22 | * $wp_filter global for our hooks either, because sometime, hooks are dynamically hooked based 23 | * on other hooks. Sigh. 24 | * 25 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 26 | */ 27 | public function __construct() { 28 | add_filter( 'all', array( &$this, 'check_for_deprecated_hooks' ) ); 29 | } 30 | 31 | /** 32 | * Check if the current hook contains the prefix of any dynamic hook that has been deprecated. 33 | * 34 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 35 | */ 36 | public function check_for_deprecated_hooks() { 37 | 38 | $current_filter = current_filter(); 39 | 40 | foreach ( $this->deprecated_hook_prefixes as $new_hook_prefix => $old_hook_prefixes ) { 41 | 42 | if ( is_array( $old_hook_prefixes ) ) { 43 | foreach ( $old_hook_prefixes as $old_hook_prefix ) { 44 | $this->check_for_deprecated_hook( $current_filter, $new_hook_prefix, $old_hook_prefix ); 45 | } 46 | } else { 47 | $this->check_for_deprecated_hook( $current_filter, $new_hook_prefix, $old_hook_prefixes ); 48 | } 49 | } 50 | } 51 | 52 | /** 53 | * Check if a given hook contains the prefix and if it does, attach the @see $this->maybe_handle_deprecated_hook() method 54 | * as a callback to it. 55 | * 56 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 57 | */ 58 | protected function check_for_deprecated_hook( $current_hook, $new_hook_prefix, $old_hook_prefix ) { 59 | 60 | if ( false !== strpos( $current_hook, $new_hook_prefix ) ) { 61 | 62 | // Get the dynamic suffix on the hook, usually a payment gateway name, like 'stripe' or 'authorize_net_cim' 63 | $hook_suffix = str_replace( $new_hook_prefix, '', $current_hook ); 64 | $old_hook = $old_hook_prefix . $hook_suffix; 65 | 66 | // register the entire new and old hook 67 | $this->deprecated_hooks[ $current_hook ][] = $old_hook; 68 | 69 | // and attach our handler now that we know the hooks 70 | add_filter( $current_hook, array( &$this, 'maybe_handle_deprecated_hook' ), -1000, 8 ); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /includes/abstracts/abstract-wcs-scheduler.php: -------------------------------------------------------------------------------- 1 | date_types_to_schedule = apply_filters( 'woocommerce_subscriptions_date_types_to_schedule', array_keys( $date_types_to_schedule ) ); 34 | } 35 | 36 | protected function get_date_types_to_schedule() { 37 | return $this->date_types_to_schedule; 38 | } 39 | 40 | /** 41 | * When a subscription's date is updated, maybe schedule an event 42 | * 43 | * @param object $subscription An instance of a WC_Subscription object 44 | * @param string $date_type Can be 'trial_end', 'next_payment', 'end', 'end_of_prepaid_term' or a custom date type 45 | * @param string $datetime A MySQL formatted date/time string in the GMT/UTC timezone. 46 | */ 47 | abstract public function update_date( $subscription, $date_type, $datetime ); 48 | 49 | /** 50 | * When a subscription's date is deleted, clear it from the scheduler 51 | * 52 | * @param object $subscription An instance of a WC_Subscription object 53 | * @param string $date_type Can be 'trial_end', 'next_payment', 'end', 'end_of_prepaid_term' or a custom date type 54 | */ 55 | abstract public function delete_date( $subscription, $date_type ); 56 | 57 | /** 58 | * When a subscription's status is updated, maybe schedule an event 59 | * 60 | * @param object $subscription An instance of a WC_Subscription object 61 | * @param string $new_status A valid subscription status 62 | * @param string $old_status A valid subscription status 63 | */ 64 | abstract public function update_status( $subscription, $new_status, $old_status ); 65 | } 66 | -------------------------------------------------------------------------------- /includes/admin/debug-tools/class-wcs-debug-tool-cache-background-updater.php: -------------------------------------------------------------------------------- 1 | System Status > Tools administration screen. 7 | * 8 | * @author Prospress 9 | * @category Admin 10 | * @package WooCommerce Subscriptions/Admin 11 | * @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 12 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 13 | */ 14 | 15 | if ( ! defined( 'ABSPATH' ) ) { 16 | exit; 17 | } // Exit if accessed directly 18 | 19 | /** 20 | * WCS_Debug_Tool_Cache_Background_Updater Class 21 | * 22 | * Provide APIs for a debug tool to update a cached data store's data in the background using Action Scheduler. 23 | */ 24 | class WCS_Debug_Tool_Cache_Background_Updater extends WCS_Background_Updater { 25 | 26 | /** 27 | * @var WCS_Cache_Updater The data store used to manage the cache. 28 | */ 29 | protected $data_store; 30 | 31 | /** 32 | * WCS_Debug_Tool_Cache_Background_Updater constructor. 33 | * 34 | * @param string $scheduled_hook The hook to schedule to run the update. 35 | * @param WCS_Cache_Updater $data_store 36 | */ 37 | public function __construct( $scheduled_hook, WCS_Cache_Updater $data_store ) { 38 | $this->scheduled_hook = $scheduled_hook; 39 | $this->data_store = $data_store; 40 | } 41 | 42 | /** 43 | * Get the items to be updated, if any. 44 | * 45 | * @return array An array of items to update, or empty array if there are no items to update. 46 | */ 47 | protected function get_items_to_update() { 48 | return $this->data_store->get_items_to_update(); 49 | } 50 | 51 | /** 52 | * Run the update for a single item. 53 | * 54 | * @param mixed $item The item to update. 55 | */ 56 | protected function update_item( $item ) { 57 | return $this->data_store->update_items_cache( $item ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /includes/admin/debug-tools/class-wcs-debug-tool-cache-eraser.php: -------------------------------------------------------------------------------- 1 | System Status > Tools page for 6 | * deleting a data store's cache/s. 7 | * 8 | * @author Prospress 9 | * @category Admin 10 | * @package WooCommerce Subscriptions/Admin 11 | * @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 12 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 13 | */ 14 | 15 | if ( ! defined( 'ABSPATH' ) ) { 16 | exit; 17 | } // Exit if accessed directly 18 | 19 | /** 20 | * WCS_Debug_Tool_Cache_Eraser Class 21 | * 22 | * Add a debug tool to the WooCommerce > System Status > Tools page for 23 | * deleting a data store's cache/s. 24 | */ 25 | class WCS_Debug_Tool_Cache_Eraser extends WCS_Debug_Tool_Cache_Updater { 26 | 27 | /** 28 | * WCS_Debug_Tool_Cache_Eraser constructor. 29 | * 30 | * @param string $tool_key The key used to add the tool to the array of available tools. 31 | * @param string $tool_name The section name given to the tool on the admin screen. 32 | * @param string $tool_description The long description for the tool displayed on the admin screen. 33 | * @param WCS_Cache_Updater $data_store The cached data store this tool will use for erasing cache. 34 | */ 35 | public function __construct( $tool_key, $tool_name, $tool_description, WCS_Cache_Updater $data_store ) { 36 | $this->tool_key = $tool_key; 37 | $this->data_store = $data_store; 38 | $this->tool_data = array( 39 | 'name' => $tool_name, 40 | 'button' => $tool_name, 41 | 'desc' => $tool_description, 42 | 'callback' => array( $this, 'delete_caches' ), 43 | ); 44 | } 45 | 46 | /** 47 | * Clear all of the data store's caches. 48 | */ 49 | public function delete_caches() { 50 | if ( $this->is_data_store_cached() ) { 51 | $this->data_store->delete_all_caches(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /includes/admin/debug-tools/class-wcs-debug-tool-cache-generator.php: -------------------------------------------------------------------------------- 1 | System Status > Tools page for generating a cache. 6 | * 7 | * @author Prospress 8 | * @category Admin 9 | * @package WooCommerce Subscriptions/Admin 10 | * @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 11 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3 12 | */ 13 | 14 | if ( ! defined( 'ABSPATH' ) ) { 15 | exit; 16 | } // Exit if accessed directly 17 | 18 | /** 19 | * WCS_Debug_Tool_Cache_Generator Class 20 | * 21 | * Add a debug tool to the WooCommerce > System Status > Tools page for generating a cache. 22 | */ 23 | class WCS_Debug_Tool_Cache_Generator extends WCS_Debug_Tool_Cache_Updater { 24 | 25 | /** 26 | * @var WCS_Background_Updater $update The instance used to generate the cache data in the background. 27 | */ 28 | protected $cache_updater; 29 | 30 | /** 31 | * WCS_Debug_Tool_Cache_Generator constructor. 32 | * 33 | * @param string $tool_key The key used to add the tool to the array of available tools. 34 | * @param string $tool_name The section name given to the tool on the admin screen. 35 | * @param string $tool_description The long description for the tool displayed on the admin screen. 36 | * @param WCS_Cache_Updater $data_store 37 | * @param WCS_Background_Updater $cache_updater 38 | */ 39 | public function __construct( $tool_key, $tool_name, $tool_description, WCS_Cache_Updater $data_store, WCS_Background_Updater $cache_updater ) { 40 | $this->tool_key = $tool_key; 41 | $this->data_store = $data_store; 42 | $this->cache_updater = $cache_updater; 43 | $this->tool_data = array( 44 | 'name' => $tool_name, 45 | 'button' => $tool_name, 46 | 'desc' => $tool_description, 47 | 'callback' => array( $this, 'generate_caches' ), 48 | ); 49 | } 50 | 51 | /** 52 | * Attach callbacks and hooks, if the store supports getting uncached items, which is required to generate cache 53 | * and also acts as a proxy to determine if the related order store is using caching 54 | */ 55 | public function init() { 56 | if ( $this->is_data_store_cached() ) { 57 | parent::init(); 58 | $this->cache_updater->init(); 59 | } 60 | } 61 | 62 | /** 63 | * Generate the data store's cache by calling the @see $this->>cache_updater's update method. 64 | */ 65 | public function generate_caches() { 66 | $this->cache_updater->run_update(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /includes/admin/meta-boxes/views/html-related-orders-row.php: -------------------------------------------------------------------------------- 1 | get_edit_order_url() ) . '" aria-label="' . esc_attr( sprintf( __( 'Edit order number %s', 'woocommerce-subscriptions' ), $order->get_order_number() ) ) . '">' . 15 | // translators: placeholder is an order number. 16 | sprintf( esc_html_x( '#%s', 'hash before order number', 'woocommerce-subscriptions' ), esc_html( $order->get_order_number() ) ) . 17 | ''; 18 | 19 | // Relationship column 20 | $relationship = esc_html( $order->get_meta( '_relationship' ) ); 21 | 22 | // Date created column 23 | $date_created = $order->get_date_created(); 24 | 25 | if ( $date_created ) { 26 | $t_time = $order->get_date_created()->date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ); 27 | $date_to_display = ucfirst( wcs_get_human_time_diff( $date_created->getTimestamp() ) ); 28 | } else { 29 | $t_time = __( 'Unpublished', 'woocommerce-subscriptions' ); 30 | $date_to_display = $t_time; 31 | } 32 | 33 | if ( ! wcs_is_custom_order_tables_usage_enabled() ) { 34 | // Backwards compatibility for third-parties using the generic WP post time filter. 35 | // Only apply this filter if HPOS is not enabled, as the filter is not compatible with HPOS. 36 | $date_to_display = apply_filters( 'post_date_column_time', $date_to_display, get_post( $order->get_id() ) ); 37 | } 38 | 39 | $date_created = '' . esc_html( apply_filters( 'wc_subscriptions_related_order_date_column', $date_to_display, $order ) ) . ''; 40 | 41 | // Status column 42 | $classes = array( 43 | 'order-status', 44 | sanitize_html_class( 'status-' . $order->get_status() ), 45 | ); 46 | 47 | if ( wcs_is_subscription( $order ) ) { 48 | $status_name = wcs_get_subscription_status_name( $order->get_status() ); 49 | $classes[] = 'subscription-status'; 50 | } else { 51 | $status_name = wc_get_order_status_name( $order->get_status() ); 52 | } 53 | 54 | $status_html = '' . esc_html( $status_name ) . ''; 55 | 56 | // Total column 57 | $total = '' . wp_kses( 58 | $order->get_formatted_order_total(), 59 | array( 60 | 'small' => array(), 61 | 'span' => array( 62 | 'class' => array(), 63 | ), 64 | 'del' => array(), 65 | 'ins' => array(), 66 | ) 67 | ) . ''; 68 | 69 | $columns = array( 70 | $order_number, 71 | $relationship, 72 | $date_created, 73 | $status_html, 74 | $total, 75 | ); 76 | 77 | $columns = apply_filters( 'wcs_related_orders_table_row_columns', $columns ); 78 | 79 | ?> 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /includes/admin/meta-boxes/views/html-related-orders-table.php: -------------------------------------------------------------------------------- 1 | 24 | 62 | -------------------------------------------------------------------------------- /includes/admin/meta-boxes/views/html-unknown-related-orders-row.php: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 20 |
21 | 22 | HTML tag. 25 | __( 'This %1$s couldn\'t be loaded from the database. %1$s Click to learn more.', 'woocommerce-subscriptions' ), 26 | esc_html( $relationship ), 27 | '
' 28 | ) 29 | ); 30 | ?> 31 |
32 |
33 | 34 | 35 | — 36 | — 37 | — 38 | 39 | -------------------------------------------------------------------------------- /includes/class-wc-subscription-item-coupon-pending-switch.php: -------------------------------------------------------------------------------- 1 | trigger_update_cache_hook( $change['type'], $object->get_id(), $key, $change['new'], $previous_value ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /includes/class-wcs-object-sorter.php: -------------------------------------------------------------------------------- 1 | get_id() 17 | * 18 | * @var string A valid object property. Could be 'date_created', 'date_modified', 'date_paid', 'date_completed' or 'id' for WC_Order or WC_Subscription objects, for example. 19 | */ 20 | protected $sort_by_property = ''; 21 | 22 | /** 23 | * Constructor. 24 | * 25 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.6.0 26 | * 27 | * @param string $property The object property to use in comparisons. This will be used to generate the object getter by prepending 'get_'. 28 | */ 29 | public function __construct( $property ) { 30 | $this->sort_by_property = $property; 31 | } 32 | 33 | /** 34 | * Compares two objects using the @see $this->sort_by_property getter. 35 | * 36 | * Designed to be used by uasort(), usort() or uksort() functions. 37 | * 38 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.6.0 39 | * 40 | * @param object $object_one 41 | * @param object $object_two 42 | * @return int 0. -1 or 1 Depending on the result of the comparison. 43 | */ 44 | public function ascending_compare( $object_one, $object_two ) { 45 | $function = "get_{$this->sort_by_property}"; 46 | 47 | if ( ! is_callable( array( $object_one, $function ) ) || ! is_callable( array( $object_two, $function ) ) ) { 48 | return 0; 49 | } 50 | 51 | $value_one = $object_one->{$function}(); 52 | $value_two = $object_two->{$function}(); 53 | 54 | if ( $value_one === $value_two ) { 55 | return 0; 56 | } 57 | 58 | return ( $value_one < $value_two ) ? -1 : 1; 59 | } 60 | 61 | /** 62 | * Compares two objects using the @see $this->sort_by_property getter in reverse order. 63 | * 64 | * Designed to be used by uasort(), or usort() style functions. 65 | * 66 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.6.0 67 | * 68 | * @param object $object_one 69 | * @param object $object_two 70 | * @return int 0. -1 or 1 Depending on the result of the comparison. 71 | */ 72 | public function descending_compare( $object_one, $object_two ) { 73 | return -1 * $this->ascending_compare( $object_one, $object_two ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /includes/class-wcs-post-meta-cache-manager-many-to-one.php: -------------------------------------------------------------------------------- 1 | meta_updated_with_previous( null, $post_id, $meta_key, $meta_value, get_post_meta( $post_id, $meta_key, true ) ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /includes/data-stores/class-wcs-customer-store-cpt.php: -------------------------------------------------------------------------------- 1 | meta_key; 36 | } 37 | 38 | /** 39 | * Gets the data key used to link the customer with a subscription. 40 | * 41 | * This can be the post meta key on stores using the WP Post architecture and the property name on HPOS architecture. 42 | * 43 | * @return string The customer user post meta key or the customer ID property key. 44 | */ 45 | protected function get_data_key() { 46 | return wcs_is_custom_order_tables_usage_enabled() ? $this->data_key : $this->meta_key; 47 | } 48 | 49 | /** 50 | * Get the IDs for a given user's subscriptions. 51 | * 52 | * @param int $user_id The id of the user whose subscriptions you want. 53 | * @return array 54 | */ 55 | public function get_users_subscription_ids( $user_id ) { 56 | 57 | if ( 0 === $user_id ) { 58 | return array(); 59 | } 60 | 61 | return wcs_get_orders_with_meta_query( 62 | [ 63 | 'type' => 'shop_subscription', 64 | 'customer_id' => $user_id, 65 | 'limit' => -1, 66 | 'status' => 'any', 67 | 'return' => 'ids', 68 | 'orderby' => 'ID', 69 | 'order' => 'DESC', 70 | ] 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /includes/data-stores/class-wcs-orders-table-data-store-controller.php: -------------------------------------------------------------------------------- 1 | init_hooks(); 25 | } 26 | 27 | /** 28 | * Initialise WCS_Orders_Table_Data_Store_Controller class hooks. 29 | * 30 | * @return void 31 | */ 32 | public function init_hooks() { 33 | add_filter( 'woocommerce_subscription_data_store', array( $this, 'get_orders_table_data_store' ), 10, 2 ); 34 | } 35 | 36 | /** 37 | * Returns an instance of the Subscriptions Order Table data store object to use. 38 | * If an instance doesn't exist, create one. 39 | * 40 | * @return WCS_Orders_Table_Subscription_Data_Store 41 | */ 42 | private function get_data_store_instance() { 43 | if ( ! isset( $this->data_store ) ) { 44 | $this->data_store = new WCS_Orders_Table_Subscription_Data_Store(); 45 | $this->data_store->init( 46 | wc_get_container()->get( \Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStoreMeta::class ), 47 | wc_get_container()->get( \Automattic\WooCommerce\Internal\Utilities\DatabaseUtil::class ), 48 | wc_get_container()->get( \Automattic\WooCommerce\Proxies\LegacyProxy::class ) 49 | ); 50 | } 51 | 52 | return $this->data_store; 53 | } 54 | 55 | /** 56 | * When the custom_order_tables feature is enabled, return the subscription datastore class. 57 | * 58 | * @param string $default_data_store The data store class name. 59 | * 60 | * @return string 61 | */ 62 | public function get_orders_table_data_store( $default_data_store ) { 63 | return wcs_is_custom_order_tables_usage_enabled() ? $this->get_data_store_instance() : $default_data_store; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /includes/data-stores/class-wcs-product-variable-data-store-cpt.php: -------------------------------------------------------------------------------- 1 | read_min_max_variation_data( $product ); 31 | } 32 | 33 | /** 34 | * Read min and max variation data from post meta. 35 | * 36 | * @param WC_Product_Variable_Subscription $product Product object. 37 | */ 38 | protected function read_min_max_variation_data( &$product ) { 39 | if ( ! isset( self::$reading_min_max_variation_data[ $product->get_id() ] ) && ! $product->meta_exists( '_min_max_variation_ids_hash' ) ) { 40 | self::$reading_min_max_variation_data[ $product->get_id() ] = ''; 41 | 42 | $product->set_min_and_max_variation_data(); 43 | 44 | update_post_meta( $product->get_id(), '_min_max_variation_data', $product->get_meta( '_min_max_variation_data', true ), true ); 45 | update_post_meta( $product->get_id(), '_min_max_variation_ids_hash', $product->get_meta( '_min_max_variation_ids_hash', true ), true ); 46 | unset( self::$reading_min_max_variation_data[ $product->get_id() ] ); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /includes/deprecated/class-wcs-deprecated-filter-hooks.php: -------------------------------------------------------------------------------- 1 | old_hook ) 27 | * 28 | * @var array 29 | */ 30 | protected $deprecated_hooks = array( 31 | 'woocommerce_subscription_get_currency' => 'woocommerce_get_currency', 32 | 'woocommerce_subscription_get_discount_total' => 'woocommerce_order_amount_discount_total', 33 | 'woocommerce_subscription_get_discount_tax' => 'woocommerce_order_amount_discount_tax', 34 | 'woocommerce_subscription_get_shipping_total' => 'woocommerce_order_amount_shipping_total', 35 | 'woocommerce_subscription_get_shipping_tax' => 'woocommerce_order_amount_shipping_tax', 36 | 'woocommerce_subscription_get_cart_tax' => 'woocommerce_order_amount_cart_tax', 37 | 'woocommerce_subscription_get_total' => 'woocommerce_order_amount_total', 38 | 'woocommerce_subscription_get_total_tax' => 'woocommerce_order_amount_total_tax', 39 | 'woocommerce_subscription_get_total_discount' => 'woocommerce_order_amount_total_discount', 40 | 'woocommerce_subscription_get_subtotal' => 'woocommerce_order_amount_subtotal', 41 | 'woocommerce_subscription_get_tax_totals' => 'woocommerce_order_tax_totals', 42 | ); 43 | 44 | /** 45 | * Display a deprecated notice for old hooks. 46 | * 47 | * @param string $old_hook 48 | * @param string $new_hook 49 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.2.0 50 | */ 51 | protected function display_notice( $old_hook, $new_hook ) { 52 | wcs_deprecated_function( sprintf( 'The "%s" hook uses out of date data structures and', esc_html( $old_hook ) ), '2.2.0', esc_html( $new_hook ) . ' to filter subscription properties' ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /includes/deprecated/class-wcs-dynamic-filter-deprecator.php: -------------------------------------------------------------------------------- 1 | 'old_hook_prefix' */ 15 | protected $deprecated_hook_prefixes = array( 16 | 'woocommerce_can_subscription_be_updated_to_' => 'woocommerce_subscription_can_be_changed_to_', 17 | ); 18 | 19 | /** 20 | * Bootstraps the class and hooks required actions & filters. 21 | * 22 | * We need to use the special 'all' hook here because we don't actually know the full hook names 23 | * in advance, just their prefix. 24 | * 25 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 26 | */ 27 | public function __construct() { 28 | parent::__construct(); 29 | } 30 | 31 | /** 32 | * Display a notice if functions are hooked to the old filter and apply the old filters args 33 | * 34 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 35 | */ 36 | protected function trigger_hook( $old_hook, $new_callback_args ) { 37 | 38 | // Return value is always the first param 39 | $return_value = $new_callback_args[0]; 40 | 41 | if ( 0 === strpos( $old_hook, 'woocommerce_subscription_can_be_changed_to_' ) ) { 42 | // New arg spec: $can_be_updated, $subscription 43 | // Old arg spec: $can_be_changed, $subscription, $order 44 | $subscription = $new_callback_args[1]; 45 | $return_value = apply_filters( $old_hook, $return_value, wcs_get_subscription_in_deprecated_structure( $subscription ), self::get_order( $subscription ) ); 46 | } 47 | 48 | return $return_value; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /includes/emails/class-wcs-email-customer-notification-auto-renewal.php: -------------------------------------------------------------------------------- 1 | plugin_id = 'woocommerce-subscriptions_'; 23 | 24 | $this->id = 'customer_notification_auto_renewal'; 25 | $this->title = __( 'Customer Notification: Automatic renewal notice', 'woocommerce-subscriptions' ); 26 | $this->description = __( 'Customer Notification: Automatic renewal notice emails are sent when customer\'s subscription is about to be renewed automatically.', 'woocommerce-subscriptions' ); 27 | 28 | $this->heading = __( 'Automatic renewal notice', 'woocommerce-subscriptions' ); 29 | 30 | $this->subject = sprintf( 31 | // translators: $1: {site_title}, $2: {customers_first_name}, $3: {time_until_renewal}, variables that will be substituted when email is sent out 32 | _x( '[%1$s] %2$s, your subscription automatically renews in %3$s!', 'default email subject for subscription\'s automatic renewal notice', 'woocommerce-subscriptions' ), 33 | '{site_title}', 34 | '{customers_first_name}', 35 | '{time_until_renewal}', 36 | ); 37 | 38 | $this->template_html = 'emails/customer-notification-auto-renewal.php'; 39 | $this->template_plain = 'emails/plain/customer-notification-auto-renewal.php'; 40 | $this->template_base = WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory( 'templates/' ); 41 | 42 | $this->customer_email = true; 43 | 44 | // Constructor in parent uses the values above in the initialization. 45 | parent::__construct(); 46 | } 47 | 48 | public function get_relevant_date_type() { 49 | return 'next_payment'; 50 | } 51 | 52 | /** 53 | * Default content to show below main email content. 54 | * 55 | * @return string 56 | */ 57 | public function get_default_additional_content() { 58 | return __( 'Thank you for being a loyal customer, {customers_first_name} — we appreciate your business.', 'woocommerce-subscriptions' ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /includes/emails/class-wcs-email-customer-notification-auto-trial-expiration.php: -------------------------------------------------------------------------------- 1 | plugin_id = 'woocommerce-subscriptions_'; 23 | 24 | $this->id = 'customer_notification_auto_trial_expiry'; 25 | $this->title = __( 'Customer Notification: Free trial expiration: automatic payment notice', 'woocommerce-subscriptions' ); 26 | $this->description = __( 'Free trial expiry notification emails are sent when customer\'s free trial for an automatically renewd subscription is about to expire.', 'woocommerce-subscriptions' ); 27 | 28 | $this->heading = __( 'Free trial expiration: automatic payment notice', 'woocommerce-subscriptions' ); 29 | // translators: $1: {site_title}, $2: {customers_first_name}, variables that will be substituted when email is sent out 30 | $this->subject = sprintf( _x( '[%1$s] %2$s, your paid subscription starts soon!', 'default email subject for free trial expiry notification emails sent to the customer', 'woocommerce-subscriptions' ), '{site_title}', '{customers_first_name}' ); 31 | 32 | $this->template_html = 'emails/customer-notification-auto-trial-ending.php'; 33 | $this->template_plain = 'emails/plain/customer-notification-auto-trial-ending.php'; 34 | $this->template_base = WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory( 'templates/' ); 35 | 36 | $this->customer_email = true; 37 | 38 | // Constructor in parent uses the values above in the initialization. 39 | parent::__construct(); 40 | } 41 | 42 | public function get_relevant_date_type() { 43 | return 'trial_end'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /includes/emails/class-wcs-email-customer-notification-manual-renewal.php: -------------------------------------------------------------------------------- 1 | plugin_id = 'woocommerce-subscriptions_'; 23 | 24 | $this->id = 'customer_notification_manual_renewal'; 25 | $this->title = __( 'Customer Notification: Manual renewal notice', 'woocommerce-subscriptions' ); 26 | $this->description = __( 'Customer Notification: Manual renewal notice are sent when customer\'s subscription needs to be manually renewed.', 'woocommerce-subscriptions' ); 27 | 28 | $this->heading = __( 'Manual renewal notice', 'woocommerce-subscriptions' ); 29 | // translators: $1: {site_title}, $2: {customers_first_name}, variables that will be substituted when email is sent out 30 | $this->subject = sprintf( _x( '[%1$s] %2$s, your subscription is ready to be renewed!', 'default email subject for notification for a manually renewed subscription sent to the customer', 'woocommerce-subscriptions' ), '{site_title}', '{customers_first_name}' ); 31 | 32 | $this->template_html = 'emails/customer-notification-manual-renewal.php'; 33 | $this->template_plain = 'emails/plain/customer-notification-manual-renewal.php'; 34 | $this->template_base = WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory( 'templates/' ); 35 | 36 | $this->customer_email = true; 37 | 38 | // Constructor in parent uses the values above in the initialization. 39 | parent::__construct(); 40 | } 41 | 42 | public function get_relevant_date_type() { 43 | return 'next_payment'; 44 | } 45 | 46 | /** 47 | * Default content to show below main email content. 48 | * 49 | * @return string 50 | */ 51 | public function get_default_additional_content() { 52 | return __( 'Thanks again for choosing {site_title}.', 'woocommerce-subscriptions' ); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /includes/emails/class-wcs-email-customer-notification-manual-trial-expiration.php: -------------------------------------------------------------------------------- 1 | plugin_id = 'woocommerce-subscriptions_'; 24 | 25 | $this->id = 'customer_notification_manual_trial_expiry'; 26 | $this->title = __( 'Customer Notification: Free trial expiration: manual payment required', 'woocommerce-subscriptions' ); 27 | $this->description = __( 'Free trial expiry notification emails are sent when customer\'s free trial for a manually renewed subscription is about to expire.', 'woocommerce-subscriptions' ); 28 | 29 | $this->heading = __( 'Free trial expiration: manual payment required', 'woocommerce-subscriptions' ); 30 | // translators: $1: {site_title}, $2: {customers_first_name}, variables that will be substituted when email is sent out. 31 | $this->subject = sprintf( _x( '[%1$s] %2$s, your free trial is almost up!', 'default email subject for an email notification for a manually renewed subscription with free trial expiry emails sent to the customer', 'woocommerce-subscriptions' ), '{site_title}', '{customers_first_name}' ); 32 | 33 | $this->template_html = 'emails/customer-notification-manual-trial-ending.php'; 34 | $this->template_plain = 'emails/plain/customer-notification-manual-trial-ending.php'; 35 | $this->template_base = WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory( 'templates/' ); 36 | 37 | $this->customer_email = true; 38 | 39 | // Constructor in parent uses the values above in the initialization. 40 | parent::__construct(); 41 | } 42 | 43 | public function get_relevant_date_type() { 44 | return 'trial_end'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /includes/emails/class-wcs-email-customer-notification-subscription-expiration.php: -------------------------------------------------------------------------------- 1 | plugin_id = 'woocommerce-subscriptions_'; 23 | 24 | $this->id = 'customer_notification_subscription_expiry'; 25 | $this->title = __( 'Customer Notification: Subscription expiration notice', 'woocommerce-subscriptions' ); 26 | $this->description = __( 'Subscription expiration notification emails are sent when customer\'s subscription is about to expire.', 'woocommerce-subscriptions' ); 27 | 28 | $this->heading = __( 'Subscription expiration notice', 'woocommerce-subscriptions' ); 29 | // translators: $1: {site_title}, $2: {customers_first_name}, variables that will be substituted when email is sent out 30 | $this->subject = sprintf( _x( '[%1$s] %2$s, your subscription is about to expire!', 'default email subject for subscription expiry notification email sent to the customer', 'woocommerce-subscriptions' ), '{site_title}', '{customers_first_name}' ); 31 | 32 | $this->template_html = 'emails/customer-notification-expiring-subscription.php'; 33 | $this->template_plain = 'emails/plain/customer-notification-expiring-subscription.php'; 34 | $this->template_base = WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory( 'templates/' ); 35 | 36 | $this->customer_email = true; 37 | 38 | // Constructor in parent uses the values above in the initialization. 39 | parent::__construct(); 40 | } 41 | 42 | public function get_relevant_date_type() { 43 | return 'end'; 44 | } 45 | 46 | /** 47 | * Default content to show below main email content. 48 | * 49 | * @return string 50 | */ 51 | public function get_default_additional_content() { 52 | return __( 'Thank you for choosing {site_title}, {customers_first_name}.', 'woocommerce-subscriptions' ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /includes/gateways/class-wc-subscriptions-gateway-restrictions-manager.php: -------------------------------------------------------------------------------- 1 | id ) ? $screen->id : ''; 28 | 29 | if ( 'product' === $screen_id ) { 30 | wp_enqueue_script( 31 | 'woocommerce_subscriptions_payment_restrictions', 32 | WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory_url( 'assets/js/admin/payment-method-restrictions.js' ), 33 | array( 'jquery', 'woocommerce_admin' ), 34 | filemtime( WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory( 'assets/js/admin/payment-method-restrictions.js' ) ), 35 | true // Load in footer. 36 | ); 37 | 38 | $decimals = wc_get_price_decimals(); 39 | $decimal_separator = wc_get_price_decimal_separator(); 40 | $zero_price = sprintf( get_woocommerce_price_format(), get_woocommerce_currency_symbol(), number_format( 0, $decimals, $decimal_separator, '' ) ); 41 | 42 | $script_data = array( 43 | // Translators: placeholder is a 0 price formatted with the the store's currency and decimal settings. 44 | 'i18n_zero_subscription_error' => sprintf( __( 'Please enter a price greater than %s.', 'woocommerce-subscriptions' ), $zero_price ), 45 | 'number_of_decimal_places' => $decimals, 46 | 'decimal_point_separator' => $decimal_separator, 47 | ); 48 | 49 | /** 50 | * Allow WC Payments to return the minimum amount that can be processed. 51 | * 52 | * @since 1.5.0 53 | * 54 | * @param false|float The minimum amount that can be processed in the given currency. 55 | * @param string The currency. 56 | */ 57 | $minimum_processable_amount = apply_filters( 'woocommerce_subscriptions_minimum_processable_recurring_amount', false, get_woocommerce_currency() ); 58 | 59 | if ( is_numeric( $minimum_processable_amount ) ) { 60 | $i18n_minimum_price = sprintf( get_woocommerce_price_format(), get_woocommerce_currency_symbol(), number_format( $minimum_processable_amount, $decimals, $decimal_separator, '' ) ); 61 | $script_data['minimum_subscription_amount'] = $minimum_processable_amount; 62 | 63 | // Translators: Placeholder is a localized price string (eg. $1.00). 64 | $script_data['i18n_below_minimum_subscription_error'] = sprintf( __( 'Warning! Your store cannot create subscriptions less than %s', 'woocommerce-subscriptions' ), $i18n_minimum_price ); 65 | } 66 | 67 | wp_localize_script( 'woocommerce_subscriptions_payment_restrictions', 'wcs_gateway_restrictions', $script_data ); 68 | } 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /includes/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api-response-billing-agreement.php: -------------------------------------------------------------------------------- 1 | get_parameter( 'BILLINGAGREEMENTID' ); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /includes/gateways/paypal/includes/class-wcs-paypal-reference-transaction-api-response-recurring-payment.php: -------------------------------------------------------------------------------- 1 | 'error', 19 | 'text' => '', 20 | ) ); 21 | 22 | switch ( $notice_args['type'] ) { 23 | case 'warning' : 24 | $notice = new WCS_Admin_Notice( 'updated', array( 'style' => array( 'border-left: 4px solid #ffba00' ) ) ); 25 | break; 26 | case 'info' : 27 | $notice = new WCS_Admin_Notice( 'notice notice-info' ); 28 | break; 29 | case 'error' : 30 | $notice = new WCS_Admin_Notice( 'updated error' ); 31 | break; 32 | case 'confirmation' : 33 | default : 34 | $notice = new WCS_Admin_Notice( 'updated' ); 35 | break; 36 | } 37 | 38 | $notice->set_simple_content( $notice_args['text'] ); 39 | $notice->display(); 40 | } 41 | -------------------------------------------------------------------------------- /includes/gateways/paypal/includes/templates/html-ipn-failure-notice.php: -------------------------------------------------------------------------------- 1 | 13 | 14 |

15 | ', 20 | '', 21 | '' 22 | ); 23 | ?> 24 |

25 | 26 | 27 | 28 | 31 | 32 |

33 | ' . esc_html( $failed_ipn_log_handle ) . '', 38 | '', 39 | '' 40 | ); 41 | ?> 42 |

43 | -------------------------------------------------------------------------------- /includes/interfaces/interface-wcs-cache-updater.php: -------------------------------------------------------------------------------- 1 | product_id = $product_id; 40 | } 41 | 42 | /** 43 | * offsetGet 44 | * @param string $key 45 | * @return mixed 46 | */ 47 | #[\ReturnTypeWillChange] 48 | public function offsetGet( $key ) { 49 | return get_post_meta( $this->product_id, $this->maybe_prefix_meta_key( $key ) ); 50 | } 51 | 52 | /** 53 | * offsetSet 54 | * @param string $key 55 | * @param mixed $value 56 | */ 57 | #[\ReturnTypeWillChange] 58 | public function offsetSet( $key, $value ) { 59 | update_post_meta( $this->product_id, $this->maybe_prefix_meta_key( $key ), $value ); 60 | } 61 | 62 | /** 63 | * offsetExists 64 | * @param string $key 65 | * @return bool 66 | */ 67 | #[\ReturnTypeWillChange] 68 | public function offsetExists( $key ) { 69 | return metadata_exists( 'post', $this->product_id, $this->maybe_prefix_meta_key( $key ) ); 70 | } 71 | 72 | /** 73 | * Nothing to do here as we access post meta directly. 74 | */ 75 | #[\ReturnTypeWillChange] 76 | public function offsetUnset( $key ) { 77 | } 78 | 79 | /** 80 | * We only work with post meta data that has meta keys prefixed with an underscore, so 81 | * add a prefix if it is not already set. 82 | */ 83 | protected function maybe_prefix_meta_key( $key ) { 84 | if ( '_' != substr( $key, 0, 1 ) ) { 85 | $key = '_' . $key; 86 | } 87 | return $key; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /includes/legacy/class-wcs-product-legacy.php: -------------------------------------------------------------------------------- 1 | scheduled_hook = 'wcs_add_start_date_metadata'; 30 | $this->log_handle = 'wcs-add-start-date-metadata'; 31 | $this->logger = $logger; 32 | } 33 | 34 | /** 35 | * Update a subscription, saving its start date as metadata. 36 | * 37 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.4.0 38 | */ 39 | protected function update_item( $subscription_id ) { 40 | try { 41 | $subscription = wcs_get_subscription( $subscription_id ); 42 | 43 | if ( false === $subscription ) { 44 | throw new Exception( 'Failed to instantiate subscription object' ); 45 | } 46 | 47 | // Saving the subscription is enough to save the start date. 48 | $subscription->save(); 49 | 50 | $this->log( sprintf( 'Subscription ID %d start date metadata added.', $subscription_id ) ); 51 | } catch ( Exception $e ) { 52 | $this->log( sprintf( '--- Exception caught adding start date metadata to subscription %d - exception message: %s ---', $subscription_id, $e->getMessage() ) ); 53 | } 54 | } 55 | 56 | /** 57 | * Get a batch of subscriptions to repair. 58 | * 59 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.4.0 60 | * @return array A list of subscription ids which may need to be repaired. 61 | */ 62 | protected function get_items_to_update() { 63 | global $wpdb; 64 | 65 | return $wpdb->get_col( 66 | "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'shop_subscription' 67 | AND post_status NOT IN ( 'trash', 'auto-draft' ) 68 | AND ID NOT IN ( SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_schedule_start' ) 69 | LIMIT 20" 70 | ); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /includes/upgrades/class-wcs-repair-subscription-address-indexes.php: -------------------------------------------------------------------------------- 1 | scheduled_hook = 'wcs_add_missing_subscription_address_indexes'; 33 | $this->log_handle = 'wcs-add-subscription-address-indexes'; 34 | $this->logger = $logger; 35 | } 36 | 37 | /** 38 | * Update a subscription, setting its address indexes. 39 | * 40 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3.0 41 | */ 42 | protected function update_item( $subscription_id ) { 43 | try { 44 | $subscription = wcs_get_subscription( $subscription_id ); 45 | 46 | if ( false === $subscription ) { 47 | throw new Exception( 'Failed to instantiate subscription object' ); 48 | } 49 | 50 | // Saving the subscription sets the address indexes if they don't exist. 51 | $subscription->save(); 52 | 53 | $this->log( sprintf( 'Subscription ID %d address index(es) added.', $subscription_id ) ); 54 | } catch ( Exception $e ) { 55 | $this->log( sprintf( '--- Exception caught repairing subscription %d - exception message: %s ---', $subscription_id, $e->getMessage() ) ); 56 | } 57 | } 58 | 59 | /** 60 | * Get a batch of subscriptions which need address indexes. 61 | * 62 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3.0 63 | * @return array A list of subscription ids which need address indexes. 64 | */ 65 | protected function get_items_to_update() { 66 | return get_posts( array( 67 | 'post_type' => 'shop_subscription', 68 | 'posts_per_page' => 20, 69 | 'post_status' => 'any', 70 | 'fields' => 'ids', 71 | 'meta_query' => array( 72 | array( 73 | 'key' => '_billing_address_index', 74 | 'compare' => 'NOT EXISTS', 75 | ), 76 | ), 77 | ) ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /includes/upgrades/class-wcs-upgrade-1-3.php: -------------------------------------------------------------------------------- 1 | query( " UPDATE $wpdb->options 28 | SET option_name = TRIM(LEADING '_transient_timeout_' FROM option_name) 29 | WHERE option_name LIKE '_transient_timeout_wcs_blocker_%'" ); 30 | 31 | // Change transient keys from the < 1.1.5 format to new format 32 | $wpdb->query( " UPDATE $wpdb->options 33 | SET option_name = CONCAT('wcs_blocker_', TRIM(LEADING '_transient_timeout_block_scheduled_subscription_payments_' FROM option_name)) 34 | WHERE option_name LIKE '_transient_timeout_block_scheduled_subscription_payments_%'" ); 35 | 36 | // Delete old transient values 37 | $wpdb->query( " DELETE FROM $wpdb->options 38 | WHERE option_name LIKE '_transient_wcs_blocker_%' 39 | OR option_name LIKE '_transient_block_scheduled_subscription_payments_%'" ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /includes/upgrades/class-wcs-upgrade-2-1.php: -------------------------------------------------------------------------------- 1 | query( 'SET SQL_BIG_SELECTS = 1;' ); 31 | 32 | $cancelled_date_meta_key = wcs_get_date_meta_key( 'cancelled' ); 33 | 34 | // Run two separate insert queries for pending cancellation and cancelled subscriptions. This could easily be done in one query, but we'll run it in two separate queries to minimise issues with large databases. 35 | foreach ( array( 'wc-pending-cancel', 'wc-cancelled' ) as $post_status ) { 36 | 37 | $rows_inserted = $wpdb->query( $wpdb->prepare( 38 | "INSERT INTO {$wpdb->postmeta}(post_id, meta_key, meta_value) 39 | SELECT ID, %s, post_modified_gmt 40 | FROM {$wpdb->posts} as posts 41 | WHERE post_status = %s 42 | AND NOT EXISTS ( 43 | SELECT null 44 | FROM {$wpdb->postmeta} as postmeta 45 | WHERE postmeta.post_id = posts.ID 46 | AND postmeta.meta_key = %s 47 | ) 48 | ", 49 | $cancelled_date_meta_key, 50 | $post_status, 51 | $cancelled_date_meta_key 52 | ) ); 53 | 54 | WCS_Upgrade_Logger::add( sprintf( 'v2.1: Set _schedule_cancelled date to post_modified_gmt column value for %d subscriptions with %s status.', $rows_inserted, $post_status ) ); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /includes/upgrades/class-wcs-upgrade-3-1-0.php: -------------------------------------------------------------------------------- 1 | get_results( "SELECT webhook_id FROM {$wpdb->prefix}wc_webhooks WHERE `topic` LIKE 'subscription.%' AND `api_version` = 3" ); 25 | 26 | if ( ! empty( $results ) && is_array( $results ) ) { 27 | WCS_Upgrade_Logger::add( sprintf( '3.1.0 - Updating %d subscription webhooks to use API Version 1 when building the payload to preserve backwards compatibility.', count( $results ) ) ); 28 | 29 | foreach ( $results as $result ) { 30 | $webhook = ! empty( $result->webhook_id ) ? wc_get_webhook( $result->webhook_id ) : null; 31 | 32 | if ( $webhook ) { 33 | $webhook->set_api_version( 1 ); 34 | $webhook->save(); 35 | 36 | WCS_Upgrade_Logger::add( sprintf( 'Updated webhook: %s (#%d).', $webhook->get_name(), $webhook->get_id() ) ); 37 | } else { 38 | WCS_Upgrade_Logger::add( sprintf( 'Warning! Couldn\'t find and update webhook: %s', print_r( $result, true ) ) ); 39 | } 40 | } 41 | } else { 42 | WCS_Upgrade_Logger::add( '3.1.0 - No subscription webhooks found using API version 3. No updates needed.' ); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /includes/upgrades/templates/update-welcome-notice.php: -------------------------------------------------------------------------------- 1 | 2 |

3 |

4 | tags ?> 5 | ', '' ) ); ?> 6 | 7 |

8 |

9 | 14 |
15 | 16 |

17 | -------------------------------------------------------------------------------- /includes/upgrades/templates/wcs-upgrade-in-progress.php: -------------------------------------------------------------------------------- 1 | 20 | 21 | > 22 | 23 | 24 | <?php esc_html_e( 'WooCommerce Subscriptions Update in Progress', 'woocommerce-subscriptions' ); ?> 25 | 26 | 27 | 28 | 29 |

WooCommerce Subscriptions

30 |

31 |

32 |

35 |

36 |

37 | 38 | 39 | is_type( 'variation' ) ) { 28 | $parent_product = wc_get_product( $product->get_parent_id() ); 29 | } else { 30 | $parent_product = $product; 31 | } 32 | 33 | return apply_filters( 'woocommerce_subscriptions_product_limitation', WC_Subscriptions_Product::get_meta_data( $parent_product, 'subscription_limit', 'no', 'use_default_value' ), $product ); 34 | } 35 | 36 | /** 37 | * Returns true if product is limited to one active subscription and user currently has this product on-hold. 38 | * 39 | * @param int|WC_Product $product A WC_Product object or the ID of a product 40 | * @return boolean 41 | */ 42 | function wcs_is_product_limited_for_user( $product, $user_id = 0 ) { 43 | if ( ! is_object( $product ) ) { 44 | $product = wc_get_product( $product ); 45 | } 46 | 47 | if ( empty( $user_id ) ) { 48 | $user_id = get_current_user_id(); 49 | } 50 | 51 | $is_limited_for_user = false; 52 | $product_limitation = wcs_get_product_limitation( $product ); 53 | 54 | // If the subscription is limited to 1 active and the customer has a subscription to this product on-hold. 55 | if ( 'active' == $product_limitation && wcs_user_has_subscription( $user_id, $product->get_id(), 'on-hold' ) ) { 56 | $is_limited_for_user = true; 57 | } elseif ( 'no' !== $product_limitation ) { 58 | $is_limited_for_user = wcs_user_has_subscription( $user_id, $product->get_id(), $product_limitation ); 59 | 60 | // If the product is limited for any status, there exists a chance that the customer has cancelled subscriptions which cannot be resubscribed to as they have no completed payments. 61 | if ( 'any' === $product_limitation && $is_limited_for_user ) { 62 | $is_limited_for_user = false; 63 | 64 | foreach ( wcs_get_users_subscriptions( $user_id ) as $subscription ) { 65 | // Skip if the subscription is not for the product we are checking. 66 | if ( ! $subscription->has_product( $product->get_id() ) ) { 67 | continue; 68 | } 69 | 70 | if ( ! $subscription->has_status( 'cancelled' ) || 0 !== $subscription->get_payment_count() ) { 71 | $is_limited_for_user = true; 72 | break; 73 | } 74 | } 75 | } 76 | } 77 | 78 | return apply_filters( 'woocommerce_subscriptions_product_limited_for_user', $is_limited_for_user, $product, $user_id ); 79 | } 80 | -------------------------------------------------------------------------------- /languages/woocommerce-subscriptions-fr.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Automattic/woocommerce-subscriptions-core/0795346299f189973e91811133eafea52b5c4f11/languages/woocommerce-subscriptions-fr.mo -------------------------------------------------------------------------------- /templates/admin/deprecated/html-variation-synchronisation.php: -------------------------------------------------------------------------------- 1 | 16 | 17 | > 18 | 'variable' . WC_Subscriptions_Synchroniser::$post_meta_key . '[' . $loop . ']', 20 | 'class' => 'wc_input_subscription_payment_sync wc-enhanced-select', 21 | 'wrapper_class' => '_subscription_payment_sync_field', 22 | 'label' => WC_Subscriptions_Synchroniser::$sync_field_label, 23 | 'options' => WC_Subscriptions_Synchroniser::get_billing_period_ranges( $subscription_period ), 24 | 'description' => WC_Subscriptions_Synchroniser::$sync_description, 25 | 'desc_tip' => true, 26 | 'value' => $payment_day, 27 | ) );?> 28 | 29 | > 30 | 31 | 'variable' . WC_Subscriptions_Synchroniser::$post_meta_key_day . '[' . $loop . ']', 33 | 'class' => 'wc_input_subscription_payment_sync wc-enhanced-select', 34 | 'wrapper_class' => '_subscription_payment_sync_field', 35 | 'label' => WC_Subscriptions_Synchroniser::$sync_field_label, 36 | 'placeholder' => _x( 'Day', 'input field placeholder for day field for annual subscriptions', 'woocommerce-subscriptions' ), 37 | 'value' => $payment_day, 38 | 'type' => 'number', 39 | 'custom_attributes' => array( 40 | 'step' => '1', 41 | 'min' => '0', 42 | 'max' => '31', 43 | ), 44 | ) ); 45 | 46 | woocommerce_wp_select( array( 47 | 'id' => 'variable' . WC_Subscriptions_Synchroniser::$post_meta_key_month . '[' . $loop . ']', 48 | 'class' => 'wc_input_subscription_payment_sync wc-enhanced-select', 49 | 'wrapper_class' => '_subscription_payment_sync_field', 50 | 'label' => '', 51 | 'options' => $wp_locale->month, 52 | 'description' => WC_Subscriptions_Synchroniser::$sync_description_year, 53 | 'desc_tip' => true, 54 | 'value' => $payment_month, // Explicitly set value in to ensure backward compatibility 55 | ) ); 56 | ?> 57 | 58 | 59 | -------------------------------------------------------------------------------- /templates/admin/deprecated/order-shipping-html.php: -------------------------------------------------------------------------------- 1 | 6 |
7 |

8 | 9 | 10 |

11 |

12 | 41 |

42 |

43 | 44 |

45 | 46 | × 47 |
48 |
49 | -------------------------------------------------------------------------------- /templates/admin/deprecated/order-tax-html.php: -------------------------------------------------------------------------------- 1 | 6 |
7 |

8 | 14 | 15 |

16 |

17 | 18 | 19 |

20 |

21 | 22 | 23 |

24 | × 25 |
26 |
27 | -------------------------------------------------------------------------------- /templates/admin/html-admin-empty-list-table.php: -------------------------------------------------------------------------------- 1 | 11 |
12 |
13 | 14 |

15 |
16 | 17 |
18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /templates/admin/html-admin-notice.php: -------------------------------------------------------------------------------- 1 | 12 |
print_attributes(); ?>> 13 | has_heading() ) : ?> 14 |

print_heading(); ?>

15 | 16 | 17 | print_content(); ?> 18 | 19 | has_actions() ) : ?> 20 |

get_actions() as $action ) { ?> 21 | 22 | 23 |

24 | 25 | 26 | is_dismissible() ) : ?> 27 | 28 | 29 |
30 | -------------------------------------------------------------------------------- /templates/admin/html-failed-scheduled-action-notice.php: -------------------------------------------------------------------------------- 1 | 24 |

', 33 | '' 34 | )?> 35 |

36 | 37 | array( 'href' => array() ) ) ); ?> 39 | 40 |

failed-scheduled-actions', 45 | '', 46 | '' 47 | );?> 48 |

49 | 50 | -------------------------------------------------------------------------------- /templates/admin/html-variation-synchronisation.php: -------------------------------------------------------------------------------- 1 | 18 | 50 | -------------------------------------------------------------------------------- /templates/admin/status.php: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | $data ) { 28 | // Use mark key if available, otherwise default back to the success key. 29 | if ( isset( $data['mark'] ) ) { 30 | $mark = $data['mark']; 31 | } elseif ( isset( $data['success'] ) && $data['success'] ) { 32 | $mark = 'yes'; 33 | } else { 34 | $mark = 'error'; 35 | } 36 | 37 | // Use mark_icon key if available, otherwise set based on $mark 38 | if ( isset( $data['mark_icon'] ) ) { 39 | $mark_icon = $data['mark_icon']; 40 | } elseif ( 'yes' === $mark ) { 41 | $mark_icon = 'yes'; 42 | } else { 43 | $mark_icon = 'no-alt'; 44 | } 45 | ?> 46 | 47 | 48 | 49 | 84 | 85 | 86 | 87 |
21 |

22 | 23 |

:  50 | '; 67 | $row_number--; 68 | } 69 | } 70 | if ( isset( $data['note'] ) ) { 71 | if ( empty( $mark ) ) { 72 | echo wp_kses_post( $data['note'] ); 73 | } else { ?> 74 | '; 77 | } 78 | echo wp_kses_post( $data['note'] );?> 79 | 83 |
88 | -------------------------------------------------------------------------------- /templates/cart/cart-recurring-shipping.php: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 31 | customer->has_calculated_shipping() ) : ?> 32 | 33 | 34 | 35 | 36 | 37 | 38 | ' . wp_kses_post( $package_details ) . '

'; ?> 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /templates/checkout/recurring-coupon-totals.php: -------------------------------------------------------------------------------- 1 | cart->get_coupons() as $code => $coupon ) { 14 | foreach ( $recurring_carts as $recurring_cart_key => $recurring_cart ) { 15 | foreach ( $recurring_cart->get_coupons() as $recurring_code => $recurring_coupon ) { 16 | if ( $recurring_code !== $code ) { 17 | continue; 18 | } ?> 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | $recurring_cart ) { 13 | foreach ( $recurring_cart->get_fees() as $recurring_fee ) { ?> 14 | 15 | name ); ?> 16 | 17 | cart->get_taxes() as $tax_id => $tax_total ) { 14 | foreach ( $recurring_carts as $recurring_cart_key => $recurring_cart ) { 15 | foreach ( $recurring_cart->get_tax_totals() as $recurring_code => $recurring_tax ) { 16 | if ( ! isset( $recurring_tax->tax_rate_id ) || $recurring_tax->tax_rate_id !== $tax_id ) { 17 | continue; 18 | } 19 | 20 | /** 21 | * Allow third-parties to filter the tax displayed. 22 | * 23 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v3.1.0 24 | * @param string The recurring cart's tax total price string for this tax code. 25 | * @param WC_Cart $recurring_cart The recurring cart. 26 | * @param string $recurring_code The tax code. 27 | * @param object $recurring_tax The recurring tax data generated by @see WC_Cart::get_tax_totals() 28 | */ 29 | $tax_amount = wp_kses_post( apply_filters( 'wcs_recurring_cart_itemized_tax_totals_html', wcs_cart_price_string( $recurring_tax->formatted_amount, $recurring_cart ), $recurring_cart, $recurring_code, $recurring_tax ) ); 30 | 31 | // If the returned amount is empty, skip it. 32 | if ( empty( $tax_amount ) ) { 33 | continue; 34 | } ?> 35 | 36 | 37 | 38 | 39 | 40 | label ); ?> 41 | 42 | 43 | 44 | 45 | $recurring_cart ) { ?> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | $recurring_cart ) { ?> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | $recurring_cart ) { 14 | /** 15 | * Allow third-parties to filter the tax displayed. 16 | * 17 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v3.1.0 18 | * @param string The recurring cart's total tax price string. 19 | * @param WC_Cart $recurring_cart The recurring cart. 20 | */ 21 | $tax_amount = wp_kses_post( apply_filters( 'wcs_recurring_cart_tax_totals_html', wcs_cart_price_string( $recurring_cart->get_taxes_total(), $recurring_cart ), $recurring_cart ) ); 22 | 23 | // Skip the tax if there's nothing to display. 24 | if ( empty( $tax_amount ) ) { 25 | continue; 26 | } ?> 27 | 28 | 29 | 30 | 31 | 32 | countries->tax_or_vat() ); ?> 33 | 34 | 35 | 36 | 37 | 15 | 16 | 17 | 18 | 19 | 20 | 58 | -------------------------------------------------------------------------------- /templates/checkout/subscription-receipt.php: -------------------------------------------------------------------------------- 1 | 14 | 42 | 43 | get_payment_method(), $subscription->get_id() ); ?> 44 | 45 |
46 | -------------------------------------------------------------------------------- /templates/emails/admin-new-renewal-order.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | ' : ''; ?> 21 | 22 |

get_formatted_billing_full_name() ) ); ?>

23 | ' : ''; ?> 24 | 25 | ' : ''; 49 | echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) ); 50 | echo $email_improvements_enabled ? '' : ''; 51 | } 52 | 53 | do_action( 'woocommerce_email_footer', $email ); 54 | -------------------------------------------------------------------------------- /templates/emails/admin-payment-retry.php: -------------------------------------------------------------------------------- 1 | 20 | 21 | ' : ''; ?> 22 | 23 |

get_order_number(), $order->get_formatted_billing_full_name(), wcs_get_human_time_diff( $retry->get_time() ) ) ); ?>

24 |

25 | ' : ''; ?> 26 | 27 | ' : ''; 51 | echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) ); 52 | echo $email_improvements_enabled ? '' : ''; 53 | } 54 | 55 | /** 56 | * @hooked WC_Emails::email_footer() Output the email footer 57 | */ 58 | do_action( 'woocommerce_email_footer', $email ); 59 | -------------------------------------------------------------------------------- /templates/emails/customer-completed-renewal-order.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | ' : ''; ?> 21 | 22 |

get_billing_first_name() ) ); ?>

23 |

24 | ' : ''; ?> 25 | 26 | ' : ''; 50 | echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) ); 51 | echo $email_improvements_enabled ? '' : ''; 52 | } 53 | 54 | do_action( 'woocommerce_email_footer', $email ); 55 | -------------------------------------------------------------------------------- /templates/emails/customer-completed-switch-order.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | ' : ''; ?> 21 | 22 |

get_billing_first_name() ) ); ?>

23 |

24 | ' : ''; ?> 25 | 38 | 39 |

40 | 41 | ' : ''; 57 | echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) ); 58 | echo $email_improvements_enabled ? '' : ''; 59 | } 60 | 61 | do_action( 'woocommerce_email_footer', $email ); 62 | -------------------------------------------------------------------------------- /templates/emails/customer-notification-auto-trial-ending.php: -------------------------------------------------------------------------------- 1 | ' : ''; ?> 20 |

21 | get_billing_first_name() 27 | ) 28 | ); 29 | ?> 30 |

31 |

32 | %2$s.', 38 | 'woocommerce-subscriptions' 39 | ), 40 | $subscription_time_til_event, 41 | $subscription_event_date 42 | ), 43 | [ 'strong' => [] ] 44 | ); 45 | ?> 46 |

47 |

48 | get_view_order_url() ) . '">' . esc_html__( 'account dashboard', 'woocommerce-subscriptions' ) . '' 55 | ), 56 | [ 'a' => [ 'href' => true ] ] 57 | ); 58 | ?> 59 |

60 | ' : ''; 62 | 63 | // Show subscription details. 64 | \WC_Subscriptions_Email::subscription_details( $subscription, $order, $sent_to_admin, $plain_text, true ); 65 | 66 | /** This action is documented in templates/emails/customer-notification-auto-renewal.php */ 67 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 68 | 69 | /** 70 | * Show user-defined additional content - this is set in each email's settings. 71 | */ 72 | if ( $additional_content ) { 73 | echo $email_improvements_enabled ? '
' : ''; 76 | } 77 | 78 | /** 79 | * @hooked WC_Emails::email_footer() Output the email footer. 80 | * 81 | * @since 6.9.0 82 | */ 83 | do_action( 'woocommerce_email_footer', $email ); 84 | -------------------------------------------------------------------------------- /templates/emails/customer-notification-expiring-subscription.php: -------------------------------------------------------------------------------- 1 | 18 | ' : ''; ?> 19 | get_billing_first_name() 25 | ) 26 | ); 27 | ?> 28 |

29 | 30 | 31 |

32 | %2$s.', 38 | 'woocommerce-subscriptions' 39 | ), 40 | $subscription_time_til_event, 41 | $subscription_event_date 42 | ), 43 | [ 'strong' => [] ] 44 | ); 45 | ?> 46 |

47 | ' : ''; 60 | echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) ); 61 | echo $email_improvements_enabled ? '' : ''; 62 | } 63 | 64 | /** 65 | * @hooked WC_Emails::email_footer() Output the email footer. 66 | * 67 | * @since 6.9.0 68 | */ 69 | do_action( 'woocommerce_email_footer', $email ); 70 | -------------------------------------------------------------------------------- /templates/emails/customer-notification-manual-trial-ending.php: -------------------------------------------------------------------------------- 1 | ' : ''; ?> 20 |

21 | get_billing_first_name() 27 | ) 28 | ); 29 | ?> 30 |

31 |

32 | %2$s.', 38 | 'woocommerce-subscriptions' 39 | ), 40 | $subscription_time_til_event, 41 | $subscription_event_date 42 | ), 43 | [ 'strong' => [] ] 44 | ); 45 | ?> 46 |

47 | ' : ''; 49 | 50 | // Show subscription details. 51 | \WC_Subscriptions_Email::subscription_details( $subscription, $order, $sent_to_admin, $plain_text ); 52 | 53 | /** This action is documented in templates/emails/customer-notification-auto-renewal.php */ 54 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 55 | 56 | /** 57 | * Show user-defined additional content - this is set in each email's settings. 58 | */ 59 | if ( $additional_content ) { 60 | echo $email_improvements_enabled ? '
' : ''; 63 | } 64 | 65 | /** 66 | * @hooked WC_Emails::email_footer() Output the email footer. 67 | * 68 | * @since 6.9.0 69 | */ 70 | do_action( 'woocommerce_email_footer', $email ); 71 | -------------------------------------------------------------------------------- /templates/emails/customer-on-hold-renewal-order.php: -------------------------------------------------------------------------------- 1 | ' : ''; 19 | /* translators: %s: Customer first name */ ?> 20 |

get_billing_first_name() ) ); ?>

21 |

22 | ' : ''; 24 | 25 | /* 26 | * @hooked WC_Subscriptions_Email::order_download_details() Shows the order details table. 27 | * @hooked WC_Subscriptions_Email::order_details() Shows the order details table. 28 | */ 29 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 30 | 31 | /* 32 | * @hooked WC_Emails::order_meta() Shows order meta data. 33 | */ 34 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 35 | 36 | /* 37 | * @hooked WC_Emails::customer_details() Shows customer details 38 | * @hooked WC_Emails::email_address() Shows email address 39 | */ 40 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 41 | 42 | /** 43 | * Show user-defined additional content - this is set in each email's settings. 44 | */ 45 | if ( $additional_content ) { 46 | echo $email_improvements_enabled ? '
' : ''; 49 | } 50 | 51 | /* 52 | * @hooked WC_Emails::email_footer() Output the email footer 53 | */ 54 | do_action( 'woocommerce_email_footer', $email ); 55 | -------------------------------------------------------------------------------- /templates/emails/customer-payment-retry.php: -------------------------------------------------------------------------------- 1 | ' : ''; 15 | 16 | /* translators: %s: Customer first name */ ?> 17 |

get_billing_first_name() ) ); ?>

18 | 19 |

get_time() ) ) ); ?>

20 | 21 | 22 |

get_checkout_payment_url() ) . '">', '' ), array( 'a' => array( 'href' => true ) ) ); ?>

23 | 24 | ' : ''; ?> 25 | 26 | ' : ''; 34 | echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) ); 35 | echo $email_improvements_enabled ? '' : ''; 36 | } 37 | 38 | do_action( 'woocommerce_email_footer', $email ); 39 | -------------------------------------------------------------------------------- /templates/emails/customer-processing-renewal-order.php: -------------------------------------------------------------------------------- 1 | ' : ''; 15 | 16 | /* translators: %s: Customer first name */ ?> 17 |

get_billing_first_name() ) ); ?>

18 | 19 |

get_order_number() ) ); ?>

20 | ' : ''; 23 | 24 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 25 | 26 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 27 | 28 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 29 | 30 | /** 31 | * Show user-defined additional content - this is set in each email's settings. 32 | */ 33 | if ( $additional_content ) { 34 | echo $email_improvements_enabled ? '
' : ''; 37 | } 38 | 39 | do_action( 'woocommerce_email_footer', $email ); 40 | -------------------------------------------------------------------------------- /templates/emails/customer-renewal-invoice.php: -------------------------------------------------------------------------------- 1 | ' : ''; 15 | 16 | /* translators: %s: Customer first name */ ?> 17 |

get_billing_first_name() ) ); ?>

18 | 19 | has_status( 'pending' ) ) : ?> 20 |

21 | get_checkout_payment_url() ) . '">' 32 | . esc_html__( 'Pay Now »', 'woocommerce-subscriptions' ) . 33 | '' 34 | ), 35 | [ 36 | 'a' => [ 'href' => true ], 37 | ] 38 | ); 39 | ?> 40 |

41 | has_status( 'failed' ) ) : ?> 42 |

43 | get_checkout_payment_url() ) . '">' 54 | . esc_html__( 'Pay Now »', 'woocommerce-subscriptions' ) . 55 | '' 56 | ), 57 | [ 58 | 'a' => [ 'href' => true ], 59 | ] 60 | ); 61 | ?> 62 |

63 | 64 | 65 | ' : ''; ?> 66 | 67 | ' : ''; 75 | echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) ); 76 | echo $email_improvements_enabled ? '' : ''; 77 | } 78 | 79 | do_action( 'woocommerce_email_footer', $email ); 80 | -------------------------------------------------------------------------------- /templates/emails/plain/admin-new-renewal-order.php: -------------------------------------------------------------------------------- 1 | get_formatted_billing_full_name() ); 17 | 18 | echo "\n\n"; 19 | 20 | echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 21 | 22 | /** 23 | * @hooked WC_Subscriptions_Email::order_details() Shows the order details table. 24 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.1.0 25 | */ 26 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 27 | 28 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 29 | 30 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 31 | 32 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 33 | 34 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 35 | 36 | /** 37 | * Show user-defined additional content - this is set in each email's settings. 38 | */ 39 | if ( $additional_content ) { 40 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 41 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 42 | } 43 | 44 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 45 | -------------------------------------------------------------------------------- /templates/emails/plain/admin-new-switch-order.php: -------------------------------------------------------------------------------- 1 | get_formatted_billing_full_name(), $count ); 19 | 20 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 21 | 22 | /** 23 | * @hooked WC_Subscriptions_Email::order_details() Shows the order details table. 24 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.1.0 25 | */ 26 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 27 | 28 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 29 | 30 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 31 | 32 | remove_filter( 'woocommerce_order_item_meta_end', 'WC_Subscriptions_Switcher::print_switch_link', 10 ); 33 | 34 | foreach ( $subscriptions as $subscription ) { 35 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 36 | } 37 | 38 | add_filter( 'woocommerce_order_item_meta_end', 'WC_Subscriptions_Switcher::print_switch_link', 10, 3 ); 39 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 40 | 41 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 42 | 43 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 44 | 45 | /** 46 | * Show user-defined additional content - this is set in each email's settings. 47 | */ 48 | if ( $additional_content ) { 49 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 50 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 51 | } 52 | 53 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 54 | -------------------------------------------------------------------------------- /templates/emails/plain/admin-payment-retry.php: -------------------------------------------------------------------------------- 1 | get_order_number(), $order->get_formatted_billing_full_name(), wcs_get_human_time_diff( $retry->get_time() ) ) . "\n\n"; 21 | echo sprintf( __( 'The renewal order is as follows:', 'woocommerce-subscriptions' ) ) . "\n\n"; 22 | 23 | echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 24 | 25 | /** 26 | * @hooked WC_Emails::order_details() Shows the order details table. 27 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.5.0 28 | */ 29 | do_action( 'woocommerce_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 30 | 31 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 32 | 33 | /** 34 | * @hooked WC_Emails::order_meta() Shows order meta data. 35 | */ 36 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 37 | 38 | /** 39 | * @hooked WC_Emails::customer_details() Shows customer details 40 | * @hooked WC_Emails::email_address() Shows email address 41 | */ 42 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 43 | 44 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 45 | 46 | /** 47 | * Show user-defined additional content - this is set in each email's settings. 48 | */ 49 | if ( $additional_content ) { 50 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 51 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 52 | } 53 | 54 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 55 | -------------------------------------------------------------------------------- /templates/emails/plain/cancelled-subscription.php: -------------------------------------------------------------------------------- 1 | get_formatted_billing_full_name() ); 17 | 18 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 19 | 20 | /** 21 | * @hooked WC_Subscriptions_Email::order_details() Shows the order details table. 22 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.1.0 23 | */ 24 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 25 | 26 | echo "\n----------\n\n"; 27 | 28 | $last_order_time_created = $subscription->get_time( 'last_order_date_created', 'site' ); 29 | 30 | if ( ! empty( $last_order_time_created ) ) { 31 | // translators: placeholder is last time subscription was paid 32 | echo sprintf( __( 'Last Order Date: %s', 'woocommerce-subscriptions' ), date_i18n( wc_date_format(), $last_order_time_created ) ) . "\n"; 33 | } 34 | 35 | $end_time = $subscription->get_time( 'end', 'site' ); 36 | 37 | if ( ! empty( $end_time ) ) { 38 | // translators: placeholder is localised date string 39 | echo sprintf( __( 'End of Prepaid Term: %s', 'woocommerce-subscriptions' ), date_i18n( wc_date_format(), $end_time ) ) . "\n"; 40 | } 41 | 42 | do_action( 'woocommerce_email_order_meta', $subscription, $sent_to_admin, $plain_text, $email ); 43 | 44 | echo "\n" . sprintf( _x( 'View Subscription: %s', 'in plain emails for subscription information', 'woocommerce-subscriptions' ), wcs_get_edit_post_link( $subscription->get_id() ) ) . "\n"; 45 | 46 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 47 | 48 | do_action( 'woocommerce_email_customer_details', $subscription, $sent_to_admin, $plain_text, $email ); 49 | 50 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 51 | 52 | /** 53 | * Show user-defined additional content - this is set in each email's settings. 54 | */ 55 | if ( $additional_content ) { 56 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 57 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 58 | } 59 | 60 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 61 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-completed-renewal-order.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() ) ) . "\n\n"; 17 | esc_html_e( 'We have finished processing your subscription renewal order.', 'woocommerce-subscriptions' ) . "\n\n"; 18 | 19 | echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 20 | 21 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 22 | 23 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 24 | 25 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 26 | 27 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 28 | 29 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 30 | 31 | /** 32 | * Show user-defined additional content - this is set in each email's settings. 33 | */ 34 | if ( $additional_content ) { 35 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 36 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 37 | } 38 | 39 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 40 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-completed-switch-order.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() ) ) . "\n\n"; 17 | esc_html_e( 'You have successfully changed your subscription items. Your new order and subscription details are shown below for your reference:', 'woocommerce-subscriptions' ); 18 | 19 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 20 | 21 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 22 | 23 | // translators: placeholder is order's view url 24 | echo "\n" . sprintf( __( 'View your order: %s', 'woocommerce-subscriptions' ), $order->get_view_order_url() ); 25 | 26 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 27 | 28 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 29 | 30 | foreach ( $subscriptions as $subscription ) { 31 | 32 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 33 | 34 | // translators: placeholder is subscription's view url 35 | echo "\n" . sprintf( __( 'View your subscription: %s', 'woocommerce-subscriptions' ), $subscription->get_view_order_url() ); 36 | } 37 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 38 | 39 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 40 | 41 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 42 | 43 | /** 44 | * Show user-defined additional content - this is set in each email's settings. 45 | */ 46 | if ( $additional_content ) { 47 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 48 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 49 | } 50 | 51 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 52 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-notification-auto-renewal.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() 21 | ) 22 | ); 23 | 24 | echo "\n\n"; 25 | 26 | echo esc_html( 27 | sprintf( 28 | // translators: %1$s: human readable time difference (eg 3 days, 1 day), %2$s: date in local format. 29 | __( 30 | 'Your subscription will automatically renew in %1$s — that’s %2$s.', 31 | 'woocommerce-subscriptions' 32 | ), 33 | $subscription_time_til_event, 34 | $subscription_event_date 35 | ) 36 | ); 37 | 38 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 39 | 40 | // Show subscription details. 41 | \WC_Subscriptions_Email::subscription_details( $subscription, $order, $sent_to_admin, $plain_text, true ); 42 | 43 | /** This action is documented in templates/emails/customer-notification-auto-renewal.php */ 44 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 45 | 46 | esc_html_e( 'You can manage this subscription from your account dashboard: ', 'woocommerce-subscriptions' ); 47 | echo esc_url( wc_get_page_permalink( 'myaccount' ) ); 48 | 49 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 50 | 51 | /** 52 | * Show user-defined additional content - this is set in each email's settings. 53 | */ 54 | if ( $additional_content ) { 55 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 56 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 57 | } 58 | 59 | echo esc_html( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) ); 60 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-notification-auto-trial-ending.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() 21 | ) 22 | ); 23 | 24 | echo "\n\n"; 25 | 26 | echo esc_html( 27 | sprintf( 28 | // translators: %1$s: human readable time difference (eg 3 days, 1 day), %2$s: date in local format. 29 | __( 30 | 'Your paid subscription begins when your free trial expires in %1$s — that’s %2$s.', 31 | 'woocommerce-subscriptions' 32 | ), 33 | $subscription_time_til_event, 34 | $subscription_event_date 35 | ) 36 | ); 37 | 38 | echo "\n\n"; 39 | 40 | // translators: %1$s: link to account dashboard. 41 | esc_html_e( 'Payment will be deducted using the payment method on file. You can manage this subscription from your account dashboard: ', 'woocommerce-subscriptions' ); 42 | echo esc_url( wc_get_page_permalink( 'myaccount' ) ); 43 | 44 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 45 | 46 | // Show subscription details. 47 | \WC_Subscriptions_Email::subscription_details( $subscription, $order, $sent_to_admin, $plain_text, true ); 48 | 49 | /** This action is documented in templates/emails/customer-notification-auto-renewal.php */ 50 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 51 | 52 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 53 | 54 | /** 55 | * Show user-defined additional content - this is set in each email's settings. 56 | */ 57 | if ( $additional_content ) { 58 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 59 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 60 | } 61 | 62 | echo esc_html( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) ); 63 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-notification-expiring-subscription.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() 21 | ) 22 | ); 23 | 24 | echo "\n\n"; 25 | 26 | echo esc_html( 27 | sprintf( 28 | // translators: %1$s: human readable time difference (eg 3 days, 1 day), %2$s: date in local format. 29 | __( 30 | 'Your subscription expires in %1$s — that’s %2$s.', 31 | 'woocommerce-subscriptions' 32 | ), 33 | $subscription_time_til_event, 34 | $subscription_event_date 35 | ) 36 | ); 37 | 38 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 39 | 40 | // Show subscription details. 41 | \WC_Subscriptions_Email::subscription_details( $subscription, $order, $sent_to_admin, $plain_text, true ); 42 | 43 | /** This action is documented in templates/emails/customer-notification-auto-renewal.php */ 44 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 45 | 46 | /** 47 | * Show user-defined additional content - this is set in each email's settings. 48 | */ 49 | if ( $additional_content ) { 50 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 51 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 52 | } 53 | 54 | echo esc_html( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) ); 55 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-notification-manual-renewal.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() 21 | ) 22 | ); 23 | 24 | echo "\n\n"; 25 | 26 | echo esc_html( 27 | sprintf( 28 | // translators: %1$s: human readable time difference (eg 3 days, 1 day), %2$s: date in local format. 29 | __( 30 | 'Your subscription is up for renewal in %1$s — that’s %2$s.', 31 | 'woocommerce-subscriptions' 32 | ), 33 | $subscription_time_til_event, 34 | $subscription_event_date 35 | ) 36 | ); 37 | 38 | echo "\n\n"; 39 | 40 | esc_html_e( 'This subscription will not renew automatically.', 'woocommerce-subscriptions' ); 41 | echo "\n"; 42 | if ( $can_renew_early ) { 43 | esc_html_e( 44 | 'You can renew it manually in a few short steps via the Subscriptions tab in your account dashboard.', 45 | 'woocommerce-subscriptions' 46 | ); 47 | } 48 | 49 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 50 | 51 | if ( $can_renew_early ) { 52 | esc_html_e( 'Renew my subscription: ', 'woocommerce-subscriptions' ); 53 | echo esc_url( $url_for_renewal ); 54 | } else { 55 | esc_html_e( 'Manage my subscription: ', 'woocommerce-subscriptions' ); 56 | echo esc_url( $url_for_renewal ); 57 | } 58 | 59 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 60 | 61 | // Show subscription details. 62 | \WC_Subscriptions_Email::subscription_details( $subscription, $order, $sent_to_admin, $plain_text ); 63 | 64 | /** This action is documented in templates/emails/customer-notification-auto-renewal.php */ 65 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 66 | 67 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 68 | 69 | /** 70 | * Show user-defined additional content - this is set in each email's settings. 71 | */ 72 | if ( $additional_content ) { 73 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 74 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 75 | } 76 | 77 | echo esc_html( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) ); 78 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-notification-manual-trial-ending.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() 21 | ) 22 | ); 23 | 24 | echo "\n\n"; 25 | 26 | echo esc_html( 27 | sprintf( 28 | // translators: %1$s: human readable time difference (eg 3 days, 1 day), %2$s: date in local format. 29 | __( 30 | 'Your free trial expires in %1$s — that’s %2$s.', 31 | 'woocommerce-subscriptions' 32 | ), 33 | $subscription_time_til_event, 34 | $subscription_event_date 35 | ) 36 | ); 37 | 38 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 39 | 40 | // Show subscription details. 41 | \WC_Subscriptions_Email::subscription_details( $subscription, $order, $sent_to_admin, $plain_text ); 42 | 43 | /** This action is documented in templates/emails/customer-notification-auto-renewal.php */ 44 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 45 | 46 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 47 | 48 | /** 49 | * Show user-defined additional content - this is set in each email's settings. 50 | */ 51 | if ( $additional_content ) { 52 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 53 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 54 | } 55 | 56 | echo esc_html( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) ); 57 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-on-hold-renewal-order.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() ) ) . "\n\n"; 17 | echo esc_html__( 'Thanks for your renewal order. It’s on-hold until we confirm that payment has been received. In the meantime, here’s a reminder of your order:', 'woocommerce-subscriptions' ) . "\n\n"; 18 | 19 | /* 20 | * @hooked WC_Emails::order_details() Shows the order details table. 21 | * @hooked WC_Structured_Data::generate_order_data() Generates structured data. 22 | * @hooked WC_Structured_Data::output_structured_data() Outputs structured data. 23 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.5.0 24 | */ 25 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 26 | 27 | echo "\n----------------------------------------\n\n"; 28 | 29 | /* 30 | * @hooked WC_Emails::order_meta() Shows order meta data. 31 | */ 32 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 33 | 34 | /* 35 | * @hooked WC_Emails::customer_details() Shows customer details 36 | * @hooked WC_Emails::email_address() Shows email address 37 | */ 38 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 39 | 40 | echo "\n\n----------------------------------------\n\n"; 41 | 42 | /** 43 | * Show user-defined additional content - this is set in each email's settings. 44 | */ 45 | if ( $additional_content ) { 46 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 47 | echo "\n\n----------------------------------------\n\n"; 48 | } 49 | 50 | echo wp_kses_post( apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ) ); 51 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-payment-retry.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() ) ) . "\n\n"; 17 | /* translators: %s: lowercase human time diff in the form returned by wcs_get_human_time_diff(), e.g. 'in 12 hours' */ 18 | echo sprintf( esc_html_x( 'The automatic payment to renew your subscription has failed. We will retry the payment %s.', 'In customer renewal invoice email', 'woocommerce-subscriptions' ), esc_html( wcs_get_human_time_diff( $retry->get_time() ) ) ) . "\n\n"; 19 | 20 | // translators: %1$s: link to checkout payment url, note: no full stop due to url at the end 21 | echo sprintf( esc_html_x( 'To reactivate the subscription now, you can also log in and pay for the renewal from your account page: %1$s', 'In customer renewal invoice email', 'woocommerce-subscriptions' ), esc_attr( $order->get_checkout_payment_url() ) ); 22 | 23 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 24 | 25 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 26 | 27 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 28 | 29 | /** 30 | * Show user-defined additional content - this is set in each email's settings. 31 | */ 32 | if ( $additional_content ) { 33 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 34 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 35 | } 36 | 37 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 38 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-processing-renewal-order.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() ) ) . "\n\n"; 17 | /* translators: %s: Order number */ 18 | echo sprintf( esc_html__( 'Just to let you know — we\'ve received your subscription renewal order #%s, and it is now being processed:', 'woocommerce-subscriptions' ), esc_html( $order->get_order_number() ) ); 19 | 20 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 21 | 22 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 23 | 24 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 25 | 26 | do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ); 27 | 28 | do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email ); 29 | 30 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 31 | 32 | /** 33 | * Show user-defined additional content - this is set in each email's settings. 34 | */ 35 | if ( $additional_content ) { 36 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 37 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 38 | } 39 | 40 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 41 | -------------------------------------------------------------------------------- /templates/emails/plain/customer-renewal-invoice.php: -------------------------------------------------------------------------------- 1 | get_billing_first_name() ) ) . "\n\n"; 17 | 18 | if ( $order->has_status( 'pending' ) ) { 19 | // translators: %1$s: name of the blog, %2$s: link to checkout payment url, note: no full stop due to url at the end 20 | printf( esc_html_x( 'An order has been created for you to renew your subscription on %1$s. To pay for this invoice please use the following link: %2$s', 'In customer renewal invoice email', 'woocommerce-subscriptions' ), esc_html( get_bloginfo( 'name' ) ), esc_attr( $order->get_checkout_payment_url() ) ) . "\n\n"; 21 | } elseif ( $order->has_status( 'failed' ) ) { 22 | // translators: %1$s: name of the blog, %2$s: link to checkout payment url, note: no full stop due to url at the end 23 | printf( esc_html_x( 'The automatic payment to renew your subscription with %1$s has failed. To reactivate the subscription, please log in and pay for the renewal from your account page: %2$s', 'In customer renewal invoice email', 'woocommerce-subscriptions' ), esc_html( get_bloginfo( 'name' ) ), esc_attr( $order->get_checkout_payment_url() ) ); 24 | } 25 | 26 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 27 | 28 | do_action( 'woocommerce_subscriptions_email_order_details', $order, $sent_to_admin, $plain_text, $email ); 29 | 30 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 31 | 32 | /** 33 | * Show user-defined additional content - this is set in each email's settings. 34 | */ 35 | if ( $additional_content ) { 36 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 37 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 38 | } 39 | 40 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 41 | -------------------------------------------------------------------------------- /templates/emails/plain/email-order-details.php: -------------------------------------------------------------------------------- 1 | get_order_number() ) . "\n"; 17 | echo sprintf( __( 'Order date: %s', 'woocommerce-subscriptions' ), wcs_format_datetime( wcs_get_objects_property( $order, 'date_created' ) ) ) . "\n"; 18 | } else { 19 | echo sprintf( __( 'Subscription Number: %s', 'woocommerce-subscriptions' ), $order->get_order_number() ) . "\n"; 20 | } 21 | echo "\n" . WC_Subscriptions_Email::email_order_items_table( $order, $order_items_table_args ); 22 | 23 | echo "----------\n\n"; 24 | 25 | if ( $totals = $order->get_order_item_totals() ) { 26 | foreach ( $totals as $total ) { 27 | echo $total['label'] . "\t " . $total['value'] . "\n"; 28 | } 29 | } 30 | 31 | do_action( 'woocommerce_email_after_' . $order_type . '_table', $order, $sent_to_admin, $plain_text, $email ); 32 | -------------------------------------------------------------------------------- /templates/emails/plain/expired-subscription.php: -------------------------------------------------------------------------------- 1 | get_formatted_billing_full_name() ); 17 | 18 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 19 | 20 | /** 21 | * @hooked WC_Subscriptions_Email::order_details() Shows the order details table. 22 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.1.0 23 | */ 24 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 25 | 26 | echo "\n----------\n\n"; 27 | 28 | $last_order_time_created = $subscription->get_time( 'last_order_date_created', 'site' ); 29 | 30 | if ( ! empty( $last_order_time_created ) ) { 31 | // translators: placeholder is last time subscription was paid 32 | echo sprintf( __( 'Last Order Date: %s', 'woocommerce-subscriptions' ), date_i18n( wc_date_format(), $last_order_time_created ) ) . "\n"; 33 | } 34 | 35 | $end_time = $subscription->get_time( 'end', 'site' ); 36 | 37 | if ( ! empty( $end_time ) ) { 38 | // translators: placeholder is localised date string 39 | echo sprintf( __( 'End Date: %s', 'woocommerce-subscriptions' ), date_i18n( wc_date_format(), $end_time ) ) . "\n"; 40 | } 41 | 42 | do_action( 'woocommerce_email_order_meta', $subscription, $sent_to_admin, $plain_text, $email ); 43 | 44 | echo "\n" . sprintf( _x( 'View Subscription: %s', 'in plain emails for subscription information', 'woocommerce-subscriptions' ), wcs_get_edit_post_link( $subscription->get_id() ) ) . "\n"; 45 | 46 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 47 | 48 | do_action( 'woocommerce_email_customer_details', $subscription, $sent_to_admin, $plain_text, $email ); 49 | 50 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 51 | 52 | /** 53 | * Show user-defined additional content - this is set in each email's settings. 54 | */ 55 | if ( $additional_content ) { 56 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 57 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 58 | } 59 | 60 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 61 | -------------------------------------------------------------------------------- /templates/emails/plain/on-hold-subscription.php: -------------------------------------------------------------------------------- 1 | get_formatted_billing_full_name() ); 17 | 18 | echo "\n\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n"; 19 | 20 | /** 21 | * @hooked WC_Subscriptions_Email::order_details() Shows the order details table. 22 | * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.1.0 23 | */ 24 | do_action( 'woocommerce_subscriptions_email_order_details', $subscription, $sent_to_admin, $plain_text, $email ); 25 | 26 | echo "\n----------\n\n"; 27 | 28 | $last_order_time_created = $subscription->get_time( 'last_order_date_created', 'site' ); 29 | 30 | if ( ! empty( $last_order_time_created ) ) { 31 | // translators: placeholder is last time subscription was paid 32 | echo sprintf( __( 'Last Order: %s', 'woocommerce-subscriptions' ), date_i18n( wc_date_format(), $last_order_time_created ) ) . "\n"; 33 | } 34 | 35 | // translators: placeholder is localised date string 36 | echo sprintf( __( 'Date Suspended: %s', 'woocommerce-subscriptions' ), date_i18n( wc_date_format(), time() ) ) . "\n"; 37 | 38 | do_action( 'woocommerce_email_order_meta', $subscription, $sent_to_admin, $plain_text, $email ); 39 | 40 | echo "\n" . sprintf( _x( 'View Subscription: %s', 'in plain emails for subscription information', 'woocommerce-subscriptions' ), wcs_get_edit_post_link( $subscription->get_id() ) ) . "\n"; 41 | 42 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 43 | 44 | do_action( 'woocommerce_email_customer_details', $subscription, $sent_to_admin, $plain_text, $email ); 45 | 46 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 47 | 48 | /** 49 | * Show user-defined additional content - this is set in each email's settings. 50 | */ 51 | if ( $additional_content ) { 52 | echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) ); 53 | echo "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n\n"; 54 | } 55 | 56 | echo apply_filters( 'woocommerce_email_footer_text', get_option( 'woocommerce_email_footer_text' ) ); 57 | -------------------------------------------------------------------------------- /templates/html-modal.php: -------------------------------------------------------------------------------- 1 | 12 |
13 |
14 | 20 | 21 |
22 | print_content(); ?> 23 |
24 | has_actions() ) : ?> 25 |
get_actions() as $action ) { 27 | $element_type = $action['type']; 28 | $attributes = $modal->get_attribute_string( $action['attributes'] ); 29 | 30 | echo wp_kses_post( "<{$element_type} {$attributes}>{$action['text']}" ); 31 | }?> 32 |
33 | 34 |
35 |
36 | -------------------------------------------------------------------------------- /templates/myaccount/subscription-totals.php: -------------------------------------------------------------------------------- 1 | 15 | get_order_item_totals(); 19 | 20 | // Don't display the payment method as it is included in the main subscription details table. 21 | unset( $totals['payment_method'] ); 22 | ?> 23 |

24 | 25 | 26 | -------------------------------------------------------------------------------- /templates/myaccount/subscriptions.php: -------------------------------------------------------------------------------- 1 | Subscriptions page 4 | * 5 | * @author Prospress 6 | * @category WooCommerce Subscriptions/Templates 7 | * @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.0.15 8 | */ 9 | 10 | if ( ! defined( 'ABSPATH' ) ) { 11 | exit; // Exit if accessed directly 12 | } 13 | 14 | WCS_Template_Loader::get_my_subscriptions( $current_page ); 15 | -------------------------------------------------------------------------------- /templates/myaccount/view-subscription.php: -------------------------------------------------------------------------------- 1 | $subscription ) ); 35 | ?> 36 | 37 |
38 | -------------------------------------------------------------------------------- /woocommerce-subscriptions-core.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | --------------------------------------------------------------------------------