Merge branch 'master' into fix/21110
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
name: "\U0001F46E♂️Security issue"
|
||||
about: Please report security issues *only* via https://www.hackerone.com
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
For security reasons, please report all security issues via https://hackerone.com/automattic/. Also, if the issue is valid, a bug bounty will be paid out to you.
|
||||
|
||||
Please disclose responsibly and not via GitHub (which allows for exploiting issues in the wild before the patch is released).
|
|
@ -1,34 +1,37 @@
|
|||
---
|
||||
name: "\U0001F41E Bug report"
|
||||
about: Report a bug if something isn't working as expected in the core WooCommerce
|
||||
plugin.
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed without action.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Isolating the problem (mark completed items with an [x]):**
|
||||
- [ ] I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active.
|
||||
- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/).
|
||||
- [ ] I can reproduce this bug consistently using the steps above.
|
||||
|
||||
**WordPress Environment**
|
||||
<details>
|
||||
```
|
||||
Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin.
|
||||
```
|
||||
</details>
|
||||
---
|
||||
name: "\U0001F41E Bug report"
|
||||
about: Report a bug if something isn't working as expected in the core WooCommerce
|
||||
plugin.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed without action.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Isolating the problem (mark completed items with an [x]):**
|
||||
- [ ] I have deactivated other plugins and confirmed this bug occurs when only WooCommerce plugin is active.
|
||||
- [ ] This bug happens with a default WordPress theme active, or [Storefront](https://woocommerce.com/storefront/).
|
||||
- [ ] I can reproduce this bug consistently using the steps above.
|
||||
|
||||
**WordPress Environment**
|
||||
<details>
|
||||
```
|
||||
Copy and paste the system status report from **WooCommerce > System Status** in WordPress admin.
|
||||
```
|
||||
</details>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
---
|
||||
name: "✨ New Enhancement"
|
||||
about: "If you have an idea to improve an existing feature in core or need something for development (such as a new hook) please let us know or submit a Pull Request!"
|
||||
about: If you have an idea to improve an existing feature in core or need something
|
||||
for development (such as a new hook) please let us know or submit a Pull Request!
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
---
|
||||
name: "\U0001F680 Feature request"
|
||||
about: "Suggest a new feature \U0001F389 We'll consider building it if it receives sufficient interest! \U0001F44D"
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
---
|
||||
name: "\U0001F680 Feature request"
|
||||
about: "Suggest a new feature \U0001F389 We'll consider building it if it receives
|
||||
sufficient interest! \U0001F44D"
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
---
|
||||
name: "❓ Support Question"
|
||||
about: "If you have a question \U0001F4AC please see our docs or use our forums, helpdesk,
|
||||
or Slack Community!"
|
||||
|
||||
---
|
||||
|
||||
We don't offer technical support on GitHub so we recommend using the following:
|
||||
|
||||
**Reading our documentation**
|
||||
Usage docs can be found here: https://docs.woocommerce.com/
|
||||
|
||||
If you have a problem, you may want to start with the self help guide here: https://docs.woocommerce.com/document/woocommerce-self-service-guide/
|
||||
|
||||
**Technical support for premium extensions or if you're a WooCommerce.com customer**
|
||||
from a human being - submit a ticket via the helpdesk
|
||||
https://woocommerce.com/contact-us/
|
||||
|
||||
**General usage and development questions**
|
||||
- WooCommerce Slack Community: https://woocommerce.com/community-slack/
|
||||
- WordPress.org Forums: https://wordpress.org/support/plugin/woocommerce
|
||||
- The WooCommerce Help and Share Facebook group
|
||||
---
|
||||
name: "❓ Support Question"
|
||||
about: "If you have a question \U0001F4AC please see our docs or use our forums, helpdesk,
|
||||
or Slack Community!"
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
We don't offer technical support on GitHub so we recommend using the following:
|
||||
|
||||
**Reading our documentation**
|
||||
Usage docs can be found here: https://docs.woocommerce.com/
|
||||
|
||||
If you have a problem, you may want to start with the self help guide here: https://docs.woocommerce.com/document/woocommerce-self-service-guide/
|
||||
|
||||
**Technical support for premium extensions or if you're a WooCommerce.com customer**
|
||||
from a human being - submit a ticket via the helpdesk
|
||||
https://woocommerce.com/contact-us/
|
||||
|
||||
**General usage and development questions**
|
||||
- WooCommerce Slack Community: https://woocommerce.com/community-slack/
|
||||
- WordPress.org Forums: https://wordpress.org/support/plugin/woocommerce
|
||||
- The WooCommerce Help and Share Facebook group
|
||||
|
|
120
CHANGELOG.txt
|
@ -1,5 +1,125 @@
|
|||
== Changelog ==
|
||||
|
||||
= 3.5.5 - 2019-02-20 =
|
||||
* Fix - Fix allow product low stock threshold be the WC settings default. #22777
|
||||
* Fix - Fix error on product category when sorting by multiple fields. #22066
|
||||
* Fix - Recalculate coupon totals after adding a coupon to an order. #22580
|
||||
* Fix - Include refunded orders in top sellers, earners sales by product. #22581
|
||||
* Fix - Fix issue where "Any" attributes on variable products not always selectable on front end. #22067
|
||||
* Fix - Ensure partial refunds fire order.updated webhooks. #22072
|
||||
* Fix - Reload the cart page when the cart is empty. #22114
|
||||
* Fix - Always show the price filter widget when filtering products by price. #22303
|
||||
* Fix - Added body `{padding: 0;}` CSS rule to the email-styles.php to fix the iOS emails layout issue. #22309
|
||||
* Fix - Update variable product default attributes to reflect attribute terms slug edit. #22398
|
||||
* Fix - Adds all 3 callback arguments to the `woocommerce_order_item_display_meta_value` filter called from the `get_formatted_legacy` method of the WC_Order_Item_Meta class. #22411
|
||||
* Fix - Remove html from add coupon error alert during manual order entry. #22424
|
||||
* Fix - Include tax in subtotals when validating coupon minimum and maximum in manual order entry. #22464
|
||||
* Fix - Fix ssl check in case shop page no longer exists. #22531
|
||||
* Fix - Exclude `paged` from price slider and rating filter. #22533
|
||||
* Fix - Limit bulk variation percentage price adjustment to decimal places in pricing settings. #22537
|
||||
* Fix - Fix category image `name` field to be used for API POST/PUT. #22553
|
||||
* Fix - Fix remote request test in `get_environment_info()`. #22551
|
||||
* Fix - Fix notices when images have no metadata or their metadata is removed. #22562
|
||||
* Fix - Check for presence of 'save' entry in post data when determining whether to save settings. #22572
|
||||
* Fix - Additional CSS support for more input types on variations panel in admin. #22590
|
||||
* Fix - Over escaping rating widget html. #22593
|
||||
* Fix - Update cron sale price removal to remove the price at midnight after the sale ends. #22609
|
||||
* Fix - WC_Log_Handler_File::remove - fix for MS Windows #22624
|
||||
* Fix - Only require flat shipping rate when shipping method is enabled in the On-Boarding Wizard. #22599
|
||||
* Fix - Fix wrong variable check in `add_uncropped_metadata`. #22638
|
||||
* Fix - No alert for mis-matched password reset. #22642
|
||||
* Fix - Hold-stock behavior between simple products and variable products was different. #22646
|
||||
* Fix - OBW: Offer Storefront when WP 5.0 default theme is active #22649
|
||||
* Fix - Add novalidate attribute to payment form to prevent hidden fields preventing submission. #22662
|
||||
* Fix - Switch span to paragraph for descriptions in admin user profile view to correct spacing. #22663
|
||||
* Fix - Added POST variable check in product data meta box. #22681
|
||||
* Fix - PayPal item name encoding. #22684
|
||||
* Fix - Move PayPal BN partner ID. #22763
|
||||
* Fix - The "for" attribute of a label for a radio input is invalid in `woocommerce_form_field`. #22690
|
||||
* Fix - Custom payment options sections was not loading settings. #22704
|
||||
* Fix - Breadcrumbs on custom post types was using the singular name instead of plural. #22705
|
||||
* Fix - Fixed generate webhook signature when secret contains special chars. #22722
|
||||
* Fix - Set correct item meta after restocking items with refunds. #22729
|
||||
* Fix - Sales by Product to consistently calculate net sales counts and amounts. #22711
|
||||
* Fix - Importer - Variations cannot be drafts so set to private. #22736
|
||||
* Fix - Next/previous links for orders REST endpoint when `status` query parameter is present. #22741
|
||||
* Fix - Default value passed to sorting dropdown #22677
|
||||
* Tweak - Updates Mailchimp branding in setup wizard. #22514
|
||||
* Tweak - Refactor `@id` generation for product structured data to prevent plugin conflicts. #22554
|
||||
* Tweak - Keep count of the number of times custom coupons apply. #22529
|
||||
* Tweak - Change WooCommerce emails footer from `Powered by WooCommerce` to `Built with WooCommerce`. #22530
|
||||
* Security - Improved escaping for Photoswipe captions.
|
||||
* Security - Improved escaping for JSON attributes and structured data.
|
||||
|
||||
= 3.5.4 - 2019-01-21 =
|
||||
* Tweak - Allow limited html in woocommerce_rating_filter_count filter. #21904
|
||||
* Tweak - Remove 'on-hold' orders from admin tax reports for more logical reporting. #22419
|
||||
* Tweak - Remove payment phrases from processing emails. #22418
|
||||
* Tweak - Removed display of cost for local pickup when free. #22446
|
||||
* Fix - Unescape CSV formulas in product attributes in CSV importer/exporter. #21938
|
||||
* Fix - Remove use of non-existing `WC_REST_Dev_Setting_Options_Controller` class. #22121
|
||||
* Fix - Fix edge case where `get_plugins` would not have the custom WooCommerce plugin headers if `get_plugins` was called early. #21669
|
||||
* Fix - Prevent PHP warning when deprecated user meta starts with uppercase. #21943
|
||||
* Fix - Fixed support for multiple query parameters translated to meta queries via REST API requests. #22108
|
||||
* Fix - Prevent PHP errors when trying to access non-existant report tabs. #22183
|
||||
* Fix - Filter by attributes dropdown placeholder text should not be wrapped in quotes. #22185
|
||||
* Fix - Apply sale price until end of closing sale date. #22189
|
||||
* Fix - Allow empty schema again when registering a custom field for the API. #22204
|
||||
* Fix - Don't display escaped html on checkout when javascript is disabled. #22214
|
||||
* Fix - Fixed formatted address in uppercase for languages that use accents. #22096
|
||||
* Fix - Reload the cart page when the cart is empty when there is a hash in the URL. #22114
|
||||
* Fix - Do not schedule duplicate webhooks within 10 minutes of each other to maintain previous behavior. #22088
|
||||
* Fix - Return correct next scheduled date for items in queue by fixing date instantiation in WC_Action_Queue::get_next(). #22104
|
||||
* Fix - Allow products to use default low stock threshold. #22084
|
||||
* Fix - Fix 0 value attribute permalink calculation, property population in REST api. #22026
|
||||
* Fix - Ensure cache delete on coupon trash or delete. #22053
|
||||
* Fix - Ensure product parent exists before getting its image. #22074
|
||||
* Fix - Correctly use wildcard character on email restrictions on coupons. #22167
|
||||
* Fix - Avoids Warnings in Action Scheduler Library for PHP 5.2. #22160
|
||||
* Fix - Don't include product in BreadcrumbList structured data so Google will recognize stand-alone Product structured data. #22344
|
||||
* Fix - Fix Product widget showing hidden products when hide out of stock was enabled. #22230
|
||||
* Fix - Run webhook status updates through new wc_is_webhook_valid_status functions when doing API requests. #22205
|
||||
* Fix - Correct quote handling in tax class names. #22270
|
||||
* Fix - Prevent style side-effects on notices on the Extensions pages. #22330
|
||||
* Fix - Check stock status of items when 'ordering again' from the account page. #22331
|
||||
* Fix - Improve rounding when rounding at subtotal level in cart. #21217
|
||||
* Fix - Restores an opportunity to print non-cart related notices that a few extensions are relying on. #22337
|
||||
* Fix - Correct order item meta alignment in order emails when using an RTL language. #22376
|
||||
* Fix - Fix bug where product status was erroneously going to draft status in some circumstances on new published variable products. #20667
|
||||
* Fix - Load customer data for logged in users regardless of being member of sub-site to avoid errors. #22448
|
||||
* Fix - Use slug sanitization on product export category slugs for better foreign character support. #22320
|
||||
* Fix - Correct item subtotal rounding when multiple taxes are applied so it matches the cart. #22416
|
||||
* Fix - Prevent fatal errors when retrieving network orders for sites that do not have WooCommerce activated. #22439
|
||||
* Fix - Numerous bug fixes around checkout field locales on first load. #22444
|
||||
* Fix - Correct position of admin notices on my-account pages. #22445
|
||||
* Fix - Fixed padding of addresses in email template. #22466
|
||||
* Fix - Prevent payment method descriptions sliding up/down if selected after ajax updates. #22459
|
||||
* Fix - Fixed formatted address in uppercase for languages that use accents. #22096
|
||||
* Fix - Fix product updating on import for SKUs with special characters. #22071
|
||||
* Fix - Ensure cache_delete on coupon deletion. #22053
|
||||
* Fix - Make product edit form aware publish was pressed. #20667
|
||||
* Fix - Unescape imported CSV formulas in product attributes. #21938
|
||||
* Fix - Warning when deprecated user meta starts with uppercase. #21943
|
||||
* Fix - Filter out buttons from the onRowClick event on the Orders list view page. #21966
|
||||
* Fix - Update "Filter Products by Attribute" widget when product stock quantity changes via "Quick Edit" or WC API. #22029
|
||||
* Fix - Ensure product parent exists before getting its image. #22074
|
||||
* Fix - Fixed support for multiple query parameters translated to meta queries via REST API requests. #22108
|
||||
* Fix - Strip hash from URL when reload refunds in the dashboard. #22116
|
||||
* Fix - Prevent notice when using non existing value for tabs in WooCommerce > Reports > Stock. #22183
|
||||
* Fix - Filter by attributes dropdown placeholder text wrapped in quotes. #22185
|
||||
* Fix - Fix escaped html on checkout when javascript is disabled. #22214
|
||||
* Fix - Allow empty schema again when registering a custom field for the API. #22204
|
||||
* Fix - Fix import & export of newline characters in product description fields. #22298
|
||||
* Fix - Allow quotes in tax class names. #22270
|
||||
* Fix - Sale price applies to end of closing sale date. #22189
|
||||
* Fix - Product export by unicode product categories. #22320
|
||||
* Fix - Check stock status of items when 'ordering again' from the account page. #22331
|
||||
* Fix - Issue where images offloaded to external servers caused errors and broken images when changing aspect ratios. #22461
|
||||
* Fix - Remove block comments from shop page description. #22334
|
||||
* Dev - REST API - 0 value attribute permalink calculation, property population in REST api. #22026
|
||||
* Dev - REST API - Fixed support to order results by slugs. #22168
|
||||
* Dev - REST API - Removed extra inherited filters from product endpoint in variations endpoint. #22452
|
||||
|
||||
= 3.5.3 - 2018-12-20 =
|
||||
* Fix - Fix orders list in the admin after a change introduced in WordPress 5.0.2. #22273
|
||||
|
||||
|
|
|
@ -10,16 +10,11 @@ div.woocommerce-message {
|
|||
overflow: hidden;
|
||||
position: relative;
|
||||
border-left-color: #cc99c2 !important;
|
||||
p {
|
||||
max-width: 700px;
|
||||
}
|
||||
p:last-child {
|
||||
max-width: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
p.woocommerce-actions,
|
||||
.woocommerce-message {
|
||||
|
||||
.button-primary {
|
||||
background: #bb77ae;
|
||||
border-color: #a36597;
|
||||
|
@ -27,7 +22,9 @@ p.woocommerce-actions,
|
|||
color: #fff;
|
||||
text-shadow: 0 -1px 1px #a36597, 1px 0 1px #a36597, 0 1px 1px #a36597, -1px 0 1px #a36597;
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
background: #a36597;
|
||||
border-color: #a36597;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 0 #a36597;
|
||||
|
@ -39,11 +36,12 @@ p.woocommerce-actions,
|
|||
float: right;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 0px 15px 10px 28px;
|
||||
padding: 0 15px 10px 28px;
|
||||
margin-top: -10px;
|
||||
font-size: 13px;
|
||||
line-height: 1.23076923;
|
||||
text-decoration: none;
|
||||
|
||||
&::before {
|
||||
position: relative;
|
||||
top: 18px;
|
||||
|
@ -73,10 +71,10 @@ div.woocommerce-legacy-shipping-notice,
|
|||
div.woocommerce-no-shipping-methods-notice {
|
||||
overflow: hidden;
|
||||
padding: 1px 12px;
|
||||
|
||||
p {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 700px;
|
||||
line-height: 1.5em;
|
||||
margin: 12px 0;
|
||||
|
||||
|
@ -84,9 +82,10 @@ div.woocommerce-no-shipping-methods-notice {
|
|||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '\e01b';
|
||||
font-family: 'WooCommerce';
|
||||
content: "\e01b";
|
||||
font-family: "WooCommerce";
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
color: #f7f1f6;
|
||||
|
|
12556
assets/css/admin.scss
|
@ -2,23 +2,23 @@
|
|||
General table styling
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
$white: #ffffff;
|
||||
$white: #fff;
|
||||
|
||||
// Grays
|
||||
$gray: #87a6bc;
|
||||
$gray-light: lighten( $gray, 33% ); //#f3f6f8
|
||||
$gray-dark: darken( $gray, 38% ); //#2e4453
|
||||
$gray-light: lighten($gray, 33%); //#f3f6f8
|
||||
$gray-dark: darken($gray, 38%); //#2e4453
|
||||
|
||||
// $gray-text: ideal for standard, non placeholder text
|
||||
// $gray-text-min: minimum contrast needed for WCAG 2.0 AA on white background
|
||||
$gray-text: $gray-dark;
|
||||
$gray-text-min: darken( $gray, 18% ); //#537994
|
||||
$gray-text-min: darken($gray, 18%); //#537994
|
||||
|
||||
$woo_pink1: #955a89;
|
||||
$woo_pink2: #bb77ae;
|
||||
|
||||
|
||||
$color_text_blue: #0073AA;
|
||||
$color_text_blue: #0073aa;
|
||||
$color_button_primary: $woo_pink1;
|
||||
$color_button_secondary: $woo_pink2;
|
||||
|
||||
|
@ -26,11 +26,13 @@ $color_button_secondary: $woo_pink2;
|
|||
Tab navigation
|
||||
------------------------------------------------------------------------------*/
|
||||
.wc-helper {
|
||||
|
||||
.nav-tab-wrapper {
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 784px) {
|
||||
@media only screen and (max-width: 784px) {
|
||||
|
||||
.nav-tab {
|
||||
max-width: 40%;
|
||||
overflow: hidden;
|
||||
|
@ -45,7 +47,11 @@ $color_button_secondary: $woo_pink2;
|
|||
------------------------------------------------------------------------------*/
|
||||
|
||||
.wc-helper {
|
||||
.button, .button:hover, .button:focus, .button:active{
|
||||
|
||||
.button,
|
||||
.button:hover,
|
||||
.button:focus,
|
||||
.button:active {
|
||||
background-color: $color_button_primary;
|
||||
border-width: 0;
|
||||
box-shadow: none;
|
||||
|
@ -56,7 +62,7 @@ $color_button_secondary: $woo_pink2;
|
|||
text-align: center;
|
||||
white-space: normal !important;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
|
@ -73,7 +79,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
.wc-helper .subscription-filter {
|
||||
color: #2E4453;
|
||||
color: #2e4453;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
margin: 22px 0;
|
||||
|
@ -83,17 +89,18 @@ $color_button_secondary: $woo_pink2;
|
|||
position: relative;
|
||||
|
||||
.chevron {
|
||||
color: #E1E1E1;
|
||||
color: #e1e1e1;
|
||||
border-bottom-width: 0;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 14px;
|
||||
top: 10px;
|
||||
right: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
color: #0073AA;
|
||||
color: #0073aa;
|
||||
display: inline-block;
|
||||
padding: 0 4px 0 8px;
|
||||
position: relative;
|
||||
|
@ -102,37 +109,38 @@ $color_button_secondary: $woo_pink2;
|
|||
background-color: #979797;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a{
|
||||
color: #0073AA;
|
||||
a {
|
||||
color: #0073aa;
|
||||
text-decoration: none;
|
||||
|
||||
&.current{
|
||||
&.current {
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.count{
|
||||
.count {
|
||||
color: #555d66;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 600px) {
|
||||
@media only screen and (max-width: 600px) {
|
||||
background-color: #fff;
|
||||
border: 1px solid #E1E1E1;
|
||||
border: 1px solid #e1e1e1;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
|
||||
|
@ -148,7 +156,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
li {
|
||||
border-bottom: 1px solid #E1E1E1;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
}
|
||||
|
||||
label,
|
||||
|
@ -165,6 +173,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
li {
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
|
@ -175,7 +184,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
span.chevron {
|
||||
color: #555555;
|
||||
color: #555;
|
||||
opacity: 0.5;
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
|
@ -185,7 +194,7 @@ $color_button_secondary: $woo_pink2;
|
|||
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
|
||||
|
||||
label {
|
||||
border-bottom: 1px solid #E1E1E1;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
}
|
||||
|
||||
li {
|
||||
|
@ -205,6 +214,7 @@ $color_button_secondary: $woo_pink2;
|
|||
------------------------------------------------------------------------------*/
|
||||
|
||||
.wc-helper {
|
||||
|
||||
.subscriptions-header {
|
||||
margin: 3em 0 0;
|
||||
position: relative;
|
||||
|
@ -217,8 +227,10 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
}
|
||||
.button-update, .button-update:hover {
|
||||
background-color: #E6E6E6;
|
||||
|
||||
.button-update,
|
||||
.button-update:hover {
|
||||
background-color: #e6e6e6;
|
||||
border-radius: 4px;
|
||||
color: #333;
|
||||
font-weight: 800;
|
||||
|
@ -243,16 +255,16 @@ $color_button_secondary: $woo_pink2;
|
|||
|
||||
.user-info {
|
||||
background-color: #fff;
|
||||
border: 1px solid #E1E1E1;
|
||||
border: 1px solid #e1e1e1;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
line-height: 26px;
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
right: 0;
|
||||
transition: all .1s ease-in;
|
||||
top: -10px;
|
||||
right: 0;
|
||||
transition: all 0.1s ease-in;
|
||||
|
||||
@media only screen and (max-width : 600px) {
|
||||
@media only screen and (max-width: 600px) {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -263,11 +275,11 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 3px 5px rgba(0,0,0,.2);
|
||||
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
header {
|
||||
color: #555555;
|
||||
color: #555;
|
||||
font-weight: 600;
|
||||
padding: 6px 14px;
|
||||
position: relative;
|
||||
|
@ -279,8 +291,8 @@ $color_button_secondary: $woo_pink2;
|
|||
.dashicons {
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
right: 14px;
|
||||
top: 9px;
|
||||
right: 14px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
@ -292,18 +304,18 @@ $color_button_secondary: $woo_pink2;
|
|||
display: none;
|
||||
|
||||
p {
|
||||
border-top: 1px solid #E1E1E1;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
padding: 6px 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.actions {
|
||||
border-top: 1px solid #E1E1E1;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #A26897;
|
||||
color: #a26897;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
line-height: 38px;
|
||||
|
@ -319,17 +331,17 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
&:first-child {
|
||||
border-right: 1px solid #E1E1E1;
|
||||
border-right: 1px solid #e1e1e1;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #A26897;
|
||||
background-color: #a26897;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border: 1px solid #ECE1EA;
|
||||
border: 1px solid #ece1ea;
|
||||
border-radius: 50%;
|
||||
height: auto;
|
||||
margin-right: 6px;
|
||||
|
@ -342,11 +354,13 @@ $color_button_secondary: $woo_pink2;
|
|||
.user-info:hover,
|
||||
.user-info:focus,
|
||||
.user-info:active {
|
||||
|
||||
header .dashicons {
|
||||
transform: rotateX(180deg);
|
||||
}
|
||||
|
||||
section {
|
||||
display: block
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -356,10 +370,11 @@ $color_button_secondary: $woo_pink2;
|
|||
------------------------------------------------------------------------------*/
|
||||
|
||||
.wc-helper {
|
||||
|
||||
.striped > tbody > :nth-child(odd),
|
||||
ul.striped > :nth-child(odd),
|
||||
.alternate {
|
||||
background-color: #ffffff;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
table.widefat,
|
||||
|
@ -396,23 +411,24 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
.button {
|
||||
@media only screen and (max-width : 782px) {
|
||||
|
||||
@media only screen and (max-width: 782px) {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
.wp-list-table__row {
|
||||
background-color: rgba(0,0,0,0);
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
|
||||
td {
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border: 0px;
|
||||
border: 0;
|
||||
//border-top: 1px solid #e5e5e5;
|
||||
padding: 16px 22px;
|
||||
vertical-align: middle;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
|
@ -424,10 +440,10 @@ $color_button_secondary: $woo_pink2;
|
|||
&.is-ext-header {
|
||||
|
||||
td {
|
||||
border-top: 1px solid #E1E1E1;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
display: inline-flex;
|
||||
flex-flow: row wrap;
|
||||
width: 100%;
|
||||
|
@ -436,6 +452,7 @@ $color_button_secondary: $woo_pink2;
|
|||
display: block;
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.wp-list-table__ext-actions {
|
||||
display: block;
|
||||
flex: 1;
|
||||
|
@ -445,8 +462,8 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
&:last-child td {
|
||||
border-bottom: 24px solid #F1F1F1;
|
||||
box-shadow: inset 0 -1px 0 #E1E1E1;
|
||||
border-bottom: 24px solid #f1f1f1;
|
||||
box-shadow: inset 0 -1px 0 #e1e1e1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,82 +475,84 @@ $color_button_secondary: $woo_pink2;
|
|||
width: 100%;
|
||||
|
||||
&::before {
|
||||
background-color: #E1E1E1;
|
||||
background-color: #e1e1e1;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0 !important;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0 !important;
|
||||
width: 1px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.wp-list-table__ext-details {
|
||||
display: flex;
|
||||
display: flex;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
display: table;
|
||||
}
|
||||
@media only screen and (max-width: 782px) {
|
||||
display: table;
|
||||
}
|
||||
}
|
||||
|
||||
.wp-list-table__ext-title {
|
||||
color: $color_text_blue;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
width: 60%;
|
||||
width: 60%;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
margin-bottom: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 320px) {
|
||||
@media only screen and (max-width: 320px) {
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
.wp-list-table__ext-description {
|
||||
color: #333;
|
||||
padding-left: 12px;
|
||||
width: 40%;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
padding-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.wp-list-table__ext-status {
|
||||
position: relative;
|
||||
|
||||
&.update-available::after {
|
||||
background-color: #FFC322;
|
||||
background-color: #ffc322;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
&.expired::after {
|
||||
background-color: #B81C23;
|
||||
background-color: #b81c23;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.dashicons-update {
|
||||
color: #FFC322;
|
||||
color: #ffc322;
|
||||
}
|
||||
|
||||
.dashicons-info {
|
||||
color: #B81C23;
|
||||
color: #b81c23;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #333333;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
@ -549,34 +568,36 @@ $color_button_secondary: $woo_pink2;
|
|||
text-align: right;
|
||||
|
||||
&::after {
|
||||
background-color: #E1E1E1;
|
||||
background-color: #e1e1e1;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.wp-list-table__ext-updates,
|
||||
.wp-list-table__ext-licence {
|
||||
|
||||
td {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
background-color: #E1E1E1;
|
||||
background-color: #e1e1e1;
|
||||
content: " ";
|
||||
height: 1px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
td.wp-list-table__ext-status,
|
||||
td.wp-list-table__licence-container {
|
||||
|
||||
&::before {
|
||||
left: 22px !important;
|
||||
width: auto !important;
|
||||
|
@ -587,7 +608,7 @@ $color_button_secondary: $woo_pink2;
|
|||
right: 22px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
display: flex;
|
||||
|
||||
.wp-list-table__ext-status {
|
||||
|
@ -604,9 +625,9 @@ $color_button_secondary: $woo_pink2;
|
|||
min-width: 0;
|
||||
|
||||
&::before {
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
width: 100% !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -616,13 +637,13 @@ $color_button_secondary: $woo_pink2;
|
|||
padding: 0 !important;
|
||||
|
||||
&::after {
|
||||
background-color: #E1E1E1;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 1px;
|
||||
background-color: #e1e1e1;
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,20 +651,20 @@ $color_button_secondary: $woo_pink2;
|
|||
display: flex;
|
||||
padding: 16px 22px;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background-color: #E1E1E1;
|
||||
content: " ";
|
||||
background-color: #e1e1e1;
|
||||
content: " ";
|
||||
height: 1px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 22px;
|
||||
left: 22px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 22px;
|
||||
left: 22px;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
@ -653,7 +674,7 @@ $color_button_secondary: $woo_pink2;
|
|||
padding-right: 16px;
|
||||
vertical-align: middle;
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
@ -664,6 +685,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
.wp-list-table__licence-label {
|
||||
|
||||
label {
|
||||
color: #23282d;
|
||||
font-weight: 600;
|
||||
|
@ -672,15 +694,16 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
.wp-list-table__licence-field {
|
||||
|
||||
input {
|
||||
height: 32px;
|
||||
|
||||
@media only screen and (max-width : 480px) {
|
||||
@media only screen and (max-width: 480px) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 782px) {
|
||||
@media only screen and (max-width: 782px) {
|
||||
padding: 8px 0 16px !important;
|
||||
}
|
||||
}
|
||||
|
@ -692,12 +715,13 @@ $color_button_secondary: $woo_pink2;
|
|||
.button {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.button-secondary {
|
||||
float: right;
|
||||
margin: 0 0 0 8px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 480px) {
|
||||
@media only screen and (max-width: 480px) {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
@ -708,12 +732,13 @@ $color_button_secondary: $woo_pink2;
|
|||
------------------------------------------------------------------------------*/
|
||||
|
||||
.wc-helper {
|
||||
|
||||
td.color-bar {
|
||||
border-left: solid 4px transparent;
|
||||
}
|
||||
|
||||
td.color-bar.expired {
|
||||
border-left-color: #B81C23;
|
||||
border-left-color: #b81c23;
|
||||
}
|
||||
|
||||
td.color-bar.expiring {
|
||||
|
@ -721,11 +746,11 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
td.color-bar.update-available {
|
||||
border-left-color: #8FAE1B;
|
||||
border-left-color: #8fae1b;
|
||||
}
|
||||
|
||||
td.color-bar.expiring.update-available {
|
||||
border-left-color: #8FAE1B;
|
||||
border-left-color: #8fae1b;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -734,6 +759,7 @@ $color_button_secondary: $woo_pink2;
|
|||
------------------------------------------------------------------------------*/
|
||||
|
||||
.wc-helper {
|
||||
|
||||
.connect-wrapper {
|
||||
background-color: #fff;
|
||||
border: 1px solid #e5e5e5;
|
||||
|
@ -776,7 +802,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width : 784px) {
|
||||
@media only screen and (max-width: 784px) {
|
||||
display: block;
|
||||
|
||||
strong {
|
||||
|
@ -802,7 +828,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
.chevron {
|
||||
color: #E1E1E1;
|
||||
color: #e1e1e1;
|
||||
display: block;
|
||||
margin: 10px;
|
||||
transform: rotateX(0deg);
|
||||
|
@ -810,7 +836,7 @@ $color_button_secondary: $woo_pink2;
|
|||
|
||||
.buttons {
|
||||
display: none;
|
||||
border-top: 1px solid #E1E1E1;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
padding: 10px 20px;
|
||||
|
||||
&.active {
|
||||
|
@ -827,8 +853,9 @@ $color_button_secondary: $woo_pink2;
|
|||
------------------------------------------------------------------------------*/
|
||||
|
||||
.wc-helper {
|
||||
|
||||
.start-container {
|
||||
background-color: #ffffff;
|
||||
background-color: #fff;
|
||||
border-left: 4px solid #cc99c2;
|
||||
padding: 45px 20px 20px 30px;
|
||||
position: relative;
|
||||
|
@ -848,8 +875,8 @@ $color_button_secondary: $woo_pink2;
|
|||
font-size: 192px;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
top: 65%;
|
||||
right: -3%;
|
||||
top: 65%;
|
||||
right: -3%;
|
||||
text-align: center;
|
||||
width: 1em;
|
||||
}
|
||||
|
@ -898,10 +925,10 @@ $color_button_secondary: $woo_pink2;
|
|||
cursor: pointer;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: left;
|
||||
text-indent: -100000px;
|
||||
z-index: 2;
|
||||
|
@ -917,7 +944,7 @@ $color_button_secondary: $woo_pink2;
|
|||
|
||||
.form-toggle__switch {
|
||||
align-self: flex-start;
|
||||
background: lighten( $gray, 20% );
|
||||
background: lighten($gray, 20%);
|
||||
border-radius: 12px;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
|
@ -926,7 +953,7 @@ $color_button_secondary: $woo_pink2;
|
|||
position: relative;
|
||||
width: 40px;
|
||||
height: 24px;
|
||||
transition: all .4s ease, box-shadow 0s;
|
||||
transition: all 0.4s ease, box-shadow 0s;
|
||||
vertical-align: middle;
|
||||
|
||||
&::before,
|
||||
|
@ -942,7 +969,7 @@ $color_button_secondary: $woo_pink2;
|
|||
border-radius: 50%;
|
||||
background: $white;
|
||||
left: 0;
|
||||
transition: all .2s ease;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
&::before {
|
||||
|
@ -961,42 +988,47 @@ $color_button_secondary: $woo_pink2;
|
|||
z-index: 1;
|
||||
|
||||
.form-toggle__label-content {
|
||||
color: #87a6bc;
|
||||
color: #87a6bc;
|
||||
flex: 0 1 100%;
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
margin-left: 12px;
|
||||
margin-right: 8px;
|
||||
vertical-align: top;
|
||||
text-transform: uppercase;
|
||||
margin-right: 8px;
|
||||
vertical-align: top;
|
||||
text-transform: uppercase;
|
||||
|
||||
@media only screen and (max-width : 480px) {
|
||||
@media only screen and (max-width: 480px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-toggle {
|
||||
|
||||
.accessible-focus &:focus {
|
||||
|
||||
+ .form-toggle__label .form-toggle__switch {
|
||||
box-shadow: 0 0 0 2px $woo_pink1;
|
||||
}
|
||||
|
||||
&:checked + .form-toggle__label .form-toggle__switch {
|
||||
box-shadow: 0 0 0 2px $woo_pink2;
|
||||
}
|
||||
}
|
||||
|
||||
& + .form-toggle__label .form-toggle__switch {
|
||||
background: lighten( $gray, 10% );
|
||||
background: lighten($gray, 10%);
|
||||
}
|
||||
|
||||
&:not( :disabled ) {
|
||||
&:not(:disabled) {
|
||||
|
||||
+ .form-toggle__label:hover .form-toggle__switch {
|
||||
background: lighten( $gray, 20% );
|
||||
background: lighten($gray, 20%);
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
|
||||
+ .form-toggle__label .form-toggle__switch {
|
||||
background: $woo_pink1;
|
||||
|
||||
|
@ -1011,6 +1043,7 @@ $color_button_secondary: $woo_pink2;
|
|||
}
|
||||
|
||||
&.disabled {
|
||||
|
||||
+ label.form-toggle__label span.form-toggle__switch {
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
@ -1019,17 +1052,21 @@ $color_button_secondary: $woo_pink2;
|
|||
|
||||
// Classes for toggle state before action is complete (updating plugin or something)
|
||||
.form-toggle.is-toggling {
|
||||
|
||||
+ .form-toggle__label .form-toggle__switch {
|
||||
background: $woo_pink1;
|
||||
}
|
||||
|
||||
&:checked {
|
||||
|
||||
+ .form-toggle__label .form-toggle__switch {
|
||||
background: lighten( $gray, 20% );
|
||||
background: lighten($gray, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-toggle.is-compact {
|
||||
|
||||
+ .form-toggle__label .form-toggle__switch {
|
||||
border-radius: 8px;
|
||||
width: 24px;
|
||||
|
@ -1041,8 +1078,11 @@ $color_button_secondary: $woo_pink2;
|
|||
width: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
&:checked {
|
||||
|
||||
+ .form-toggle__label .form-toggle__switch {
|
||||
|
||||
&::after {
|
||||
left: 8px;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
*/
|
||||
/*
|
||||
|
||||
|
||||
1. Buttons
|
||||
|
||||
*/
|
||||
|
@ -31,13 +31,11 @@
|
|||
margin: 0;
|
||||
float: right;
|
||||
opacity: 0.75;
|
||||
z-index: 1600;
|
||||
-webkit-transition: opacity 0.2s;
|
||||
transition: opacity 0.2s;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none; }
|
||||
.pswp__button:focus,
|
||||
.pswp__button:hover {
|
||||
.pswp__button:focus, .pswp__button:hover {
|
||||
opacity: 1; }
|
||||
.pswp__button:active {
|
||||
outline: none;
|
||||
|
@ -258,7 +256,7 @@ a.pswp__share--download:hover {
|
|||
padding: 0 10px; }
|
||||
|
||||
/*
|
||||
|
||||
|
||||
4. Caption
|
||||
|
||||
*/
|
||||
|
@ -339,8 +337,8 @@ a.pswp__share--download:hover {
|
|||
margin: 0; }
|
||||
|
||||
.pswp--css_animation .pswp__preloader__cut {
|
||||
/*
|
||||
The idea of animating inner circle is based on Polymer ("material") loading indicator
|
||||
/*
|
||||
The idea of animating inner circle is based on Polymer ("material") loading indicator
|
||||
by Keanu Lee https://blog.keanulee.com/2014/10/20/the-tale-of-three-spinners.html
|
||||
*/
|
||||
position: relative;
|
||||
|
@ -410,12 +408,13 @@ a.pswp__share--download:hover {
|
|||
transform: rotate(0); } }
|
||||
|
||||
/*
|
||||
|
||||
|
||||
6. Additional styles
|
||||
|
||||
*/
|
||||
/* root element of UI */
|
||||
.pswp__ui {
|
||||
-webkit-font-smoothing: auto;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
z-index: 1550; }
|
||||
|
|
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 547 B |
|
@ -1 +1 @@
|
|||
<svg width="264" height="88" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M67.002 59.5v3.768c-6.307.84-9.184 5.75-10.002 9.732 2.22-2.83 5.564-5.098 10.002-5.098V71.5L73 65.585 67.002 59.5zM13 29v-5h2v3h3v2h-5zm0-14h5v2h-3v3h-2v-5zm18 0v5h-2v-3h-3v-2h5zm0 14h-5v-2h3v-3h2v5zm31-5v5h-2v-3h-3v-2h5zm0-4h-5v-2h3v-3h2v5zm8 0v-5h2v3h3v2h-5zm0 4h5v2h-3v3h-2v-5zM20.586 66l-5.656-5.656 1.414-1.414L22 64.586l5.656-5.656 1.414 1.414L23.414 66l5.656 5.656-1.414 1.414L22 67.414l-5.656 5.656-1.414-1.414L20.586 66zm91.199-.97L110 63.5l3-3.5h-10v-2h10l-3-3.5 1.785-1.468L117 59l-5.215 6.03zm40.43 0L154 63.5l-3-3.5h10v-2h-10l3-3.5-1.785-1.468L147 59l5.215 6.03zm8.742-36.487l-3.25-3.25-1.413 1.414 3.25 3.25z" fill="#fff"/><path d="M152.5 27a5.5 5.5 0 1 0 0-11 5.5 5.5 0 1 0 0 11z" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M150 21h5v1h-5zM116.957 28.543l-1.414 1.414-3.25-3.25 1.414-1.414 3.25 3.25z"/><path d="M108.5 27a5.5 5.5 0 1 0 0-11 5.5 5.5 0 1 0 0 11z" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M106 21h5v1h-5z"/><path fill="#fff" d="M109.043 19.008l-.085 5-1-.017.085-5z"/></g></svg>
|
||||
<svg width="264" height="88" viewBox="0 0 264 88" xmlns="http://www.w3.org/2000/svg"><title>default-skin 2</title><g fill="none" fill-rule="evenodd"><g><path d="M67.002 59.5v3.768c-6.307.84-9.184 5.75-10.002 9.732 2.22-2.83 5.564-5.098 10.002-5.098V71.5L73 65.585 67.002 59.5z" id="Shape" fill="#fff"/><g fill="#fff"><path d="M13 29v-5h2v3h3v2h-5zM13 15h5v2h-3v3h-2v-5zM31 15v5h-2v-3h-3v-2h5zM31 29h-5v-2h3v-3h2v5z" id="Shape"/></g><g fill="#fff"><path d="M62 24v5h-2v-3h-3v-2h5zM62 20h-5v-2h3v-3h2v5zM70 20v-5h2v3h3v2h-5zM70 24h5v2h-3v3h-2v-5z"/></g><path d="M20.586 66l-5.656-5.656 1.414-1.414L22 64.586l5.656-5.656 1.414 1.414L23.414 66l5.656 5.656-1.414 1.414L22 67.414l-5.656 5.656-1.414-1.414L20.586 66z" fill="#fff"/><path d="M111.785 65.03L110 63.5l3-3.5h-10v-2h10l-3-3.5 1.785-1.468L117 59l-5.215 6.03z" fill="#fff"/><path d="M152.215 65.03L154 63.5l-3-3.5h10v-2h-10l3-3.5-1.785-1.468L147 59l5.215 6.03z" fill="#fff"/><g><path id="Rectangle-11" fill="#fff" d="M160.957 28.543l-3.25-3.25-1.413 1.414 3.25 3.25z"/><path d="M152.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" id="Oval-1" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M150 21h5v1h-5z"/></g><g><path d="M116.957 28.543l-1.414 1.414-3.25-3.25 1.414-1.414 3.25 3.25z" fill="#fff"/><path d="M108.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M106 21h5v1h-5z"/><path fill="#fff" d="M109.043 19.008l-.085 5-1-.017.085-5z"/></g></g></g></svg>
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 866 B After Width: | Height: | Size: 866 B |
|
@ -1,35 +1,3 @@
|
|||
/**
|
||||
* WooCommerce Photoswipe styles.
|
||||
* 1. These styles are required to overwrite default theme button styles (Twenty Twelve adds gradients via background-image).
|
||||
* 2. For zooming on mobile.
|
||||
*/
|
||||
.woocommerce img.pswp__img,
|
||||
.woocommerce-page img.pswp__img {
|
||||
max-width: none; /* 2 */
|
||||
}
|
||||
button.pswp__button {
|
||||
box-shadow: none !important;
|
||||
background-image: url('default-skin/default-skin.png') !important;
|
||||
}
|
||||
button.pswp__button,
|
||||
button.pswp__button:hover,
|
||||
button.pswp__button--arrow--left::before,
|
||||
button.pswp__button--arrow--right::before {
|
||||
background-color: transparent !important; /* 1 */
|
||||
}
|
||||
button.pswp__button--arrow--left,
|
||||
button.pswp__button--arrow--right,
|
||||
button.pswp__button--arrow--left:hover,
|
||||
button.pswp__button--arrow--right:hover {
|
||||
background-image: none !important; /* 1 */
|
||||
}
|
||||
button.pswp__button--close:hover {
|
||||
background-position: 0 -44px;
|
||||
}
|
||||
button.pswp__button--zoom:hover {
|
||||
background-position: -88px 0;
|
||||
}
|
||||
|
||||
/*! PhotoSwipe main CSS by Dmitry Semenov | photoswipe.com | MIT license */
|
||||
/*
|
||||
Styles for basic PhotoSwipe functionality (sliding area, open/close transitions)
|
||||
|
@ -45,7 +13,7 @@ button.pswp__button--zoom:hover {
|
|||
overflow: hidden;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
z-index: 999999;
|
||||
z-index: 1500;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
/* create separate layer, to avoid paint on window.onscroll in webkit/blink */
|
||||
-webkit-backface-visibility: hidden;
|
||||
|
@ -98,6 +66,8 @@ button.pswp__button--zoom:hover {
|
|||
height: 100%;
|
||||
background: #000;
|
||||
opacity: 0;
|
||||
-webkit-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
-webkit-backface-visibility: hidden;
|
||||
will-change: opacity; }
|
||||
|
||||
|
|
|
@ -1,30 +1,32 @@
|
|||
/**
|
||||
* Twenty Seventeen integration styles
|
||||
*/
|
||||
@import 'mixins';
|
||||
@import 'animation';
|
||||
@import "mixins";
|
||||
@import "animation";
|
||||
|
||||
/**
|
||||
* Fonts
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'star';
|
||||
src: url('../fonts/star.eot');
|
||||
src: url('../fonts/star.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/star.woff') format('woff'),
|
||||
url('../fonts/star.ttf') format('truetype'),
|
||||
url('../fonts/star.svg#star') format('svg');
|
||||
font-family: "star";
|
||||
src: url("../fonts/star.eot");
|
||||
src:
|
||||
url("../fonts/star.eot?#iefix") format("embedded-opentype"),
|
||||
url("../fonts/star.woff") format("woff"),
|
||||
url("../fonts/star.ttf") format("truetype"),
|
||||
url("../fonts/star.svg#star") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'WooCommerce';
|
||||
src: url('../fonts/WooCommerce.eot');
|
||||
src: url('../fonts/WooCommerce.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/WooCommerce.woff') format('woff'),
|
||||
url('../fonts/WooCommerce.ttf') format('truetype'),
|
||||
url('../fonts/WooCommerce.svg#WooCommerce') format('svg');
|
||||
font-family: "WooCommerce";
|
||||
src: url("../fonts/WooCommerce.eot");
|
||||
src:
|
||||
url("../fonts/WooCommerce.eot?#iefix") format("embedded-opentype"),
|
||||
url("../fonts/WooCommerce.woff") format("woff"),
|
||||
url("../fonts/WooCommerce.ttf") format("truetype"),
|
||||
url("../fonts/WooCommerce.svg#WooCommerce") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
@ -55,17 +57,21 @@
|
|||
/**
|
||||
* Global elements
|
||||
*/
|
||||
.woocommerce {
|
||||
.woocommerce {
|
||||
|
||||
.blockUI.blockOverlay {
|
||||
position: relative;
|
||||
|
||||
@include loader();
|
||||
}
|
||||
|
||||
.loader {
|
||||
|
||||
@include loader();
|
||||
}
|
||||
|
||||
form .form-row {
|
||||
|
||||
.required {
|
||||
color: firebrick;
|
||||
text-decoration: none;
|
||||
|
@ -78,14 +84,16 @@
|
|||
|
||||
.optional {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-form-login {
|
||||
|
||||
.woocommerce-form-login__submit {
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.woocommerce-form-login__rememberme {
|
||||
display: inline-block;
|
||||
line-height: 3em;
|
||||
|
@ -101,6 +109,7 @@
|
|||
font-size: 0.8125rem;
|
||||
|
||||
a {
|
||||
|
||||
@include link();
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +137,7 @@
|
|||
float: none;
|
||||
line-height: 1.5;
|
||||
border-radius: 2px;
|
||||
transition: background-color ease-in-out .3s;
|
||||
transition: background-color ease-in-out 0.3s;
|
||||
}
|
||||
|
||||
span.page-numbers {
|
||||
|
@ -147,7 +156,7 @@
|
|||
top: 0;
|
||||
left: 0;
|
||||
display: inline-block;
|
||||
padding: .5em 1em;
|
||||
padding: 0.5em 1em;
|
||||
font-size: 13px;
|
||||
font-size: 0.8125rem;
|
||||
text-transform: uppercase;
|
||||
|
@ -155,10 +164,12 @@
|
|||
}
|
||||
|
||||
.price {
|
||||
|
||||
del {
|
||||
opacity: .5;
|
||||
opacity: 0.5;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
ins {
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -190,7 +201,9 @@
|
|||
.woocommerce-message,
|
||||
.woocommerce-error,
|
||||
.woocommerce-info {
|
||||
|
||||
a {
|
||||
|
||||
@include link_white();
|
||||
}
|
||||
}
|
||||
|
@ -224,37 +237,40 @@
|
|||
* Shop page
|
||||
*/
|
||||
.woocommerce-result-count {
|
||||
padding: .75em 0;
|
||||
padding: 0.75em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Products
|
||||
*/
|
||||
ul.products {
|
||||
|
||||
li.product {
|
||||
list-style: none;
|
||||
|
||||
.price,
|
||||
.star-rating {
|
||||
display: block;
|
||||
margin-bottom: .75em;
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
|
||||
.woocommerce-placeholder {
|
||||
border: 1px solid #F2F2F2;
|
||||
border: 1px solid #f2f2f2;
|
||||
}
|
||||
|
||||
.button {
|
||||
|
||||
@include link();
|
||||
|
||||
&.loading {
|
||||
opacity: .5;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.added_to_cart {
|
||||
|
||||
@include link();
|
||||
margin-left: .5em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -266,10 +282,10 @@ ul.products {
|
|||
line-height: 1;
|
||||
font-size: 1em;
|
||||
width: 5.4em;
|
||||
font-family: 'star';
|
||||
font-family: "star";
|
||||
|
||||
&::before {
|
||||
content: '\73\73\73\73\73';
|
||||
content: "\73\73\73\73\73";
|
||||
float: left;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
@ -286,7 +302,7 @@ ul.products {
|
|||
}
|
||||
|
||||
span::before {
|
||||
content: '\53\53\53\53\53';
|
||||
content: "\53\53\53\53\53";
|
||||
top: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
@ -318,13 +334,15 @@ a.remove {
|
|||
}
|
||||
}
|
||||
|
||||
dl.variation, .wc-item-meta {
|
||||
dl.variation,
|
||||
.wc-item-meta {
|
||||
list-style: none outside;
|
||||
|
||||
dt, .wc-item-meta-label {
|
||||
dt,
|
||||
.wc-item-meta-label {
|
||||
float: left;
|
||||
clear: both;
|
||||
margin-right: .25em;
|
||||
margin-right: 0.25em;
|
||||
display: inline-block;
|
||||
list-style: none outside;
|
||||
}
|
||||
|
@ -343,6 +361,7 @@ dl.variation, .wc-item-meta {
|
|||
* Single product
|
||||
*/
|
||||
.single-product {
|
||||
|
||||
div.product {
|
||||
position: relative;
|
||||
}
|
||||
|
@ -365,14 +384,15 @@ dl.variation, .wc-item-meta {
|
|||
|
||||
.star-rating {
|
||||
float: left;
|
||||
margin-right: .25em;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
form.cart {
|
||||
|
||||
.quantity {
|
||||
float: left;
|
||||
margin-right: .5em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
input {
|
||||
|
@ -381,10 +401,12 @@ dl.variation, .wc-item-meta {
|
|||
}
|
||||
|
||||
.woocommerce-variation-add-to-cart {
|
||||
|
||||
.button {
|
||||
padding-top: .72em;
|
||||
padding-bottom: .72em;
|
||||
padding-top: 0.72em;
|
||||
padding-bottom: 0.72em;
|
||||
}
|
||||
|
||||
.button.disabled {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
@ -392,12 +414,13 @@ dl.variation, .wc-item-meta {
|
|||
}
|
||||
|
||||
table.variations {
|
||||
|
||||
label {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
select {
|
||||
margin-right: .5em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,7 +444,7 @@ table.variations {
|
|||
}
|
||||
|
||||
.woocommerce-product-gallery__image--placeholder {
|
||||
border: 1px solid #F2F2F2;
|
||||
border: 1px solid #f2f2f2;
|
||||
}
|
||||
|
||||
.woocommerce-product-gallery__image:nth-child(n+2) {
|
||||
|
@ -430,6 +453,7 @@ table.variations {
|
|||
}
|
||||
|
||||
.flex-control-thumbs {
|
||||
|
||||
li {
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
|
@ -437,7 +461,7 @@ table.variations {
|
|||
}
|
||||
|
||||
img {
|
||||
opacity: .5;
|
||||
opacity: 0.5;
|
||||
|
||||
&:hover,
|
||||
&.flex-active {
|
||||
|
@ -453,27 +477,33 @@ table.variations {
|
|||
}
|
||||
|
||||
.woocommerce-product-gallery--columns-3 {
|
||||
|
||||
.flex-control-thumbs li {
|
||||
width: 33.3333%;
|
||||
}
|
||||
|
||||
.flex-control-thumbs li:nth-child(3n+1) {
|
||||
clear: left;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-product-gallery--columns-4 {
|
||||
|
||||
.flex-control-thumbs li {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.flex-control-thumbs li:nth-child(4n+1) {
|
||||
clear: left;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-product-gallery--columns-5 {
|
||||
|
||||
.flex-control-thumbs li {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.flex-control-thumbs li:nth-child(5n+1) {
|
||||
clear: left;
|
||||
}
|
||||
|
@ -493,6 +523,7 @@ table.variations {
|
|||
margin-right: 1em;
|
||||
|
||||
&.active {
|
||||
|
||||
a {
|
||||
box-shadow: 0 3px 0 rgba(15, 15, 15, 1);
|
||||
}
|
||||
|
@ -500,6 +531,7 @@ table.variations {
|
|||
}
|
||||
|
||||
a {
|
||||
|
||||
@include link();
|
||||
}
|
||||
|
||||
|
@ -517,6 +549,7 @@ table.variations {
|
|||
}
|
||||
|
||||
#reviews {
|
||||
|
||||
li.review,
|
||||
li.comment {
|
||||
list-style: none;
|
||||
|
@ -530,11 +563,12 @@ table.variations {
|
|||
}
|
||||
|
||||
p.meta {
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
p.stars {
|
||||
|
||||
a {
|
||||
position: relative;
|
||||
height: 1em;
|
||||
|
@ -552,40 +586,46 @@ table.variations {
|
|||
width: 1em;
|
||||
height: 1em;
|
||||
line-height: 1;
|
||||
font-family: 'WooCommerce';
|
||||
content: '\e021';
|
||||
font-family: "WooCommerce";
|
||||
content: "\e021";
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
~ a::before {
|
||||
content: '\e021';
|
||||
content: "\e021";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
||||
a {
|
||||
|
||||
&::before {
|
||||
content: '\e020';
|
||||
content: "\e020";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
|
||||
a.active {
|
||||
|
||||
&::before {
|
||||
content: '\e020';
|
||||
content: "\e020";
|
||||
}
|
||||
|
||||
~ a::before {
|
||||
content: '\e021';
|
||||
content: "\e021";
|
||||
}
|
||||
}
|
||||
|
||||
a:not( .active ) {
|
||||
a:not(.active) {
|
||||
|
||||
&::before {
|
||||
content: '\e020';
|
||||
content: "\e020";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -624,17 +664,21 @@ table.variations {
|
|||
}
|
||||
|
||||
.widget_shopping_cart {
|
||||
|
||||
.buttons {
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
margin: 0 .5em 0 0;
|
||||
margin: 0 0.5em 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.widget_layered_nav {
|
||||
|
||||
.chosen {
|
||||
&:before {
|
||||
|
||||
&::before {
|
||||
content: "×";
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
|
@ -644,12 +688,13 @@ table.variations {
|
|||
text-align: center;
|
||||
border-radius: 100%;
|
||||
border: 1px solid black;
|
||||
margin-right: .25em;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.widget_price_filter {
|
||||
|
||||
.price_slider {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
@ -661,7 +706,7 @@ table.variations {
|
|||
|
||||
.button {
|
||||
float: left;
|
||||
padding: .4em 1em;
|
||||
padding: 0.4em 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,17 +765,19 @@ table.variations {
|
|||
}
|
||||
|
||||
.widget_rating_filter {
|
||||
|
||||
li {
|
||||
text-align: right;
|
||||
|
||||
.star-rating {
|
||||
float: left;
|
||||
margin-top: .3em;
|
||||
margin-top: 0.3em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.widget_product_search {
|
||||
|
||||
form {
|
||||
position: relative;
|
||||
}
|
||||
|
@ -741,8 +788,8 @@ table.variations {
|
|||
|
||||
input[type=submit] {
|
||||
position: absolute;
|
||||
top: .5em;
|
||||
right: .5em;
|
||||
top: 0.5em;
|
||||
right: 0.5em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
@ -752,6 +799,7 @@ table.variations {
|
|||
* Account section
|
||||
*/
|
||||
.woocommerce-account {
|
||||
|
||||
.woocommerce-MyAccount-navigation {
|
||||
float: right;
|
||||
width: 25%;
|
||||
|
@ -759,7 +807,7 @@ table.variations {
|
|||
|
||||
li {
|
||||
list-style: none;
|
||||
padding: .5em 0;
|
||||
padding: 0.5em 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
|
||||
a {
|
||||
|
@ -770,14 +818,15 @@ table.variations {
|
|||
}
|
||||
}
|
||||
|
||||
&:before {
|
||||
&::before {
|
||||
content: "→";
|
||||
display: inline-block;
|
||||
margin-right: .25em;
|
||||
margin-right: 0.25em;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
|
||||
a {
|
||||
box-shadow: 0 3px 0 rgba(15, 15, 15, 1);
|
||||
}
|
||||
|
@ -794,8 +843,9 @@ table.variations {
|
|||
* Cart
|
||||
*/
|
||||
.woocommerce-cart-form {
|
||||
|
||||
td {
|
||||
padding: 1em .5em;
|
||||
padding: 1em 0.5em;
|
||||
}
|
||||
|
||||
img {
|
||||
|
@ -818,14 +868,16 @@ table.variations {
|
|||
}
|
||||
|
||||
.actions {
|
||||
|
||||
.input-text {
|
||||
width: 130px !important;
|
||||
float: left;
|
||||
margin-right: .25em;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
.quantity {
|
||||
|
||||
input {
|
||||
width: 4em;
|
||||
}
|
||||
|
@ -833,21 +885,25 @@ table.variations {
|
|||
}
|
||||
|
||||
.cart_totals {
|
||||
th, td {
|
||||
|
||||
th,
|
||||
td {
|
||||
vertical-align: top;
|
||||
padding: 1em 0;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
th {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.woocommerce-shipping-destination {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.shipping-calculator-button {
|
||||
margin-top: .5em;
|
||||
margin-top: 0.5em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
@ -860,7 +916,7 @@ table.variations {
|
|||
margin: 0;
|
||||
|
||||
li {
|
||||
margin-bottom: .5em;
|
||||
margin-bottom: 0.5em;
|
||||
|
||||
input {
|
||||
float: left;
|
||||
|
@ -886,7 +942,7 @@ table.variations {
|
|||
border-color: #999;
|
||||
}
|
||||
|
||||
&:after {
|
||||
&::after {
|
||||
content: "→";
|
||||
}
|
||||
}
|
||||
|
@ -895,6 +951,7 @@ table.variations {
|
|||
* Checkout
|
||||
*/
|
||||
#ship-to-different-address {
|
||||
|
||||
label {
|
||||
font-weight: 300;
|
||||
cursor: pointer;
|
||||
|
@ -903,7 +960,7 @@ table.variations {
|
|||
position: relative;
|
||||
display: block;
|
||||
|
||||
&:before {
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
height: 16px;
|
||||
|
@ -912,13 +969,13 @@ table.variations {
|
|||
background: #bbb;
|
||||
border-radius: 13em;
|
||||
box-sizing: content-box;
|
||||
transition: all ease-in-out .3s;
|
||||
transition: all ease-in-out 0.3s;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 14px;
|
||||
|
@ -928,7 +985,7 @@ table.variations {
|
|||
top: 7px;
|
||||
right: 17px;
|
||||
border-radius: 13em;
|
||||
transition: all ease-in-out .3s;
|
||||
transition: all ease-in-out 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -936,11 +993,11 @@ table.variations {
|
|||
display: none;
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked + span:after {
|
||||
input[type=checkbox]:checked + span::after {
|
||||
right: 3px;
|
||||
}
|
||||
|
||||
input[type=checkbox]:checked + span:before {
|
||||
input[type=checkbox]:checked + span::before {
|
||||
border-color: #000;
|
||||
background: #000;
|
||||
}
|
||||
|
@ -948,10 +1005,12 @@ table.variations {
|
|||
}
|
||||
|
||||
.woocommerce-no-js {
|
||||
|
||||
form.woocommerce-form-login,
|
||||
form.woocommerce-form-coupon {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.woocommerce-form-login-toggle,
|
||||
.woocommerce-form-coupon-toggle,
|
||||
.showcoupon {
|
||||
|
@ -960,37 +1019,40 @@ table.variations {
|
|||
}
|
||||
|
||||
.woocommerce-terms-and-conditions {
|
||||
border: 1px solid rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
|
||||
background: rgba(0,0,0,.05);
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.woocommerce-terms-and-conditions-link {
|
||||
display: inline-block;
|
||||
|
||||
&:after {
|
||||
&::after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
border-style: solid;
|
||||
margin-bottom: 2px;
|
||||
margin-left: .25em;
|
||||
margin-left: 0.25em;
|
||||
border-width: 6px 6px 0 6px;
|
||||
border-color: #111 transparent transparent transparent;
|
||||
}
|
||||
&.woocommerce-terms-and-conditions-link--open:after {
|
||||
|
||||
&.woocommerce-terms-and-conditions-link--open::after {
|
||||
border-width: 0 6px 6px 6px;
|
||||
border-color: transparent transparent #111 transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-checkout {
|
||||
|
||||
.woocommerce-input-wrapper {
|
||||
|
||||
.description {
|
||||
background: royalblue;
|
||||
color: #fff;
|
||||
border-radius: 3px;
|
||||
padding: 1em;
|
||||
margin: .5em 0 0;
|
||||
margin: 0.5em 0 0;
|
||||
clear: both;
|
||||
display: none;
|
||||
position: relative;
|
||||
|
@ -1002,11 +1064,11 @@ table.variations {
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:before {
|
||||
&::before {
|
||||
left: 50%;
|
||||
top: 0%;
|
||||
margin-top: -4px;
|
||||
transform: translatex(-50%) rotate(180deg);
|
||||
transform: translateX(-50%) rotate(180deg);
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-width: 4px 6px 0 6px;
|
||||
|
@ -1022,26 +1084,32 @@ table.variations {
|
|||
.select2-choice:hover {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.select2-choice {
|
||||
padding: .7em 0 .7em .7em;
|
||||
padding: 0.7em 0 0.7em 0.7em;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 46px;
|
||||
}
|
||||
|
||||
.select2-container--focus .select2-selection {
|
||||
border-color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-checkout-review-order-table {
|
||||
|
||||
td {
|
||||
padding: 1em .5em;
|
||||
padding: 1em 0.5em;
|
||||
}
|
||||
|
||||
dl.variation {
|
||||
|
@ -1063,6 +1131,7 @@ table.variations {
|
|||
|
||||
ul,
|
||||
ol {
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
@ -1102,7 +1171,8 @@ table.variations {
|
|||
display: none;
|
||||
|
||||
& + label {
|
||||
&:before {
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
|
@ -1111,14 +1181,15 @@ table.variations {
|
|||
box-shadow: 0 0 0 2px black;
|
||||
background: white;
|
||||
margin-left: 4px;
|
||||
margin-right: .5em;
|
||||
margin-right: 0.5em;
|
||||
border-radius: 100%;
|
||||
transform: translateY(2px);
|
||||
}
|
||||
}
|
||||
|
||||
&:checked + label {
|
||||
&:before {
|
||||
|
||||
&::before {
|
||||
background: black;
|
||||
}
|
||||
}
|
||||
|
@ -1126,10 +1197,12 @@ table.variations {
|
|||
}
|
||||
|
||||
.colors-dark {
|
||||
|
||||
.page-numbers {
|
||||
color: #444;
|
||||
|
||||
&.next, &.prev {
|
||||
&.next,
|
||||
&.prev {
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
@ -1143,17 +1216,21 @@ table.variations {
|
|||
}
|
||||
|
||||
.wc_payment_method {
|
||||
|
||||
.payment_box {
|
||||
background: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-container--default {
|
||||
|
||||
.select2-results {
|
||||
|
||||
.select2-results__options {
|
||||
background:#333;
|
||||
background: #333;
|
||||
}
|
||||
.select2-results__option[data-selected="true"]{
|
||||
|
||||
.select2-results__option[data-selected="true"] {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
@ -1177,7 +1254,9 @@ table.variations {
|
|||
* Layout stuff
|
||||
*/
|
||||
@media screen and (min-width: 48em) {
|
||||
|
||||
.has-sidebar.woocommerce-page:not(.error404) {
|
||||
|
||||
#primary {
|
||||
width: 74%;
|
||||
}
|
||||
|
|
|
@ -962,7 +962,7 @@ h3.jetpack-reasons {
|
|||
& > * {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
.plugin-install-info-list-item::after {
|
||||
content: ', ';
|
||||
}
|
||||
|
@ -1299,7 +1299,7 @@ p.jetpack-terms {
|
|||
}
|
||||
|
||||
&.recommended-item-icon-mailchimp {
|
||||
background-color: #209bbb;
|
||||
background-color: #ffe01b;
|
||||
height: 2em;
|
||||
padding: ( 3.5em - 2em ) / 2;
|
||||
}
|
||||
|
@ -1354,4 +1354,4 @@ p.jetpack-terms {
|
|||
border-bottom: 1px solid #eee;
|
||||
margin-top: 0;
|
||||
padding: 30px 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#4267b2;}.cls-2{fill:#fff;}</style></defs><title>flogo_RGB_HEX-512</title><path class="cls-1" d="M483.74,0H28.26A28.26,28.26,0,0,0,0,28.26V483.74A28.26,28.26,0,0,0,28.26,512H273.5V314H207V236.5h66.5v-57c0-66.13,40.39-102.14,99.38-102.14,28.25,0,52.54,2.1,59.62,3v69.11l-40.68,0c-32.1,0-38.32,15.25-38.32,37.64V236.5h76.74l-10,77.5H353.5V512H483.74A28.26,28.26,0,0,0,512,483.74V28.26A28.26,28.26,0,0,0,483.74,0Z"/><path id="f" class="cls-2" d="M353.5,512V314h66.75l10-77.5H353.5V187.14c0-22.39,6.22-37.64,38.32-37.64l40.68,0V80.37c-7.08-.94-31.37-3-59.62-3-59,0-99.38,36-99.38,102.14v57H207V314h66.5V512Z"/></svg>
|
After Width: | Height: | Size: 732 B |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 15 KiB |
|
@ -560,6 +560,13 @@ jQuery( function ( $ ) {
|
|||
if ( response.success ) {
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).empty();
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
|
||||
|
||||
// Update notes.
|
||||
if ( response.data.notes_html ) {
|
||||
$( 'ul.order_notes' ).empty();
|
||||
$( 'ul.order_notes' ).append( $( response.data.notes_html ).find( 'li' ) );
|
||||
}
|
||||
|
||||
wc_meta_boxes_order_items.reloaded_items();
|
||||
wc_meta_boxes_order_items.unblock();
|
||||
} else {
|
||||
|
@ -641,7 +648,7 @@ jQuery( function ( $ ) {
|
|||
items: $( 'table.woocommerce_order_items :input[name], .wc-order-totals-items :input[name]' ).serialize(),
|
||||
security: woocommerce_admin_meta_boxes.calc_totals_nonce
|
||||
} );
|
||||
|
||||
|
||||
$( document.body ).trigger( 'order-totals-recalculate-before', data );
|
||||
|
||||
$.ajax({
|
||||
|
@ -680,10 +687,22 @@ jQuery( function ( $ ) {
|
|||
data: data,
|
||||
type: 'POST',
|
||||
success: function( response ) {
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).empty();
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).append( response );
|
||||
wc_meta_boxes_order_items.reloaded_items();
|
||||
wc_meta_boxes_order_items.unblock();
|
||||
if ( response.success ) {
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).empty();
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
|
||||
|
||||
// Update notes.
|
||||
if ( response.data.notes_html ) {
|
||||
$( 'ul.order_notes' ).empty();
|
||||
$( 'ul.order_notes' ).append( $( response.data.notes_html ).find( 'li' ) );
|
||||
}
|
||||
|
||||
wc_meta_boxes_order_items.reloaded_items();
|
||||
wc_meta_boxes_order_items.unblock();
|
||||
} else {
|
||||
wc_meta_boxes_order_items.unblock();
|
||||
window.alert( response.data.error );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -978,6 +997,13 @@ jQuery( function ( $ ) {
|
|||
if ( response.success ) {
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).empty();
|
||||
$( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
|
||||
|
||||
// Update notes.
|
||||
if ( response.data.notes_html ) {
|
||||
$( 'ul.order_notes' ).empty();
|
||||
$( 'ul.order_notes' ).append( $( response.data.notes_html ).find( 'li' ) );
|
||||
}
|
||||
|
||||
wc_meta_boxes_order_items.reloaded_items();
|
||||
wc_meta_boxes_order_items.unblock();
|
||||
} else {
|
||||
|
|
|
@ -38,6 +38,9 @@ jQuery( function( $ ) {
|
|||
var $fragment_refresh = {
|
||||
url: wc_cart_fragments_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_refreshed_fragments' ),
|
||||
type: 'POST',
|
||||
data: {
|
||||
time: new Date().getTime()
|
||||
},
|
||||
timeout: wc_cart_fragments_params.request_timeout,
|
||||
success: function( data ) {
|
||||
if ( data && data.fragments ) {
|
||||
|
@ -96,7 +99,10 @@ jQuery( function( $ ) {
|
|||
|
||||
// Refresh when storage changes in another tab
|
||||
$( window ).on( 'storage onstorage', function ( e ) {
|
||||
if ( cart_hash_key === e.originalEvent.key && localStorage.getItem( cart_hash_key ) !== sessionStorage.getItem( cart_hash_key ) ) {
|
||||
if (
|
||||
cart_hash_key === e.originalEvent.key
|
||||
&& localStorage.getItem( cart_hash_key ) !== sessionStorage.getItem( cart_hash_key )
|
||||
) {
|
||||
refresh_cart_fragment();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -24,6 +24,8 @@ jQuery( function( $ ) {
|
|||
|
||||
if ( $( document.body ).hasClass( 'woocommerce-order-pay' ) ) {
|
||||
this.$order_review.on( 'click', 'input[name="payment_method"]', this.payment_method_selected );
|
||||
this.$order_review.on( 'submit', this.submitOrder );
|
||||
this.$order_review.attr( 'novalidate', 'novalidate' );
|
||||
}
|
||||
|
||||
// Prevent HTML5 validation which can conflict.
|
||||
|
@ -413,6 +415,22 @@ jQuery( function( $ ) {
|
|||
|
||||
});
|
||||
},
|
||||
blockOnSubmit: function( $form ) {
|
||||
var form_data = $form.data();
|
||||
|
||||
if ( 1 !== form_data['blockUI.isBlocked'] ) {
|
||||
$form.block({
|
||||
message: null,
|
||||
overlayCSS: {
|
||||
background: '#fff',
|
||||
opacity: 0.6
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
submitOrder: function() {
|
||||
wc_checkout_form.blockOnSubmit( $( this ) );
|
||||
},
|
||||
submit: function() {
|
||||
wc_checkout_form.reset_update_checkout_timer();
|
||||
var $form = $( this );
|
||||
|
@ -426,17 +444,7 @@ jQuery( function( $ ) {
|
|||
|
||||
$form.addClass( 'processing' );
|
||||
|
||||
var form_data = $form.data();
|
||||
|
||||
if ( 1 !== form_data['blockUI.isBlocked'] ) {
|
||||
$form.block({
|
||||
message: null,
|
||||
overlayCSS: {
|
||||
background: '#fff',
|
||||
opacity: 0.6
|
||||
}
|
||||
});
|
||||
}
|
||||
wc_checkout_form.blockOnSubmit( $form );
|
||||
|
||||
// ajaxSetup is global, but we use it to ensure JSON is valid once returned.
|
||||
$.ajaxSetup( {
|
||||
|
|
|
@ -122,6 +122,10 @@ jQuery( function( $ ) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( ! placeholder ) {
|
||||
placeholder = wc_country_select_params.i18n_select_state_text;
|
||||
}
|
||||
|
||||
$statebox.closest( 'p.form-row' ).show();
|
||||
|
||||
if ( $statebox.is( 'input' ) ) {
|
||||
|
|
|
@ -44,7 +44,19 @@ jQuery( function( $ ) {
|
|||
} )
|
||||
// Star ratings for comments
|
||||
.on( 'init', '#rating', function() {
|
||||
$( '#rating' ).hide().before( '<p class="stars"><span><a class="star-1" href="#">1</a><a class="star-2" href="#">2</a><a class="star-3" href="#">3</a><a class="star-4" href="#">4</a><a class="star-5" href="#">5</a></span></p>' );
|
||||
$( '#rating' )
|
||||
.hide()
|
||||
.before(
|
||||
'<p class="stars">\
|
||||
<span>\
|
||||
<a class="star-1" href="#">1</a>\
|
||||
<a class="star-2" href="#">2</a>\
|
||||
<a class="star-3" href="#">3</a>\
|
||||
<a class="star-4" href="#">4</a>\
|
||||
<a class="star-5" href="#">5</a>\
|
||||
</span>\
|
||||
</p>'
|
||||
);
|
||||
} )
|
||||
.on( 'click', '#respond p.stars a', function() {
|
||||
var $star = $( this ),
|
||||
|
@ -210,6 +222,12 @@ jQuery( function( $ ) {
|
|||
|
||||
zoomTarget.trigger( 'zoom.destroy' );
|
||||
zoomTarget.zoom( zoom_options );
|
||||
|
||||
setTimeout( function() {
|
||||
if ( zoomTarget.find(':hover').length ) {
|
||||
zoomTarget.trigger( 'mouseover' );
|
||||
}
|
||||
}, 100 );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -307,12 +325,12 @@ jQuery( function( $ ) {
|
|||
* Initialize all galleries on page.
|
||||
*/
|
||||
$( '.woocommerce-product-gallery' ).each( function() {
|
||||
|
||||
|
||||
$( this ).trigger( 'wc-product-gallery-before-init', [ this, wc_single_product_params ] );
|
||||
|
||||
|
||||
$( this ).wc_product_gallery( wc_single_product_params );
|
||||
|
||||
|
||||
$( this ).trigger( 'wc-product-gallery-after-init', [ this, wc_single_product_params ] );
|
||||
|
||||
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -14,19 +14,22 @@ jQuery( function( $ ) {
|
|||
}
|
||||
});
|
||||
|
||||
// Set a cookie and hide the store notice when the dismiss button is clicked
|
||||
$( '.woocommerce-store-notice__dismiss-link' ).click( function() {
|
||||
Cookies.set( 'store_notice', 'hidden', { path: '/' } );
|
||||
$( '.woocommerce-store-notice' ).hide();
|
||||
});
|
||||
var noticeID = $( '.woocommerce-store-notice' ).data( 'notice-id' ) || '',
|
||||
cookieName = 'store_notice' + noticeID;
|
||||
|
||||
// Check the value of that cookie and show/hide the notice accordingly
|
||||
if ( 'hidden' === Cookies.get( 'store_notice' ) ) {
|
||||
if ( 'hidden' === Cookies.get( cookieName ) ) {
|
||||
$( '.woocommerce-store-notice' ).hide();
|
||||
} else {
|
||||
$( '.woocommerce-store-notice' ).show();
|
||||
}
|
||||
|
||||
// Set a cookie and hide the store notice when the dismiss button is clicked
|
||||
$( '.woocommerce-store-notice__dismiss-link' ).click( function() {
|
||||
Cookies.set( cookieName, 'hidden', { path: '/' } );
|
||||
$( '.woocommerce-store-notice' ).hide();
|
||||
});
|
||||
|
||||
// Make form field descriptions toggle on focus.
|
||||
$( document.body ).on( 'click', function() {
|
||||
$( '.woocommerce-input-wrapper span.description:visible' ).prop( 'aria-hidden', true ).slideUp( 250 );
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*! PhotoSwipe Default UI - 4.1.1 - 2015-12-24
|
||||
/*! PhotoSwipe Default UI - 4.1.3 - 2019-01-08
|
||||
* http://photoswipe.com
|
||||
* Copyright (c) 2015 Dmitry Semenov; */
|
||||
* Copyright (c) 2019 Dmitry Semenov; */
|
||||
/**
|
||||
*
|
||||
* UI on top of main sliding area (caption, arrows, close button, etc.).
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*! PhotoSwipe - v4.1.1 - 2015-12-24
|
||||
/*! PhotoSwipe - v4.1.3 - 2019-01-08
|
||||
* http://photoswipe.com
|
||||
* Copyright (c) 2015 Dmitry Semenov; */
|
||||
* Copyright (c) 2019 Dmitry Semenov; */
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(factory);
|
||||
|
@ -157,7 +157,7 @@ var framework = {
|
|||
features.caf = window.cancelAnimationFrame;
|
||||
}
|
||||
|
||||
features.pointerEvent = navigator.pointerEnabled || navigator.msPointerEnabled;
|
||||
features.pointerEvent = !!(window.PointerEvent) || navigator.msPointerEnabled;
|
||||
|
||||
// fix false-positive detection of old Android in new IE
|
||||
// (IE11 ua string contains "Android 4.0")
|
||||
|
@ -397,6 +397,8 @@ var _isOpen,
|
|||
_features,
|
||||
_windowVisibleSize = {},
|
||||
_renderMaxResolution = false,
|
||||
_orientationChangeTimeout,
|
||||
|
||||
|
||||
// Registers PhotoSWipe module (History, Controller ...)
|
||||
_registerModule = function(name, module) {
|
||||
|
@ -544,13 +546,13 @@ var _isOpen,
|
|||
framework.bind(document, 'mousemove', _onFirstMouseMove);
|
||||
}
|
||||
|
||||
framework.bind(window, 'resize scroll', self);
|
||||
framework.bind(window, 'resize scroll orientationchange', self);
|
||||
|
||||
_shout('bindEvents');
|
||||
},
|
||||
|
||||
_unbindEvents = function() {
|
||||
framework.unbind(window, 'resize', self);
|
||||
framework.unbind(window, 'resize scroll orientationchange', self);
|
||||
framework.unbind(window, 'scroll', _globalEventHandlers.scroll);
|
||||
framework.unbind(document, 'keydown', self);
|
||||
framework.unbind(document, 'mousemove', _onFirstMouseMove);
|
||||
|
@ -563,6 +565,8 @@ var _isOpen,
|
|||
framework.unbind(window, _upMoveEvents, self);
|
||||
}
|
||||
|
||||
clearTimeout(_orientationChangeTimeout);
|
||||
|
||||
_shout('unbindEvents');
|
||||
},
|
||||
|
||||
|
@ -841,6 +845,18 @@ var publicMethods = {
|
|||
// Setup global events
|
||||
_globalEventHandlers = {
|
||||
resize: self.updateSize,
|
||||
|
||||
// Fixes: iOS 10.3 resize event
|
||||
// does not update scrollWrap.clientWidth instantly after resize
|
||||
// https://github.com/dimsemenov/PhotoSwipe/issues/1315
|
||||
orientationchange: function() {
|
||||
clearTimeout(_orientationChangeTimeout);
|
||||
_orientationChangeTimeout = setTimeout(function() {
|
||||
if(_viewportSize.x !== self.scrollWrap.clientWidth) {
|
||||
self.updateSize();
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
scroll: _updatePageScrollOffset,
|
||||
keydown: _onKeyDown,
|
||||
click: _onGlobalClick
|
||||
|
@ -1971,9 +1987,7 @@ var _gestureStartTime,
|
|||
if(pointerIndex > -1) {
|
||||
releasePoint = _currPointers.splice(pointerIndex, 1)[0];
|
||||
|
||||
if(navigator.pointerEnabled) {
|
||||
releasePoint.type = e.pointerType || 'mouse';
|
||||
} else {
|
||||
if(navigator.msPointerEnabled) {
|
||||
var MSPOINTER_TYPES = {
|
||||
4: 'mouse', // event.MSPOINTER_TYPE_MOUSE
|
||||
2: 'touch', // event.MSPOINTER_TYPE_TOUCH
|
||||
|
@ -1984,6 +1998,8 @@ var _gestureStartTime,
|
|||
if(!releasePoint.type) {
|
||||
releasePoint.type = e.pointerType || 'mouse';
|
||||
}
|
||||
} else {
|
||||
releasePoint.type = e.pointerType || 'mouse';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2436,11 +2452,11 @@ _registerModule('Gestures', {
|
|||
}
|
||||
|
||||
if(_pointerEventEnabled) {
|
||||
if(navigator.pointerEnabled) {
|
||||
addEventNames('pointer', 'down', 'move', 'up', 'cancel');
|
||||
} else {
|
||||
if(navigator.msPointerEnabled) {
|
||||
// IE10 pointer events are case-sensitive
|
||||
addEventNames('MSPointer', 'Down', 'Move', 'Up', 'Cancel');
|
||||
} else {
|
||||
addEventNames('pointer', 'down', 'move', 'up', 'cancel');
|
||||
}
|
||||
} else if(_features.touch) {
|
||||
addEventNames('touch', 'start', 'move', 'end', 'cancel');
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"prefer-stable": true,
|
||||
"minimum-stability": "dev",
|
||||
"require": {
|
||||
"composer/installers": "~1.6"
|
||||
"composer/installers": "1.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"apigen/apigen": "4.1.2",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "67b8066152baf2f08393562b576da266",
|
||||
"content-hash": "e7a81f490b054c067759791d696be7bd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/installers",
|
||||
|
@ -247,7 +247,7 @@
|
|||
"homepage": "https://github.com/kukulich"
|
||||
},
|
||||
{
|
||||
"name": "Tomas Votruba",
|
||||
"name": "Tomáš Votruba",
|
||||
"email": "tomas.vot@gmail.com"
|
||||
},
|
||||
{
|
||||
|
@ -2805,6 +2805,7 @@
|
|||
"mock",
|
||||
"xunit"
|
||||
],
|
||||
"abandoned": true,
|
||||
"time": "2018-08-09T05:50:03+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3731,7 +3732,7 @@
|
|||
},
|
||||
{
|
||||
"name": "Gert de Pagter",
|
||||
"email": "backendtea@gmail.com"
|
||||
"email": "BackEndTea@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for ctype functions",
|
||||
|
|
|
@ -140,7 +140,7 @@ return array(
|
|||
'LT' => __( 'Lithuania', 'woocommerce' ),
|
||||
'LU' => __( 'Luxembourg', 'woocommerce' ),
|
||||
'MO' => __( 'Macao S.A.R., China', 'woocommerce' ),
|
||||
'MK' => __( 'Macedonia', 'woocommerce' ),
|
||||
'MK' => __( 'North Macedonia', 'woocommerce' ),
|
||||
'MG' => __( 'Madagascar', 'woocommerce' ),
|
||||
'MW' => __( 'Malawi', 'woocommerce' ),
|
||||
'MY' => __( 'Malaysia', 'woocommerce' ),
|
||||
|
|
|
@ -1079,9 +1079,14 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
|
||||
// If the prices include tax, discounts should be taken off the tax inclusive prices like in the cart.
|
||||
if ( $this->get_prices_include_tax() && wc_tax_enabled() ) {
|
||||
$amount_tax = WC_Tax::get_tax_total( WC_Tax::calc_tax( $amount, WC_Tax::get_rates( $item->get_tax_class() ), true ) );
|
||||
$amount -= $amount_tax;
|
||||
$item->set_total( max( 0, $item->get_total() - $amount ) );
|
||||
$taxes = WC_Tax::calc_tax( $amount, WC_Tax::get_rates( $item->get_tax_class() ), true );
|
||||
|
||||
if ( 'yes' !== get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$taxes = array_map( 'wc_round_tax_total', $taxes );
|
||||
}
|
||||
|
||||
$amount = $amount - array_sum( $taxes );
|
||||
$item->set_total( max( 0, round( $item->get_total() - $amount, wc_get_price_decimals() ) ) );
|
||||
} else {
|
||||
$item->set_total( max( 0, $item->get_total() - $amount ) );
|
||||
}
|
||||
|
@ -1119,11 +1124,22 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
$item = $this->get_item( $item_id, false );
|
||||
|
||||
if ( $this->get_prices_include_tax() && wc_tax_enabled() ) {
|
||||
$amount_tax = array_sum( WC_Tax::calc_tax( $item_discount_amount, WC_Tax::get_rates( $item->get_tax_class() ), true ) );
|
||||
$discount_tax += $amount_tax;
|
||||
$amount = $amount - $amount_tax;
|
||||
$taxes = WC_Tax::calc_tax( $item_discount_amount, WC_Tax::get_rates( $item->get_tax_class() ), true );
|
||||
|
||||
if ( 'yes' !== get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$taxes = array_map( 'wc_round_tax_total', $taxes );
|
||||
}
|
||||
|
||||
$discount_tax += array_sum( $taxes );
|
||||
$amount = $amount - array_sum( $taxes );
|
||||
} else {
|
||||
$discount_tax += array_sum( WC_Tax::calc_tax( $item_discount_amount, WC_Tax::get_rates( $item->get_tax_class() ) ) );
|
||||
$taxes = WC_Tax::calc_tax( $item_discount_amount, WC_Tax::get_rates( $item->get_tax_class() ) );
|
||||
|
||||
if ( 'yes' !== get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$taxes = array_map( 'wc_round_tax_total', $taxes );
|
||||
}
|
||||
|
||||
$discount_tax += array_sum( $taxes );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1411,14 +1427,8 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
$this->add_item( $item );
|
||||
}
|
||||
|
||||
if ( 'yes' !== get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$this->set_shipping_tax( wc_round_tax_total( array_sum( array_map( 'wc_round_tax_total', $shipping_taxes ) ) ) );
|
||||
$this->set_cart_tax( wc_round_tax_total( array_sum( array_map( 'wc_round_tax_total', $cart_taxes ) ) ) );
|
||||
} else {
|
||||
$this->set_shipping_tax( wc_round_tax_total( array_sum( $shipping_taxes ) ) );
|
||||
$this->set_cart_tax( wc_round_tax_total( array_sum( $cart_taxes ) ) );
|
||||
}
|
||||
|
||||
$this->set_shipping_tax( wc_round_tax_total( array_sum( $shipping_taxes ) ) );
|
||||
$this->set_cart_tax( wc_round_tax_total( array_sum( $cart_taxes ) ) );
|
||||
$this->save();
|
||||
}
|
||||
|
||||
|
@ -1434,7 +1444,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
|
||||
$cart_subtotal = 0;
|
||||
$cart_total = 0;
|
||||
$fee_total = 0;
|
||||
$fees_total = 0;
|
||||
$shipping_total = 0;
|
||||
$cart_subtotal_tax = 0;
|
||||
$cart_total_tax = 0;
|
||||
|
@ -1454,18 +1464,17 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
|
||||
// Sum fee costs.
|
||||
foreach ( $this->get_fees() as $item ) {
|
||||
$amount = $item->get_amount();
|
||||
$fee_total = $item->get_total();
|
||||
|
||||
if ( 0 > $amount ) {
|
||||
$item->set_total( $amount );
|
||||
$max_discount = round( $cart_total + $fee_total + $shipping_total, wc_get_price_decimals() ) * -1;
|
||||
if ( 0 > $fee_total ) {
|
||||
$max_discount = round( $cart_total + $fees_total + $shipping_total, wc_get_price_decimals() ) * -1;
|
||||
|
||||
if ( $item->get_total() < $max_discount ) {
|
||||
if ( $fee_total < $max_discount ) {
|
||||
$item->set_total( $max_discount );
|
||||
}
|
||||
}
|
||||
|
||||
$fee_total += $item->get_total();
|
||||
$fees_total += $item->get_total();
|
||||
}
|
||||
|
||||
// Calculate taxes for items, shipping, discounts. Note; this also triggers save().
|
||||
|
@ -1473,15 +1482,22 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
|
|||
$this->calculate_taxes();
|
||||
}
|
||||
|
||||
// Sum taxes.
|
||||
// Sum taxes again so we can work out how much tax was discounted. This uses original values, not those possibly rounded to 2dp.
|
||||
foreach ( $this->get_items() as $item ) {
|
||||
$cart_subtotal_tax += $item->get_subtotal_tax();
|
||||
$cart_total_tax += $item->get_total_tax();
|
||||
$taxes = $item->get_taxes();
|
||||
|
||||
foreach ( $taxes['total'] as $tax_rate_id => $tax ) {
|
||||
$cart_total_tax += (float) $tax;
|
||||
}
|
||||
|
||||
foreach ( $taxes['subtotal'] as $tax_rate_id => $tax ) {
|
||||
$cart_subtotal_tax += (float) $tax;
|
||||
}
|
||||
}
|
||||
|
||||
$this->set_discount_total( $cart_subtotal - $cart_total );
|
||||
$this->set_discount_tax( $cart_subtotal_tax - $cart_total_tax );
|
||||
$this->set_total( round( $cart_total + $fee_total + $this->get_shipping_total() + $this->get_cart_tax() + $this->get_shipping_tax(), wc_get_price_decimals() ) );
|
||||
$this->set_discount_tax( wc_round_tax_total( $cart_subtotal_tax - $cart_total_tax ) );
|
||||
$this->set_total( round( $cart_total + $fees_total + $this->get_shipping_total() + $this->get_cart_tax() + $this->get_shipping_tax(), wc_get_price_decimals() ) );
|
||||
|
||||
do_action( 'woocommerce_order_after_calculate_totals', $and_taxes, $this );
|
||||
|
||||
|
|
|
@ -263,16 +263,23 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
|
|||
* @param array $args Arguments (default: array()).
|
||||
*/
|
||||
public function add_rate( $args = array() ) {
|
||||
$args = apply_filters( 'woocommerce_shipping_method_add_rate_args', wp_parse_args( $args, array(
|
||||
'id' => $this->get_rate_id(), // ID for the rate. If not passed, this id:instance default will be used.
|
||||
'label' => '', // Label for the rate.
|
||||
'cost' => '0', // Amount or array of costs (per item shipping).
|
||||
'taxes' => '', // Pass taxes, or leave empty to have it calculated for you, or 'false' to disable calculations.
|
||||
'calc_tax' => 'per_order', // Calc tax per_order or per_item. Per item needs an array of costs.
|
||||
'meta_data' => array(), // Array of misc meta data to store along with this rate - key value pairs.
|
||||
'package' => false, // Package array this rate was generated for @since 2.6.0.
|
||||
'price_decimals' => wc_get_price_decimals(),
|
||||
) ), $this );
|
||||
$args = apply_filters(
|
||||
'woocommerce_shipping_method_add_rate_args',
|
||||
wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'id' => $this->get_rate_id(), // ID for the rate. If not passed, this id:instance default will be used.
|
||||
'label' => '', // Label for the rate.
|
||||
'cost' => '0', // Amount or array of costs (per item shipping).
|
||||
'taxes' => '', // Pass taxes, or leave empty to have it calculated for you, or 'false' to disable calculations.
|
||||
'calc_tax' => 'per_order', // Calc tax per_order or per_item. Per item needs an array of costs.
|
||||
'meta_data' => array(), // Array of misc meta data to store along with this rate - key value pairs.
|
||||
'package' => false, // Package array this rate was generated for @since 2.6.0.
|
||||
'price_decimals' => wc_get_price_decimals(),
|
||||
)
|
||||
),
|
||||
$this
|
||||
);
|
||||
|
||||
// ID and label are required.
|
||||
if ( ! $args['id'] || ! $args['label'] ) {
|
||||
|
@ -323,7 +330,6 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
|
|||
* Calc taxes per item being shipping in costs array.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @access protected
|
||||
* @param array $costs Costs.
|
||||
* @return array of taxes
|
||||
*/
|
||||
|
@ -460,7 +466,8 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
|
|||
}
|
||||
|
||||
// Return global option.
|
||||
return parent::get_option( $key, $empty_value );
|
||||
$option = apply_filters( 'woocommerce_shipping_' . $this->id . '_option', parent::get_option( $key, $empty_value ), $key, $this );
|
||||
return $option;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -485,7 +492,8 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
|
|||
$this->instance_settings[ $key ] = $empty_value;
|
||||
}
|
||||
|
||||
return $this->instance_settings[ $key ];
|
||||
$instance_option = apply_filters( 'woocommerce_shipping_' . $this->id . '_instance_option', $this->instance_settings[ $key ], $key, $this );
|
||||
return $instance_option;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -256,7 +256,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
|||
'wc-admin-order-meta-boxes',
|
||||
'woocommerce_admin_meta_boxes_order',
|
||||
array(
|
||||
'countries' => json_encode( array_merge( WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states() ) ),
|
||||
'countries' => wp_json_encode( array_merge( WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states() ) ),
|
||||
'i18n_select_state_text' => esc_attr__( 'Select an option…', 'woocommerce' ),
|
||||
'default_country' => isset( $default_location['country'] ) ? $default_location['country'] : '',
|
||||
'default_state' => isset( $default_location['state'] ) ? $default_location['state'] : '',
|
||||
|
@ -411,7 +411,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
|||
'wc-users',
|
||||
'wc_users_params',
|
||||
array(
|
||||
'countries' => json_encode( array_merge( WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states() ) ),
|
||||
'countries' => wp_json_encode( array_merge( WC()->countries->get_allowed_country_states(), WC()->countries->get_shipping_country_states() ) ),
|
||||
'i18n_select_state_text' => esc_attr__( 'Select an option…', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
|
|
@ -351,7 +351,7 @@ class WC_Admin_Notices {
|
|||
* @todo Remove this notice and associated code once the feature plugin has been merged into core.
|
||||
*/
|
||||
public static function add_wootenberg_feature_plugin_notice() {
|
||||
if ( ( is_plugin_active( 'gutenberg/gutenberg.php' ) || version_compare( get_bloginfo( 'version' ), '5.0', '>=' ) ) && ! is_plugin_active( 'woo-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) ) {
|
||||
if ( ( self::is_plugin_active( 'gutenberg/gutenberg.php' ) || version_compare( get_bloginfo( 'version' ), '5.0', '>=' ) ) && ! self::is_plugin_active( 'woo-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) ) {
|
||||
self::add_notice( 'wootenberg' );
|
||||
}
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ class WC_Admin_Notices {
|
|||
* @todo Remove this notice and associated code once the feature plugin has been merged into core.
|
||||
*/
|
||||
public static function add_wootenberg_feature_plugin_notice_on_gutenberg_activate() {
|
||||
if ( ! is_plugin_active( 'woo-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) && version_compare( get_bloginfo( 'version' ), '5.0', '<' ) ) {
|
||||
if ( ! self::is_plugin_active( 'woo-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) && version_compare( get_bloginfo( 'version' ), '5.0', '<' ) ) {
|
||||
self::add_notice( 'wootenberg' );
|
||||
}
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ class WC_Admin_Notices {
|
|||
* Notice about trying the Products block.
|
||||
*/
|
||||
public static function wootenberg_feature_plugin_notice() {
|
||||
if ( get_user_meta( get_current_user_id(), 'dismissed_wootenberg_notice', true ) || is_plugin_active( 'woo-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) ) {
|
||||
if ( get_user_meta( get_current_user_id(), 'dismissed_wootenberg_notice', true ) || self::is_plugin_active( 'woo-gutenberg-products-block/woocommerce-gutenberg-products-block.php' ) ) {
|
||||
self::remove_notice( 'wootenberg' );
|
||||
return;
|
||||
}
|
||||
|
@ -392,6 +392,18 @@ class WC_Admin_Notices {
|
|||
return ( is_ssl() && 'https' === substr( $shop_page, 0, 5 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for is_plugin_active.
|
||||
*
|
||||
* @param string $plugin Plugin to check.
|
||||
* @return boolean
|
||||
*/
|
||||
protected static function is_plugin_active( $plugin ) {
|
||||
if ( ! function_exists( 'is_plugin_active' ) ) {
|
||||
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
return is_plugin_active( $plugin );
|
||||
}
|
||||
}
|
||||
|
||||
WC_Admin_Notices::init();
|
||||
|
|
|
@ -221,12 +221,12 @@ class WC_Admin_Pointers {
|
|||
* @param array $pointers
|
||||
*/
|
||||
public function enqueue_pointers( $pointers ) {
|
||||
$pointers = wp_json_encode( $pointers );
|
||||
$pointers = rawurlencode( wp_json_encode( $pointers ) );
|
||||
wp_enqueue_style( 'wp-pointer' );
|
||||
wp_enqueue_script( 'wp-pointer' );
|
||||
wc_enqueue_js(
|
||||
"jQuery( function( $ ) {
|
||||
var wc_pointers = {$pointers};
|
||||
var wc_pointers = JSON.parse( decodeURIComponent( '{$pointers}' ) );
|
||||
|
||||
setTimeout( init_wc_pointers, 800 );
|
||||
|
||||
|
|
|
@ -186,8 +186,7 @@ if ( ! class_exists( 'WC_Admin_Profile', false ) ) :
|
|||
<?php else : ?>
|
||||
<input type="text" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="<?php echo esc_attr( $this->get_user_meta( $user->ID, $key ) ); ?>" class="<?php echo ( ! empty( $field['class'] ) ? esc_attr( $field['class'] ) : 'regular-text' ); ?>" />
|
||||
<?php endif; ?>
|
||||
<br/>
|
||||
<span class="description"><?php echo wp_kses_post( $field['description'] ); ?></span>
|
||||
<p class="description"><?php echo wp_kses_post( $field['description'] ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -392,8 +392,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
|
|||
}
|
||||
|
||||
?>
|
||||
>
|
||||
<?php echo esc_html( $val ); ?></option>
|
||||
><?php echo esc_html( $val ); ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -133,6 +133,21 @@ class WC_Admin_Setup_Wizard {
|
|||
return current_user_can( 'install_plugins' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we show the Facebook install option?
|
||||
* True only if the user can install plugins,
|
||||
* and up until the end date of the recommendation.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function should_show_facebook() {
|
||||
$end_date_facebook_recommendation = new DateTime( '8 October 2019' );
|
||||
$current_user_date = new DateTime( current_time( 'Y-m-d' ) );
|
||||
|
||||
return current_user_can( 'install_plugins' ) &&
|
||||
$end_date_facebook_recommendation >= $current_user_date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we display the 'Recommended' step?
|
||||
* True if at least one of the recommendations will be displayed.
|
||||
|
@ -142,7 +157,8 @@ class WC_Admin_Setup_Wizard {
|
|||
protected function should_show_recommended_step() {
|
||||
return $this->should_show_theme()
|
||||
|| $this->should_show_automated_tax()
|
||||
|| $this->should_show_mailchimp();
|
||||
|| $this->should_show_mailchimp()
|
||||
|| $this->should_show_facebook();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -478,7 +494,7 @@ class WC_Admin_Setup_Wizard {
|
|||
<?php endforeach; ?>
|
||||
</select>
|
||||
<script type="text/javascript">
|
||||
var wc_setup_currencies = <?php echo wp_json_encode( $currency_by_country ); ?>;
|
||||
var wc_setup_currencies = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( $currency_by_country ) ); ?>' ) );
|
||||
var wc_base_state = "<?php echo esc_js( $state ); ?>";
|
||||
</script>
|
||||
</div>
|
||||
|
@ -576,12 +592,13 @@ class WC_Admin_Setup_Wizard {
|
|||
update_option( 'woocommerce_price_thousand_sep', $locale_info[ $country ]['thousand_sep'] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $tracking ) {
|
||||
update_option( 'woocommerce_allow_tracking', 'yes' );
|
||||
wp_schedule_single_event( time() + 10, 'woocommerce_tracker_send_event', array( true ) );
|
||||
} else {
|
||||
update_option( 'woocommerce_allow_tracking', 'no' );
|
||||
if ( 'unknown' === get_option( 'woocommerce_allow_tracking', 'unknown' ) ) {
|
||||
if ( $tracking ) {
|
||||
update_option( 'woocommerce_allow_tracking', 'yes' );
|
||||
wp_schedule_single_event( time() + 10, 'woocommerce_tracker_send_event', array( true ) );
|
||||
} else {
|
||||
update_option( 'woocommerce_allow_tracking', 'no' );
|
||||
}
|
||||
}
|
||||
|
||||
WC_Install::create_pages();
|
||||
|
@ -799,7 +816,7 @@ class WC_Admin_Setup_Wizard {
|
|||
id="<?php echo esc_attr( "{$input_prefix}[method]" ); ?>"
|
||||
name="<?php echo esc_attr( "{$input_prefix}[method]" ); ?>"
|
||||
class="method wc-enhanced-select"
|
||||
data-plugins="<?php echo esc_attr( wp_json_encode( $this->get_wcs_requisite_plugins() ) ); ?>"
|
||||
data-plugins="<?php echo wc_esc_json( wp_json_encode( $this->get_wcs_requisite_plugins() ) ); ?>"
|
||||
>
|
||||
<?php foreach ( $shipping_methods as $method_id => $method ) : ?>
|
||||
<option value="<?php echo esc_attr( $method_id ); ?>" <?php selected( $selected, $method_id ); ?>><?php echo esc_html( $method['name'] ); ?></option>
|
||||
|
@ -1653,7 +1670,7 @@ class WC_Admin_Setup_Wizard {
|
|||
placeholder="<?php echo esc_attr( $setting['placeholder'] ); ?>"
|
||||
<?php echo ( $setting['required'] ) ? 'required' : ''; ?>
|
||||
<?php echo $is_checkbox ? checked( isset( $checked ) && $checked, true, false ) : ''; ?>
|
||||
data-plugins="<?php echo esc_attr( wp_json_encode( isset( $setting['plugins'] ) ? $setting['plugins'] : null ) ); ?>"
|
||||
data-plugins="<?php echo wc_esc_json( wp_json_encode( isset( $setting['plugins'] ) ? $setting['plugins'] : null ) ); ?>"
|
||||
/>
|
||||
<?php if ( ! empty( $setting['description'] ) ) : ?>
|
||||
<span class="wc-wizard-service-settings-description"><?php echo esc_html( $setting['description'] ); ?></span>
|
||||
|
@ -1670,7 +1687,7 @@ class WC_Admin_Setup_Wizard {
|
|||
type="checkbox"
|
||||
name="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>-enabled"
|
||||
value="yes" <?php checked( $should_enable_toggle ); ?>
|
||||
data-plugins="<?php echo esc_attr( wp_json_encode( $plugins ) ); ?>"
|
||||
data-plugins="<?php echo wc_esc_json( wp_json_encode( $plugins ) ); ?>"
|
||||
/>
|
||||
<label for="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>">
|
||||
</span>
|
||||
|
@ -1839,7 +1856,7 @@ class WC_Admin_Setup_Wizard {
|
|||
name="<?php echo esc_attr( 'setup_' . $type ); ?>"
|
||||
value="yes"
|
||||
checked
|
||||
data-plugins="<?php echo esc_attr( wp_json_encode( isset( $item_info['plugins'] ) ? $item_info['plugins'] : null ) ); ?>"
|
||||
data-plugins="<?php echo wc_esc_json( wp_json_encode( isset( $item_info['plugins'] ) ? $item_info['plugins'] : null ) ); ?>"
|
||||
/>
|
||||
<label for="<?php echo esc_attr( 'wc_recommended_' . $type ); ?>">
|
||||
<img
|
||||
|
@ -1868,20 +1885,9 @@ class WC_Admin_Setup_Wizard {
|
|||
public function wc_setup_recommended() {
|
||||
?>
|
||||
<h1><?php esc_html_e( 'Recommended for All WooCommerce Stores', 'woocommerce' ); ?></h1>
|
||||
<p><?php
|
||||
// If we're displaying all of the recommended features, show the full description. Otherwise, display a placeholder.
|
||||
// We're not translating all of the different permutations to save on translations,
|
||||
// and the default is the most common.
|
||||
if (
|
||||
$this->should_show_theme()
|
||||
&& $this->should_show_automated_tax()
|
||||
&& $this->should_show_mailchimp()
|
||||
) :
|
||||
esc_html_e( 'Select from the list below to enable automated taxes and MailChimp’s best-in-class email services — and design your store with our official, free WooCommerce theme.', 'woocommerce' );
|
||||
else :
|
||||
esc_html_e( 'Enhance your store with these recommended features.', 'woocommerce' );
|
||||
endif;
|
||||
?></p>
|
||||
<p>
|
||||
<?php esc_html_e( 'Enhance your store with these recommended features.', 'woocommerce' ); ?>
|
||||
</p>
|
||||
<form method="post">
|
||||
<ul class="recommended-step">
|
||||
<?php
|
||||
|
@ -1921,6 +1927,17 @@ class WC_Admin_Setup_Wizard {
|
|||
'plugins' => array( array( 'name' => __( 'Mailchimp for WooCommerce', 'woocommerce' ), 'slug' => 'mailchimp-for-woocommerce' ) ),
|
||||
) );
|
||||
endif;
|
||||
|
||||
if ( $this->should_show_facebook() ) :
|
||||
$this->display_recommended_item( array(
|
||||
'type' => 'facebook',
|
||||
'title' => __( 'Facebook', 'woocommerce' ),
|
||||
'description' => __( 'Enjoy all Facebook products combined in one extension: pixel tracking, catalog sync, messenger chat, shop functionality and Instagram shopping (coming soon)!', 'woocommerce' ),
|
||||
'img_url' => WC()->plugin_url() . '/assets/images/obw-facebook-icon.svg',
|
||||
'img_alt' => __( 'Facebook icon', 'woocommerce' ),
|
||||
'plugins' => array( array( 'name' => __( 'Facebook for WooCommerce', 'woocommerce' ), 'slug' => 'facebook-for-woocommerce' ) ),
|
||||
) );
|
||||
endif;
|
||||
?>
|
||||
</ul>
|
||||
<p class="wc-setup-actions step">
|
||||
|
@ -1941,6 +1958,7 @@ class WC_Admin_Setup_Wizard {
|
|||
$setup_storefront = isset( $_POST['setup_storefront_theme'] ) && 'yes' === $_POST['setup_storefront_theme'];
|
||||
$setup_automated_tax = isset( $_POST['setup_automated_taxes'] ) && 'yes' === $_POST['setup_automated_taxes'];
|
||||
$setup_mailchimp = isset( $_POST['setup_mailchimp'] ) && 'yes' === $_POST['setup_mailchimp'];
|
||||
$setup_facebook = isset( $_POST['setup_facebook'] ) && 'yes' === $_POST['setup_facebook'];
|
||||
|
||||
update_option( 'woocommerce_calc_taxes', $setup_automated_tax ? 'yes' : 'no' );
|
||||
update_option( 'woocommerce_setup_automated_taxes', $setup_automated_tax );
|
||||
|
@ -1967,6 +1985,16 @@ class WC_Admin_Setup_Wizard {
|
|||
);
|
||||
}
|
||||
|
||||
if ( $setup_facebook ) {
|
||||
$this->install_plugin(
|
||||
'facebook-for-woocommerce',
|
||||
array(
|
||||
'name' => __( 'Facebook for WooCommerce', 'woocommerce' ),
|
||||
'repo-slug' => 'facebook-for-woocommerce',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
|
||||
exit;
|
||||
}
|
||||
|
|
|
@ -86,8 +86,10 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
|
|||
add_query_arg(
|
||||
array(
|
||||
'delete' => $webhook->get_id(),
|
||||
), admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=webhooks' )
|
||||
), 'delete-webhook'
|
||||
),
|
||||
admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=webhooks' )
|
||||
),
|
||||
'delete-webhook'
|
||||
)
|
||||
) . '">' . esc_html__( 'Delete permanently', 'woocommerce' ) . '</a>',
|
||||
);
|
||||
|
@ -262,7 +264,10 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
|
|||
echo '<label class="screen-reader-text" for="' . esc_attr( $input_id ) . '">' . esc_html( $text ) . ':</label>';
|
||||
echo '<input type="search" id="' . esc_attr( $input_id ) . '" name="s" value="' . esc_attr( $search_query ) . '" />';
|
||||
submit_button(
|
||||
$text, '', '', false,
|
||||
$text,
|
||||
'',
|
||||
'',
|
||||
false,
|
||||
array(
|
||||
'id' => 'search-submit',
|
||||
)
|
||||
|
@ -292,22 +297,19 @@ class WC_Admin_Webhooks_Table_List extends WP_List_Table {
|
|||
$args['search'] = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); // WPCS: input var okay, CSRF ok.
|
||||
}
|
||||
|
||||
$args['paginate'] = true;
|
||||
|
||||
// Get the webhooks.
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$webhooks = $data_store->search_webhooks( $args );
|
||||
$this->items = array_map( 'wc_get_webhook', $webhooks );
|
||||
|
||||
// Get total items.
|
||||
$args['limit'] = -1;
|
||||
$args['offset'] = 0;
|
||||
$total_items = count( $data_store->search_webhooks( $args ) );
|
||||
$this->items = array_map( 'wc_get_webhook', $webhooks->webhooks );
|
||||
|
||||
// Set the pagination.
|
||||
$this->set_pagination_args(
|
||||
array(
|
||||
'total_items' => $total_items,
|
||||
'total_items' => $webhooks->total,
|
||||
'per_page' => $per_page,
|
||||
'total_pages' => ceil( $total_items / $per_page ),
|
||||
'total_pages' => $webhooks->max_num_pages,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -270,8 +270,9 @@ class WC_Admin_Webhooks {
|
|||
echo '<h2>' . esc_html__( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=webhooks&edit-webhook=0' ) ) . '" class="add-new-h2">' . esc_html__( 'Add webhook', 'woocommerce' ) . '</a></h2>';
|
||||
|
||||
// Get the webhooks count.
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$count = count( $data_store->get_webhooks_ids() );
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$num_webhooks = $data_store->get_count_webhooks_by_status();
|
||||
$count = array_sum( $num_webhooks );
|
||||
|
||||
if ( 0 < $count ) {
|
||||
$webhooks_table_list->process_bulk_action();
|
||||
|
|
|
@ -161,7 +161,7 @@ class WC_Helper_Updater {
|
|||
*/
|
||||
private static function _update_check( $payload ) {
|
||||
ksort( $payload );
|
||||
$hash = md5( json_encode( $payload ) );
|
||||
$hash = md5( wp_json_encode( $payload ) );
|
||||
|
||||
$cache_key = '_woocommerce_helper_updates';
|
||||
if ( false !== ( $data = get_transient( $cache_key ) ) ) {
|
||||
|
@ -179,7 +179,7 @@ class WC_Helper_Updater {
|
|||
|
||||
$request = WC_Helper_API::post(
|
||||
'update-check', array(
|
||||
'body' => json_encode( array( 'products' => $payload ) ),
|
||||
'body' => wp_json_encode( array( 'products' => $payload ) ),
|
||||
'authenticated' => true,
|
||||
)
|
||||
);
|
||||
|
|
|
@ -836,7 +836,7 @@ class WC_Helper {
|
|||
$request = WC_Helper_API::post(
|
||||
'activate', array(
|
||||
'authenticated' => true,
|
||||
'body' => json_encode(
|
||||
'body' => wp_json_encode(
|
||||
array(
|
||||
'product_key' => $product_key,
|
||||
)
|
||||
|
@ -888,7 +888,7 @@ class WC_Helper {
|
|||
$request = WC_Helper_API::post(
|
||||
'deactivate', array(
|
||||
'authenticated' => true,
|
||||
'body' => json_encode(
|
||||
'body' => wp_json_encode(
|
||||
array(
|
||||
'product_key' => $product_key,
|
||||
)
|
||||
|
@ -1190,7 +1190,7 @@ class WC_Helper {
|
|||
$request = WC_Helper_API::post(
|
||||
'activate', array(
|
||||
'authenticated' => true,
|
||||
'body' => json_encode(
|
||||
'body' => wp_json_encode(
|
||||
array(
|
||||
'product_key' => $subscription['product_key'],
|
||||
)
|
||||
|
@ -1256,7 +1256,7 @@ class WC_Helper {
|
|||
$request = WC_Helper_API::post(
|
||||
'deactivate', array(
|
||||
'authenticated' => true,
|
||||
'body' => json_encode(
|
||||
'body' => wp_json_encode(
|
||||
array(
|
||||
'product_key' => $subscription['product_key'],
|
||||
)
|
||||
|
|
|
@ -2,14 +2,11 @@
|
|||
/**
|
||||
* Order Notes
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce/Admin/Meta Boxes
|
||||
* @version 2.1.0
|
||||
* @package WooCommerce/Admin/Meta Boxes
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,7 +17,7 @@ class WC_Meta_Box_Order_Notes {
|
|||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $post;
|
||||
|
@ -31,52 +28,20 @@ class WC_Meta_Box_Order_Notes {
|
|||
|
||||
$notes = wc_get_order_notes( $args );
|
||||
|
||||
echo '<ul class="order_notes">';
|
||||
|
||||
if ( $notes ) {
|
||||
|
||||
foreach ( $notes as $note ) {
|
||||
|
||||
$note_classes = array( 'note' );
|
||||
$note_classes[] = $note->customer_note ? 'customer-note' : '';
|
||||
$note_classes[] = 'system' === $note->added_by ? 'system-note' : '';
|
||||
$note_classes = apply_filters( 'woocommerce_order_note_class', array_filter( $note_classes ), $note );
|
||||
?>
|
||||
<li rel="<?php echo absint( $note->id ); ?>" class="<?php echo esc_attr( implode( ' ', $note_classes ) ); ?>">
|
||||
<div class="note_content">
|
||||
<?php echo wpautop( wptexturize( wp_kses_post( make_clickable( $note->content ) ) ) ); ?>
|
||||
</div>
|
||||
<p class="meta">
|
||||
<abbr class="exact-date" title="<?php echo $note->date_created->date( 'y-m-d h:i:s' ); ?>"><?php printf( __( 'added on %1$s at %2$s', 'woocommerce' ), $note->date_created->date_i18n( wc_date_format() ), $note->date_created->date_i18n( wc_time_format() ) ); ?></abbr>
|
||||
<?php
|
||||
if ( 'system' !== $note->added_by ) :
|
||||
/* translators: %s: note author */
|
||||
printf( ' ' . __( 'by %s', 'woocommerce' ), $note->added_by );
|
||||
endif;
|
||||
?>
|
||||
<a href="#" class="delete_note" role="button"><?php _e( 'Delete note', 'woocommerce' ); ?></a>
|
||||
</p>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
echo '<li>' . __( 'There are no notes yet.', 'woocommerce' ) . '</li>';
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
include 'views/html-order-notes.php';
|
||||
?>
|
||||
<div class="add_note">
|
||||
<p>
|
||||
<label for="add_order_note"><?php _e( 'Add note', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'Add a note for your reference, or add a customer note (the user will be notified).', 'woocommerce' ) ); ?></label>
|
||||
<label for="add_order_note"><?php esc_html_e( 'Add note', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'Add a note for your reference, or add a customer note (the user will be notified).', 'woocommerce' ) ); ?></label>
|
||||
<textarea type="text" name="order_note" id="add_order_note" class="input-text" cols="20" rows="5"></textarea>
|
||||
</p>
|
||||
<p>
|
||||
<label for="order_note_type" class="screen-reader-text"><?php _e( 'Note type', 'woocommerce' ); ?></label>
|
||||
<label for="order_note_type" class="screen-reader-text"><?php esc_html_e( 'Note type', 'woocommerce' ); ?></label>
|
||||
<select name="order_note_type" id="order_note_type">
|
||||
<option value=""><?php _e( 'Private note', 'woocommerce' ); ?></option>
|
||||
<option value="customer"><?php _e( 'Note to customer', 'woocommerce' ); ?></option>
|
||||
<option value=""><?php esc_html_e( 'Private note', 'woocommerce' ); ?></option>
|
||||
<option value="customer"><?php esc_html_e( 'Note to customer', 'woocommerce' ); ?></option>
|
||||
</select>
|
||||
<button type="button" class="add_note button"><?php _e( 'Add', 'woocommerce' ); ?></button>
|
||||
<button type="button" class="add_note button"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
*
|
||||
* Displays the product data box, tabbed, with several panels covering price, stock etc.
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce/Admin/Meta Boxes
|
||||
* @version 3.0.0
|
||||
*/
|
||||
|
@ -22,7 +20,7 @@ class WC_Meta_Box_Product_Data {
|
|||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $thepostid, $product_object;
|
||||
|
@ -56,7 +54,8 @@ class WC_Meta_Box_Product_Data {
|
|||
*/
|
||||
private static function get_product_type_options() {
|
||||
return apply_filters(
|
||||
'product_type_options', array(
|
||||
'product_type_options',
|
||||
array(
|
||||
'virtual' => array(
|
||||
'id' => '_virtual',
|
||||
'wrapper_class' => 'show_if_simple',
|
||||
|
@ -82,7 +81,8 @@ class WC_Meta_Box_Product_Data {
|
|||
*/
|
||||
private static function get_product_data_tabs() {
|
||||
$tabs = apply_filters(
|
||||
'woocommerce_product_data_tabs', array(
|
||||
'woocommerce_product_data_tabs',
|
||||
array(
|
||||
'general' => array(
|
||||
'label' => __( 'General', 'woocommerce' ),
|
||||
'target' => 'general_product_data',
|
||||
|
@ -148,7 +148,7 @@ class WC_Meta_Box_Product_Data {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ( $a['priority'] == $b['priority'] ) {
|
||||
if ( $a['priority'] === $b['priority'] ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ class WC_Meta_Box_Product_Data {
|
|||
/**
|
||||
* Filter callback for finding variation attributes.
|
||||
*
|
||||
* @param WC_Product_Attribute $attribute
|
||||
* @param WC_Product_Attribute $attribute Product attribute.
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_variation_attributes( $attribute ) {
|
||||
|
@ -183,9 +183,9 @@ class WC_Meta_Box_Product_Data {
|
|||
/**
|
||||
* Prepare downloads for save.
|
||||
*
|
||||
* @param array $file_names
|
||||
* @param array $file_urls
|
||||
* @param array $file_hashes
|
||||
* @param array $file_names File names.
|
||||
* @param array $file_urls File urls.
|
||||
* @param array $file_hashes File hashes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -193,7 +193,7 @@ class WC_Meta_Box_Product_Data {
|
|||
$downloads = array();
|
||||
|
||||
if ( ! empty( $file_urls ) ) {
|
||||
$file_url_size = sizeof( $file_urls );
|
||||
$file_url_size = count( $file_urls );
|
||||
|
||||
for ( $i = 0; $i < $file_url_size; $i ++ ) {
|
||||
if ( ! empty( $file_urls[ $i ] ) ) {
|
||||
|
@ -220,7 +220,7 @@ class WC_Meta_Box_Product_Data {
|
|||
/**
|
||||
* Prepare attributes for save.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data Attribute data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
@ -281,9 +281,9 @@ class WC_Meta_Box_Product_Data {
|
|||
/**
|
||||
* Prepare attributes for a specific variation or defaults.
|
||||
*
|
||||
* @param array $all_attributes
|
||||
* @param string $key_prefix
|
||||
* @param int $index
|
||||
* @param array $all_attributes List of attribute keys.
|
||||
* @param string $key_prefix Attribute key prefix.
|
||||
* @param int $index Attribute array index.
|
||||
* @return array
|
||||
*/
|
||||
private static function prepare_set_attributes( $all_attributes, $key_prefix = 'attribute_', $index = null ) {
|
||||
|
@ -318,12 +318,12 @@ class WC_Meta_Box_Product_Data {
|
|||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param $post
|
||||
* @param int $post_id WP post id.
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function save( $post_id, $post ) {
|
||||
// Process product type first so we have the correct class to run setters.
|
||||
$product_type = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( stripslashes( $_POST['product-type'] ) );
|
||||
$product_type = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( wp_unslash( $_POST['product-type'] ) );
|
||||
$classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' );
|
||||
$product = new $classname( $post_id );
|
||||
$attributes = self::prepare_attributes();
|
||||
|
@ -331,7 +331,7 @@ class WC_Meta_Box_Product_Data {
|
|||
|
||||
// Handle stock changes.
|
||||
if ( isset( $_POST['_stock'] ) ) {
|
||||
if ( isset( $_POST['_original_stock'] ) && wc_stock_amount( $product->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( $_POST['_original_stock'] ) ) {
|
||||
if ( isset( $_POST['_original_stock'] ) && wc_stock_amount( $product->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( wp_unslash( $_POST['_original_stock'] ) ) ) {
|
||||
/* translators: 1: product ID 2: quantity in stock */
|
||||
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The stock has not been updated because the value has changed since editing. Product %1$d has %2$d units in stock.', 'woocommerce' ), $product->get_id(), $product->get_stock_quantity( 'edit' ) ) );
|
||||
} else {
|
||||
|
@ -365,7 +365,7 @@ class WC_Meta_Box_Product_Data {
|
|||
'backorders' => isset( $_POST['_backorders'] ) ? wc_clean( wp_unslash( $_POST['_backorders'] ) ) : null,
|
||||
'stock_status' => wc_clean( wp_unslash( $_POST['_stock_status'] ) ),
|
||||
'stock_quantity' => $stock,
|
||||
'low_stock_amount' => wc_stock_amount( wp_unslash( $_POST['_low_stock_amount'] ) ),
|
||||
'low_stock_amount' => isset( $_POST['_low_stock_amount'] ) && '' !== $_POST['_low_stock_amount'] ? wc_stock_amount( wp_unslash( $_POST['_low_stock_amount'] ) ) : '',
|
||||
'download_limit' => '' === $_POST['_download_limit'] ? '' : absint( wp_unslash( $_POST['_download_limit'] ) ),
|
||||
'download_expiry' => '' === $_POST['_download_expiry'] ? '' : absint( wp_unslash( $_POST['_download_expiry'] ) ),
|
||||
'downloads' => self::prepare_downloads(
|
||||
|
@ -373,12 +373,12 @@ class WC_Meta_Box_Product_Data {
|
|||
isset( $_POST['_wc_file_urls'] ) ? wp_unslash( $_POST['_wc_file_urls'] ) : array(),
|
||||
isset( $_POST['_wc_file_hashes'] ) ? wp_unslash( $_POST['_wc_file_hashes'] ) : array()
|
||||
),
|
||||
'product_url' => esc_url_raw( wp_unslash( $_POST['_product_url'] ) ),
|
||||
'button_text' => wc_clean( wp_unslash( $_POST['_button_text'] ) ),
|
||||
'children' => 'grouped' === $product_type ? self::prepare_children() : null,
|
||||
'reviews_allowed' => ! empty( $_POST['comment_status'] ) && 'open' === $_POST['comment_status'],
|
||||
'attributes' => $attributes,
|
||||
'default_attributes' => self::prepare_set_attributes( $attributes, 'default_attribute_' ),
|
||||
'product_url' => esc_url_raw( wp_unslash( $_POST['_product_url'] ) ),
|
||||
'button_text' => wc_clean( wp_unslash( $_POST['_button_text'] ) ),
|
||||
'children' => 'grouped' === $product_type ? self::prepare_children() : null,
|
||||
'reviews_allowed' => ! empty( $_POST['comment_status'] ) && 'open' === $_POST['comment_status'],
|
||||
'attributes' => $attributes,
|
||||
'default_attributes' => self::prepare_set_attributes( $attributes, 'default_attribute_' ),
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -387,24 +387,26 @@ class WC_Meta_Box_Product_Data {
|
|||
}
|
||||
|
||||
/**
|
||||
* @since 3.0.0 to set props before save.
|
||||
* Set props before save.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
do_action( 'woocommerce_admin_process_product_object', $product );
|
||||
|
||||
$product->save();
|
||||
|
||||
if ( $product->is_type( 'variable' ) ) {
|
||||
$product->get_data_store()->sync_variation_names( $product, wc_clean( $_POST['original_post_title'] ), wc_clean( $_POST['post_title'] ) );
|
||||
$product->get_data_store()->sync_variation_names( $product, wc_clean( wp_unslash( $_POST['original_post_title'] ) ), wc_clean( wp_unslash( $_POST['post_title'] ) ) );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_process_product_meta_' . $product_type, $post_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
* Save variation meta box data.
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param WP_Post $post
|
||||
* @param int $post_id WP post id.
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function save_variations( $post_id, $post ) {
|
||||
if ( isset( $_POST['variable_post_id'] ) ) {
|
||||
|
@ -412,7 +414,7 @@ class WC_Meta_Box_Product_Data {
|
|||
$parent->set_default_attributes( self::prepare_set_attributes( $parent->get_attributes(), 'default_attribute_' ) );
|
||||
$parent->save();
|
||||
|
||||
$max_loop = max( array_keys( $_POST['variable_post_id'] ) );
|
||||
$max_loop = max( array_keys( wp_unslash( $_POST['variable_post_id'] ) ) );
|
||||
$data_store = $parent->get_data_store();
|
||||
$data_store->sort_all_product_variations( $parent->get_id() );
|
||||
|
||||
|
@ -427,45 +429,45 @@ class WC_Meta_Box_Product_Data {
|
|||
|
||||
// Handle stock changes.
|
||||
if ( isset( $_POST['variable_stock'], $_POST['variable_stock'][ $i ] ) ) {
|
||||
if ( isset( $_POST['variable_original_stock'], $_POST['variable_original_stock'][ $i ] ) && wc_stock_amount( $variation->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( $_POST['variable_original_stock'][ $i ] ) ) {
|
||||
if ( isset( $_POST['variable_original_stock'], $_POST['variable_original_stock'][ $i ] ) && wc_stock_amount( $variation->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( wp_unslash( $_POST['variable_original_stock'][ $i ] ) ) ) {
|
||||
/* translators: 1: product ID 2: quantity in stock */
|
||||
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The stock has not been updated because the value has changed since editing. Product %1$d has %2$d units in stock.', 'woocommerce' ), $variation->get_id(), $variation->get_stock_quantity( 'edit' ) ) );
|
||||
} else {
|
||||
$stock = wc_stock_amount( $_POST['variable_stock'][ $i ] );
|
||||
$stock = wc_stock_amount( wp_unslash( $_POST['variable_stock'][ $i ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
$errors = $variation->set_props(
|
||||
array(
|
||||
'status' => isset( $_POST['variable_enabled'][ $i ] ) ? 'publish' : 'private',
|
||||
'menu_order' => wc_clean( $_POST['variation_menu_order'][ $i ] ),
|
||||
'regular_price' => wc_clean( $_POST['variable_regular_price'][ $i ] ),
|
||||
'sale_price' => wc_clean( $_POST['variable_sale_price'][ $i ] ),
|
||||
'menu_order' => wc_clean( wp_unslash( $_POST['variation_menu_order'][ $i ] ) ),
|
||||
'regular_price' => wc_clean( wp_unslash( $_POST['variable_regular_price'][ $i ] ) ),
|
||||
'sale_price' => wc_clean( wp_unslash( $_POST['variable_sale_price'][ $i ] ) ),
|
||||
'virtual' => isset( $_POST['variable_is_virtual'][ $i ] ),
|
||||
'downloadable' => isset( $_POST['variable_is_downloadable'][ $i ] ),
|
||||
'date_on_sale_from' => wc_clean( $_POST['variable_sale_price_dates_from'][ $i ] ),
|
||||
'date_on_sale_to' => wc_clean( $_POST['variable_sale_price_dates_to'][ $i ] ),
|
||||
'description' => wp_kses_post( $_POST['variable_description'][ $i ] ),
|
||||
'download_limit' => wc_clean( $_POST['variable_download_limit'][ $i ] ),
|
||||
'download_expiry' => wc_clean( $_POST['variable_download_expiry'][ $i ] ),
|
||||
'date_on_sale_from' => wc_clean( wp_unslash( $_POST['variable_sale_price_dates_from'][ $i ] ) ),
|
||||
'date_on_sale_to' => wc_clean( wp_unslash( $_POST['variable_sale_price_dates_to'][ $i ] ) ),
|
||||
'description' => wp_kses_post( wp_unslash( $_POST['variable_description'][ $i ] ) ),
|
||||
'download_limit' => wc_clean( wp_unslash( $_POST['variable_download_limit'][ $i ] ) ),
|
||||
'download_expiry' => wc_clean( wp_unslash( $_POST['variable_download_expiry'][ $i ] ) ),
|
||||
'downloads' => self::prepare_downloads(
|
||||
isset( $_POST['_wc_variation_file_names'][ $variation_id ] ) ? $_POST['_wc_variation_file_names'][ $variation_id ] : array(),
|
||||
isset( $_POST['_wc_variation_file_urls'][ $variation_id ] ) ? $_POST['_wc_variation_file_urls'][ $variation_id ] : array(),
|
||||
isset( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) ? $_POST['_wc_variation_file_hashes'][ $variation_id ] : array()
|
||||
isset( $_POST['_wc_variation_file_names'][ $variation_id ] ) ? wp_unslash( $_POST['_wc_variation_file_names'][ $variation_id ] ) : array(),
|
||||
isset( $_POST['_wc_variation_file_urls'][ $variation_id ] ) ? wp_unslash( $_POST['_wc_variation_file_urls'][ $variation_id ] ) : array(),
|
||||
isset( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) ? wp_unslash( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) : array()
|
||||
),
|
||||
'manage_stock' => isset( $_POST['variable_manage_stock'][ $i ] ),
|
||||
'stock_quantity' => $stock,
|
||||
'backorders' => isset( $_POST['variable_backorders'], $_POST['variable_backorders'][ $i ] ) ? wc_clean( $_POST['variable_backorders'][ $i ] ) : null,
|
||||
'stock_status' => wc_clean( $_POST['variable_stock_status'][ $i ] ),
|
||||
'image_id' => wc_clean( $_POST['upload_image_id'][ $i ] ),
|
||||
'backorders' => isset( $_POST['variable_backorders'], $_POST['variable_backorders'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_backorders'][ $i ] ) ) : null,
|
||||
'stock_status' => wc_clean( wp_unslash( $_POST['variable_stock_status'][ $i ] ) ),
|
||||
'image_id' => wc_clean( wp_unslash( $_POST['upload_image_id'][ $i ] ) ),
|
||||
'attributes' => self::prepare_set_attributes( $parent->get_attributes(), 'attribute_', $i ),
|
||||
'sku' => isset( $_POST['variable_sku'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_sku'][ $i ] ) ) : '',
|
||||
'weight' => isset( $_POST['variable_weight'][ $i ] ) ? wc_clean( $_POST['variable_weight'][ $i ] ) : '',
|
||||
'length' => isset( $_POST['variable_length'][ $i ] ) ? wc_clean( $_POST['variable_length'][ $i ] ) : '',
|
||||
'width' => isset( $_POST['variable_width'][ $i ] ) ? wc_clean( $_POST['variable_width'][ $i ] ) : '',
|
||||
'height' => isset( $_POST['variable_height'][ $i ] ) ? wc_clean( $_POST['variable_height'][ $i ] ) : '',
|
||||
'shipping_class_id' => wc_clean( $_POST['variable_shipping_class'][ $i ] ),
|
||||
'tax_class' => isset( $_POST['variable_tax_class'][ $i ] ) ? wc_clean( $_POST['variable_tax_class'][ $i ] ) : null,
|
||||
'weight' => isset( $_POST['variable_weight'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_weight'][ $i ] ) ) : '',
|
||||
'length' => isset( $_POST['variable_length'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_length'][ $i ] ) ) : '',
|
||||
'width' => isset( $_POST['variable_width'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_width'][ $i ] ) ) : '',
|
||||
'height' => isset( $_POST['variable_height'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_height'][ $i ] ) ) : '',
|
||||
'shipping_class_id' => wc_clean( wp_unslash( $_POST['variable_shipping_class'][ $i ] ) ),
|
||||
'tax_class' => isset( $_POST['variable_tax_class'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_tax_class'][ $i ] ) ) : null,
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -105,19 +105,24 @@ if ( wc_tax_enabled() ) {
|
|||
<li><strong><?php esc_html_e( 'Coupon(s)', 'woocommerce' ); ?></strong></li>
|
||||
<?php
|
||||
foreach ( $coupons as $item_id => $item ) :
|
||||
$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' LIMIT 1;", $item->get_code() ) );
|
||||
$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' LIMIT 1;", $item->get_code() ) ); // phpcs:disable WordPress.WP.GlobalVariablesOverride.OverrideProhibited
|
||||
$class = $order->is_editable() ? 'code editable' : 'code';
|
||||
?>
|
||||
<li class="<?php echo esc_attr( $class ); ?>">
|
||||
<?php if ( $post_id ) : ?>
|
||||
<?php
|
||||
$post_url = apply_filters( 'woocommerce_admin_order_item_coupon_url', add_query_arg(
|
||||
array(
|
||||
'post' => $post_id,
|
||||
'action' => 'edit',
|
||||
$post_url = apply_filters(
|
||||
'woocommerce_admin_order_item_coupon_url',
|
||||
add_query_arg(
|
||||
array(
|
||||
'post' => $post_id,
|
||||
'action' => 'edit',
|
||||
),
|
||||
admin_url( 'post.php' )
|
||||
),
|
||||
admin_url( 'post.php' )
|
||||
), $item, $order );
|
||||
$item,
|
||||
$order
|
||||
);
|
||||
?>
|
||||
<a href="<?php echo esc_url( $post_url ); ?>" class="tips" data-tip="<?php echo esc_attr( wc_price( $item->get_discount(), array( 'currency' => $order->get_currency() ) ) ); ?>">
|
||||
<span><?php echo esc_html( $item->get_code() ); ?></span>
|
||||
|
@ -156,11 +161,11 @@ if ( wc_tax_enabled() ) {
|
|||
<?php
|
||||
$refunded = $order->get_total_shipping_refunded();
|
||||
if ( $refunded > 0 ) {
|
||||
echo '<del>' . strip_tags( wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ) ) . '</del> <ins>' . wc_price( $order->get_shipping_total() - $refunded, array( 'currency' => $order->get_currency() ) ) . '</ins>'; // WPCS: XSS ok.
|
||||
echo '<del>' . wp_strip_all_tags( wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ) ) . '</del> <ins>' . wc_price( $order->get_shipping_total() - $refunded, array( 'currency' => $order->get_currency() ) ) . '</ins>'; // WPCS: XSS ok.
|
||||
} else {
|
||||
echo wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ); // WPCS: XSS ok.
|
||||
}
|
||||
?>
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
|
@ -168,19 +173,19 @@ if ( wc_tax_enabled() ) {
|
|||
<?php do_action( 'woocommerce_admin_order_totals_after_shipping', $order->get_id() ); ?>
|
||||
|
||||
<?php if ( wc_tax_enabled() ) : ?>
|
||||
<?php foreach ( $order->get_tax_totals() as $code => $tax ) : ?>
|
||||
<?php foreach ( $order->get_tax_totals() as $code => $tax_total ) : ?>
|
||||
<tr>
|
||||
<td class="label"><?php echo esc_html( $tax->label ); ?>:</td>
|
||||
<td class="label"><?php echo esc_html( $tax_total->label ); ?>:</td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php
|
||||
$refunded = $order->get_total_tax_refunded_by_rate_id( $tax->rate_id );
|
||||
$refunded = $order->get_total_tax_refunded_by_rate_id( $tax_total->rate_id );
|
||||
if ( $refunded > 0 ) {
|
||||
echo '<del>' . strip_tags( $tax->formatted_amount ) . '</del> <ins>' . wc_price( WC_Tax::round( $tax->amount, wc_get_price_decimals() ) - WC_Tax::round( $refunded, wc_get_price_decimals() ), array( 'currency' => $order->get_currency() ) ) . '</ins>'; // WPCS: XSS ok.
|
||||
echo '<del>' . wp_strip_all_tags( $tax_total->formatted_amount ) . '</del> <ins>' . wc_price( WC_Tax::round( $tax_total->amount, wc_get_price_decimals() ) - WC_Tax::round( $refunded, wc_get_price_decimals() ), array( 'currency' => $order->get_currency() ) ) . '</ins>'; // WPCS: XSS ok.
|
||||
} else {
|
||||
echo wp_kses_post( $tax->formatted_amount );
|
||||
echo wp_kses_post( $tax_total->formatted_amount );
|
||||
}
|
||||
?>
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
@ -265,14 +270,32 @@ if ( wc_tax_enabled() ) {
|
|||
<td class="total"><?php echo wc_price( $order->get_total() - $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // WPCS: XSS ok. ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><label for="refund_amount"><?php esc_html_e( 'Refund amount', 'woocommerce' ); ?>:</label></td>
|
||||
<td class="label">
|
||||
<label for="refund_amount">
|
||||
<?php echo wc_help_tip( __( 'Refund the line items above. This will show the total amount to be refunded', 'woocommerce' ) ); ?>
|
||||
<?php esc_html_e( 'Refund amount', 'woocommerce' ); ?>:
|
||||
</label>
|
||||
</td>
|
||||
<td class="total">
|
||||
<input type="text" id="refund_amount" name="refund_amount" class="wc_input_price" />
|
||||
<input type="text" id="refund_amount" name="refund_amount" class="wc_input_price"
|
||||
<?php
|
||||
if ( wc_tax_enabled() ) {
|
||||
// If taxes are enabled, using this refund amount can cause issues due to taxes not being refunded also.
|
||||
// The refunds should be added to the line items, not the order as a whole.
|
||||
echo 'readonly';
|
||||
}
|
||||
?>
|
||||
/>
|
||||
<div class="clear"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><label for="refund_reason"><?php echo wc_help_tip( __( 'Note: the refund reason will be visible by the customer.', 'woocommerce' ) ); ?> <?php esc_html_e( 'Reason for refund (optional):', 'woocommerce' ); ?></label></td>
|
||||
<td class="label">
|
||||
<label for="refund_reason">
|
||||
<?php echo wc_help_tip( __( 'Note: the refund reason will be visible by the customer.', 'woocommerce' ) ); ?>
|
||||
<?php esc_html_e( 'Reason for refund (optional):', 'woocommerce' ); ?>
|
||||
</label>
|
||||
</td>
|
||||
<td class="total">
|
||||
<input type="text" id="refund_reason" name="refund_reason" />
|
||||
<div class="clear"></div>
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/**
|
||||
* Order notes HTML for meta box.
|
||||
*
|
||||
* @package WooCommerce/Admin
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
<ul class="order_notes">
|
||||
<?php
|
||||
if ( $notes ) {
|
||||
foreach ( $notes as $note ) {
|
||||
$css_class = array( 'note' );
|
||||
$css_class[] = $note->customer_note ? 'customer-note' : '';
|
||||
$css_class[] = 'system' === $note->added_by ? 'system-note' : '';
|
||||
$css_class = apply_filters( 'woocommerce_order_note_class', array_filter( $css_class ), $note );
|
||||
?>
|
||||
<li rel="<?php echo absint( $note->id ); ?>" class="<?php echo esc_attr( implode( ' ', $css_class ) ); ?>">
|
||||
<div class="note_content">
|
||||
<?php echo wpautop( wptexturize( wp_kses_post( $note->content ) ) ); // @codingStandardsIgnoreLine ?>
|
||||
</div>
|
||||
<p class="meta">
|
||||
<abbr class="exact-date" title="<?php echo esc_attr( $note->date_created->date( 'y-m-d h:i:s' ) ); ?>">
|
||||
<?php
|
||||
/* translators: %1$s: note date %2$s: note time */
|
||||
echo esc_html( sprintf( __( '%1$s at %2$s', 'woocommerce' ), $note->date_created->date_i18n( wc_date_format() ), $note->date_created->date_i18n( wc_time_format() ) ) );
|
||||
?>
|
||||
</abbr>
|
||||
<?php
|
||||
if ( 'system' !== $note->added_by ) :
|
||||
/* translators: %s: note author */
|
||||
echo esc_html( sprintf( ' ' . __( 'by %s', 'woocommerce' ), $note->added_by ) );
|
||||
endif;
|
||||
?>
|
||||
<a href="#" class="delete_note" role="button"><?php esc_html_e( 'Delete note', 'woocommerce' ); ?></a>
|
||||
</p>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
?>
|
||||
<li><?php esc_html_e( 'There are no notes yet.', 'woocommerce' ); ?></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</ul>
|
|
@ -28,8 +28,8 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
<label for="product_length"><?php printf( __( 'Dimensions (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?></label>
|
||||
<span class="wrap">
|
||||
<input id="product_length" placeholder="<?php esc_attr_e( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_length" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_length( 'edit' ) ) ); ?>" />
|
||||
<input placeholder="<?php esc_attr_e( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_width" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_width( 'edit' ) ) ); ?>" />
|
||||
<input placeholder="<?php esc_attr_e( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="_height" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_height( 'edit' ) ) ); ?>" />
|
||||
<input id="product_width" placeholder="<?php esc_attr_e( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_width" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_width( 'edit' ) ) ); ?>" />
|
||||
<input id="product_height" placeholder="<?php esc_attr_e( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="_height" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_height( 'edit' ) ) ); ?>" />
|
||||
</span>
|
||||
<?php echo wc_help_tip( __( 'LxWxH in decimal form', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
|
|
|
@ -115,13 +115,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// esc_attr does not double encode - htmlspecialchars does.
|
||||
$attributes_data = htmlspecialchars( wp_json_encode( wc_list_pluck( $variation_attributes, 'get_data' ) ) );
|
||||
?>
|
||||
|
||||
<div class="woocommerce_variations wc-metaboxes" data-attributes="<?php echo $attributes_data; // WPCS: XSS ok. ?>" data-total="<?php echo esc_attr( $variations_count ); ?>" data-total_pages="<?php echo esc_attr( $variations_total_pages ); ?>" data-page="1" data-edited="false">
|
||||
</div>
|
||||
<div class="woocommerce_variations wc-metaboxes" data-attributes="<?php echo wc_esc_json( wp_json_encode( wc_list_pluck( $variation_attributes, 'get_data' ) ) ); // WPCS: XSS ok. ?>" data-total="<?php echo esc_attr( $variations_count ); ?>" data-total_pages="<?php echo esc_attr( $variations_total_pages ); ?>" data-page="1" data-edited="false"></div>
|
||||
|
||||
<div class="toolbar">
|
||||
<button type="button" class="button-primary save-variation-changes" disabled="disabled"><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
|
||||
|
|
|
@ -338,7 +338,7 @@ class WC_Admin_Report {
|
|||
$wpdb->query( 'SET SESSION SQL_BIG_SELECTS=1' );
|
||||
$big_selects = true;
|
||||
}
|
||||
|
||||
|
||||
$cached_results[ $query_hash ] = apply_filters( 'woocommerce_reports_get_order_report_data', $wpdb->$query_type( $query ), $data );
|
||||
set_transient( strtolower( get_class( $this ) ), $cached_results, DAY_IN_SECONDS );
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ class WC_Admin_Report {
|
|||
|
||||
$sparkline_data = array_values( $this->prepare_chart_data( $data, 'post_date', 'sparkline_value', $days - 1, strtotime( 'midnight -' . ( $days - 1 ) . ' days', current_time( 'timestamp' ) ), 'day' ) );
|
||||
|
||||
return '<span class="wc_sparkline ' . ( ( 'sales' === $type ) ? 'lines' : 'bars' ) . ' tips" data-color="#777" data-tip="' . esc_attr( $tooltip ) . '" data-barwidth="' . 60 * 60 * 16 * 1000 . '" data-sparkline="' . esc_attr( json_encode( $sparkline_data ) ) . '"></span>';
|
||||
return '<span class="wc_sparkline ' . ( ( 'sales' === $type ) ? 'lines' : 'bars' ) . ' tips" data-color="#777" data-tip="' . esc_attr( $tooltip ) . '" data-barwidth="' . 60 * 60 * 16 * 1000 . '" data-sparkline="' . wc_esc_json( wp_json_encode( $sparkline_data ) ) . '"></span>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -455,7 +455,7 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report {
|
|||
$order_discount_amounts = $this->prepare_chart_data( $order_discount_amounts, 'post_date', 'discount_amount', $this->chart_interval, $this->start_date, $this->chart_groupby );
|
||||
|
||||
// Encode in json format.
|
||||
$chart_data = json_encode(
|
||||
$chart_data = wp_json_encode(
|
||||
array(
|
||||
'order_coupon_counts' => array_values( $order_coupon_counts ),
|
||||
'order_discount_amounts' => array_values( $order_discount_amounts ),
|
||||
|
@ -469,7 +469,7 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report {
|
|||
var main_chart;
|
||||
|
||||
jQuery(function(){
|
||||
var order_data = jQuery.parseJSON( '<?php echo $chart_data; ?>' );<?php // @codingStandardsIgnoreLine ?>
|
||||
var order_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );
|
||||
|
||||
var drawGraph = function( highlight ) {
|
||||
var series = [
|
||||
|
@ -525,7 +525,7 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report {
|
|||
tickColor: 'transparent',
|
||||
mode: "time",
|
||||
timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
|
||||
monthNames: <?php echo json_encode( array_values( $wp_locale->month_abbrev ) ); ?>,
|
||||
monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
|
||||
tickLength: 1,
|
||||
minTickSize: [1, "<?php echo esc_js( $this->chart_groupby ); ?>"],
|
||||
font: {
|
||||
|
|
|
@ -309,10 +309,12 @@ class WC_Report_Customers extends WC_Admin_Report {
|
|||
$customer_orders = $this->prepare_chart_data( $customer_orders, 'post_date', 'total_orders', $this->chart_interval, $this->start_date, $this->chart_groupby );
|
||||
$guest_orders = $this->prepare_chart_data( $guest_orders, 'post_date', 'total_orders', $this->chart_interval, $this->start_date, $this->chart_groupby );
|
||||
|
||||
$chart_data = array(
|
||||
'signups' => array_values( $signups ),
|
||||
'customer_orders' => array_values( $customer_orders ),
|
||||
'guest_orders' => array_values( $guest_orders ),
|
||||
$chart_data = wp_json_encode(
|
||||
array(
|
||||
'signups' => array_values( $signups ),
|
||||
'customer_orders' => array_values( $customer_orders ),
|
||||
'guest_orders' => array_values( $guest_orders ),
|
||||
)
|
||||
);
|
||||
?>
|
||||
<div class="chart-container">
|
||||
|
@ -322,7 +324,7 @@ class WC_Report_Customers extends WC_Admin_Report {
|
|||
var main_chart;
|
||||
|
||||
jQuery(function(){
|
||||
var chart_data = jQuery.parseJSON( '<?php echo wp_json_encode( $chart_data ); ?>' );
|
||||
var chart_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );
|
||||
|
||||
var drawGraph = function( highlight ) {
|
||||
var series = [
|
||||
|
@ -391,7 +393,7 @@ class WC_Report_Customers extends WC_Admin_Report {
|
|||
tickColor: 'transparent',
|
||||
mode: "time",
|
||||
timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
|
||||
monthNames: <?php echo wp_json_encode( array_values( $wp_locale->month_abbrev ) ); ?>,
|
||||
monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
|
||||
tickLength: 1,
|
||||
minTickSize: [1, "<?php echo esc_html( $this->chart_groupby ); ?>"],
|
||||
tickSize: [1, "<?php echo esc_html( $this->chart_groupby ); ?>"],
|
||||
|
|
|
@ -348,12 +348,16 @@ class WC_Report_Sales_By_Category extends WC_Admin_Report {
|
|||
$width = $this->barwidth / sizeof( $chart_data );
|
||||
$offset = ( $width * $index );
|
||||
$series = $data['data'];
|
||||
|
||||
foreach ( $series as $key => $series_data ) {
|
||||
$series[ $key ][0] = $series_data[0] + $offset;
|
||||
}
|
||||
|
||||
$series = wp_json_encode( $series );
|
||||
|
||||
echo '{
|
||||
label: "' . esc_js( $data['category'] ) . '",
|
||||
data: jQuery.parseJSON( "' . json_encode( $series ) . '" ),
|
||||
data: JSON.parse( decodeURIComponent( "' . rawurlencode( $series ) . '" ) ),
|
||||
color: "' . $color . '",
|
||||
bars: {
|
||||
fillColor: "' . $color . '",
|
||||
|
@ -407,7 +411,7 @@ class WC_Report_Sales_By_Category extends WC_Admin_Report {
|
|||
tickColor: 'transparent',
|
||||
mode: "time",
|
||||
timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
|
||||
monthNames: <?php echo json_encode( array_values( $wp_locale->month_abbrev ) ); ?>,
|
||||
monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
|
||||
tickLength: 1,
|
||||
minTickSize: [1, "<?php echo $this->chart_groupby; ?>"],
|
||||
tickSize: [1, "<?php echo $this->chart_groupby; ?>"],
|
||||
|
|
|
@ -693,7 +693,7 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
|
|||
var main_chart;
|
||||
|
||||
jQuery(function(){
|
||||
var order_data = jQuery.parseJSON( '<?php echo $chart_data; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?>' );
|
||||
var order_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );
|
||||
var drawGraph = function( highlight ) {
|
||||
var series = [
|
||||
{
|
||||
|
@ -817,7 +817,7 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
|
|||
tickColor: 'transparent',
|
||||
mode: "time",
|
||||
timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
|
||||
monthNames: <?php echo wp_json_encode( array_values( $wp_locale->month_abbrev ) ); ?>,
|
||||
monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
|
||||
tickLength: 1,
|
||||
minTickSize: [1, "<?php echo esc_js( $this->chart_groupby ); ?>"],
|
||||
font: {
|
||||
|
|
|
@ -85,6 +85,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
|
|||
),
|
||||
'query_type' => 'get_var',
|
||||
'filter_range' => true,
|
||||
'order_status' => array( 'completed', 'processing', 'on-hold', 'refunded' ),
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -110,6 +111,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
|
|||
),
|
||||
'query_type' => 'get_var',
|
||||
'filter_range' => true,
|
||||
'order_status' => array( 'completed', 'processing', 'on-hold', 'refunded' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -461,6 +463,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
|
|||
'order_by' => 'post_date ASC',
|
||||
'query_type' => 'get_results',
|
||||
'filter_range' => true,
|
||||
'order_status' => array( 'completed', 'processing', 'on-hold', 'refunded' ),
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -498,6 +501,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
|
|||
'order_by' => 'post_date ASC',
|
||||
'query_type' => 'get_results',
|
||||
'filter_range' => true,
|
||||
'order_status' => array( 'completed', 'processing', 'on-hold', 'refunded' ),
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -521,7 +525,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
|
|||
var main_chart;
|
||||
|
||||
jQuery(function(){
|
||||
var order_data = jQuery.parseJSON( '<?php echo $chart_data; ?>' );
|
||||
var order_data = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( $chart_data ); ?>' ) );
|
||||
|
||||
var drawGraph = function( highlight ) {
|
||||
|
||||
|
@ -578,7 +582,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
|
|||
tickColor: 'transparent',
|
||||
mode: "time",
|
||||
timeformat: "<?php echo ( 'day' === $this->chart_groupby ) ? '%d %b' : '%b'; ?>",
|
||||
monthNames: <?php echo json_encode( array_values( $wp_locale->month_abbrev ) ) ?>,
|
||||
monthNames: JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( array_values( $wp_locale->month_abbrev ) ) ); ?>' ) ),
|
||||
tickLength: 1,
|
||||
minTickSize: [1, "<?php echo $this->chart_groupby; ?>"],
|
||||
font: {
|
||||
|
|
|
@ -50,7 +50,8 @@ class WC_Settings_Payment_Gateways extends WC_Settings_Page {
|
|||
|
||||
if ( '' === $current_section ) {
|
||||
$settings = apply_filters(
|
||||
'woocommerce_payment_gateways_settings', array(
|
||||
'woocommerce_payment_gateways_settings',
|
||||
array(
|
||||
array(
|
||||
'title' => __( 'Payment methods', 'woocommerce' ),
|
||||
'desc' => __( 'Installed payment methods are listed below and can be sorted to control their display order on the frontend.', 'woocommerce' ),
|
||||
|
@ -94,10 +95,9 @@ class WC_Settings_Payment_Gateways extends WC_Settings_Page {
|
|||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$settings = $this->get_settings();
|
||||
WC_Admin_Settings::output_fields( $settings );
|
||||
}
|
||||
$settings = $this->get_settings( $current_section );
|
||||
WC_Admin_Settings::output_fields( $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,14 +2,12 @@
|
|||
/**
|
||||
* WooCommerce Admin Functions
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Core
|
||||
* @package WooCommerce/Admin/Functions
|
||||
* @version 2.4.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,7 +44,9 @@ function wc_get_screen_ids() {
|
|||
$screen_ids[] = 'edit-' . $type;
|
||||
}
|
||||
|
||||
if ( $attributes = wc_get_attribute_taxonomies() ) {
|
||||
$attributes = wc_get_attribute_taxonomies();
|
||||
|
||||
if ( $attributes ) {
|
||||
foreach ( $attributes as $attribute ) {
|
||||
$screen_ids[] = 'edit-' . wc_attribute_taxonomy_name( $attribute->attribute_name );
|
||||
}
|
||||
|
@ -58,21 +58,23 @@ function wc_get_screen_ids() {
|
|||
/**
|
||||
* Create a page and store the ID in an option.
|
||||
*
|
||||
* @param mixed $slug Slug for the new page
|
||||
* @param string $option Option name to store the page's ID
|
||||
* @param string $page_title (default: '') Title for the new page
|
||||
* @param string $page_content (default: '') Content for the new page
|
||||
* @param int $post_parent (default: 0) Parent for the new page
|
||||
* @return int page ID
|
||||
* @param mixed $slug Slug for the new page.
|
||||
* @param string $option Option name to store the page's ID.
|
||||
* @param string $page_title (default: '') Title for the new page.
|
||||
* @param string $page_content (default: '') Content for the new page.
|
||||
* @param int $post_parent (default: 0) Parent for the new page.
|
||||
* @return int page ID.
|
||||
*/
|
||||
function wc_create_page( $slug, $option = '', $page_title = '', $page_content = '', $post_parent = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$option_value = get_option( $option );
|
||||
|
||||
if ( $option_value > 0 && ( $page_object = get_post( $option_value ) ) ) {
|
||||
if ( 'page' === $page_object->post_type && ! in_array( $page_object->post_status, array( 'pending', 'trash', 'future', 'auto-draft' ) ) ) {
|
||||
// Valid page is already in place
|
||||
if ( $option_value > 0 ) {
|
||||
$page_object = get_post( $option_value );
|
||||
|
||||
if ( $page_object && 'page' === $page_object->post_type && ! in_array( $page_object->post_status, array( 'pending', 'trash', 'future', 'auto-draft' ), true ) ) {
|
||||
// Valid page is already in place.
|
||||
return $page_object->ID;
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +84,7 @@ function wc_create_page( $slug, $option = '', $page_title = '', $page_content =
|
|||
$shortcode = str_replace( array( '<!-- wp:shortcode -->', '<!-- /wp:shortcode -->' ), '', $page_content );
|
||||
$valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' ) AND post_content LIKE %s LIMIT 1;", "%{$shortcode}%" ) );
|
||||
} else {
|
||||
// Search for an existing page with the specified page slug
|
||||
// Search for an existing page with the specified page slug.
|
||||
$valid_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status NOT IN ( 'pending', 'trash', 'future', 'auto-draft' ) AND post_name = %s LIMIT 1;", $slug ) );
|
||||
}
|
||||
|
||||
|
@ -95,12 +97,12 @@ function wc_create_page( $slug, $option = '', $page_title = '', $page_content =
|
|||
return $valid_page_found;
|
||||
}
|
||||
|
||||
// Search for a matching valid trashed page
|
||||
// Search for a matching valid trashed page.
|
||||
if ( strlen( $page_content ) > 0 ) {
|
||||
// Search for an existing page with the specified page content (typically a shortcode)
|
||||
// Search for an existing page with the specified page content (typically a shortcode).
|
||||
$trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_content LIKE %s LIMIT 1;", "%{$page_content}%" ) );
|
||||
} else {
|
||||
// Search for an existing page with the specified page slug
|
||||
// Search for an existing page with the specified page slug.
|
||||
$trashed_page_found = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_type='page' AND post_status = 'trash' AND post_name = %s LIMIT 1;", $slug ) );
|
||||
}
|
||||
|
||||
|
@ -137,7 +139,7 @@ function wc_create_page( $slug, $option = '', $page_title = '', $page_content =
|
|||
*
|
||||
* Loops though the woocommerce options array and outputs each field.
|
||||
*
|
||||
* @param array $options Opens array to output
|
||||
* @param array $options Opens array to output.
|
||||
*/
|
||||
function woocommerce_admin_fields( $options ) {
|
||||
|
||||
|
@ -151,8 +153,8 @@ function woocommerce_admin_fields( $options ) {
|
|||
/**
|
||||
* Update all settings which are passed.
|
||||
*
|
||||
* @param array $options
|
||||
* @param array $data
|
||||
* @param array $options Option fields to save.
|
||||
* @param array $data Passed data.
|
||||
*/
|
||||
function woocommerce_update_options( $options, $data = null ) {
|
||||
|
||||
|
@ -166,8 +168,8 @@ function woocommerce_update_options( $options, $data = null ) {
|
|||
/**
|
||||
* Get a setting from the settings API.
|
||||
*
|
||||
* @param mixed $option_name
|
||||
* @param mixed $default
|
||||
* @param mixed $option_name Option name to save.
|
||||
* @param mixed $default Default value to save.
|
||||
* @return string
|
||||
*/
|
||||
function woocommerce_settings_get_option( $option_name, $default = '' ) {
|
||||
|
@ -179,17 +181,61 @@ function woocommerce_settings_get_option( $option_name, $default = '' ) {
|
|||
return WC_Admin_Settings::get_option( $option_name, $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sees if line item stock has already reduced stock, and whether those values need adjusting e.g. after changing item qty.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param WC_Order_Item $item Item object.
|
||||
* @param integer $item_quantity Optional quantity to check against. Read from object if not passed.
|
||||
* @return boolean|array|WP_Error Array of changes or error object when stock is updated (@see wc_update_product_stock). False if nothing changes.
|
||||
*/
|
||||
function wc_maybe_adjust_line_item_product_stock( $item, $item_quantity = -1 ) {
|
||||
if ( 'line_item' !== $item->get_type() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$product = $item->get_product();
|
||||
$item_quantity = wc_stock_amount( $item_quantity >= 0 ? $item_quantity : $item->get_quantity() );
|
||||
$already_reduced_stock = wc_stock_amount( $item->get_meta( '_reduced_stock', true ) );
|
||||
|
||||
if ( ! $product || ! $product->managing_stock() || ! $already_reduced_stock || $item_quantity === $already_reduced_stock ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$diff = $item_quantity - $already_reduced_stock;
|
||||
|
||||
if ( $diff < 0 ) {
|
||||
$new_stock = wc_update_product_stock( $product, $diff * -1, 'increase' );
|
||||
} else {
|
||||
$new_stock = wc_update_product_stock( $product, $diff, 'decrease' );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $new_stock ) ) {
|
||||
return $new_stock;
|
||||
}
|
||||
|
||||
$item->update_meta_data( '_reduced_stock', $item_quantity );
|
||||
$item->save();
|
||||
|
||||
return array(
|
||||
'from' => $new_stock + $diff,
|
||||
'to' => $new_stock,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save order items. Uses the CRUD.
|
||||
*
|
||||
* @since 2.2
|
||||
* @param int $order_id Order ID
|
||||
* @param array $items Order items to save
|
||||
* @param int $order_id Order ID.
|
||||
* @param array $items Order items to save.
|
||||
*/
|
||||
function wc_save_order_items( $order_id, $items ) {
|
||||
// Allow other plugins to check change in order items before they are saved.
|
||||
do_action( 'woocommerce_before_save_order_items', $order_id, $items );
|
||||
|
||||
$qty_change_order_notes = array();
|
||||
|
||||
// Line items and fees.
|
||||
if ( isset( $items['order_item_id'] ) ) {
|
||||
$data_keys = array(
|
||||
|
@ -202,7 +248,9 @@ function wc_save_order_items( $order_id, $items ) {
|
|||
'line_subtotal' => null,
|
||||
);
|
||||
foreach ( $items['order_item_id'] as $item_id ) {
|
||||
if ( ! $item = WC_Order_Factory::get_order_item( absint( $item_id ) ) ) {
|
||||
$item = WC_Order_Factory::get_order_item( absint( $item_id ) );
|
||||
|
||||
if ( ! $item ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -213,6 +261,10 @@ function wc_save_order_items( $order_id, $items ) {
|
|||
}
|
||||
|
||||
if ( '0' === $item_data['order_item_qty'] ) {
|
||||
$changed_stock = wc_maybe_adjust_line_item_product_stock( $item, 0 );
|
||||
if ( $changed_stock && ! is_wp_error( $changed_stock ) ) {
|
||||
$qty_change_order_notes[] = $item->get_name() . ' – ' . $changed_stock['from'] . '→' . $changed_stock['to'];
|
||||
}
|
||||
$item->delete();
|
||||
continue;
|
||||
}
|
||||
|
@ -256,10 +308,15 @@ function wc_save_order_items( $order_id, $items ) {
|
|||
do_action( 'woocommerce_before_save_order_item', $item );
|
||||
|
||||
$item->save();
|
||||
|
||||
$changed_stock = wc_maybe_adjust_line_item_product_stock( $item );
|
||||
if ( $changed_stock && ! is_wp_error( $changed_stock ) ) {
|
||||
$qty_change_order_notes[] = $item->get_name() . ' (' . $changed_stock['from'] . '→' . $changed_stock['to'] . ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shipping Rows
|
||||
// Shipping Rows.
|
||||
if ( isset( $items['shipping_method_id'] ) ) {
|
||||
$data_keys = array(
|
||||
'shipping_method' => null,
|
||||
|
@ -269,7 +326,9 @@ function wc_save_order_items( $order_id, $items ) {
|
|||
);
|
||||
|
||||
foreach ( $items['shipping_method_id'] as $item_id ) {
|
||||
if ( ! $item = WC_Order_Factory::get_order_item( absint( $item_id ) ) ) {
|
||||
$item = WC_Order_Factory::get_order_item( absint( $item_id ) );
|
||||
|
||||
if ( ! $item ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -311,10 +370,16 @@ function wc_save_order_items( $order_id, $items ) {
|
|||
}
|
||||
|
||||
$order = wc_get_order( $order_id );
|
||||
|
||||
if ( ! empty( $qty_change_order_notes ) ) {
|
||||
/* translators: %s item name. */
|
||||
$order->add_order_note( sprintf( __( 'Adjusted stock: %s', 'woocommerce' ), implode( ', ', $qty_change_order_notes ) ), false, true );
|
||||
}
|
||||
|
||||
$order->update_taxes();
|
||||
$order->calculate_totals( false );
|
||||
|
||||
// Inform other plugins that the items have been saved
|
||||
// Inform other plugins that the items have been saved.
|
||||
do_action( 'woocommerce_saved_order_items', $order_id, $items );
|
||||
}
|
||||
|
||||
|
|
|
@ -56,13 +56,10 @@ class WC_REST_Authentication {
|
|||
|
||||
$rest_prefix = trailingslashit( rest_get_url_prefix() );
|
||||
|
||||
// Check if our endpoint.
|
||||
$woocommerce = ( false !== strpos( $_SERVER['REQUEST_URI'], $rest_prefix . 'wc/' ) ); // @codingStandardsIgnoreLine
|
||||
|
||||
// Allow third party plugins use our authentication methods.
|
||||
$third_party = ( false !== strpos( $_SERVER['REQUEST_URI'], $rest_prefix . 'wc-' ) ); // @codingStandardsIgnoreLine
|
||||
|
||||
return apply_filters( 'woocommerce_rest_is_request_to_rest_api', $woocommerce || $third_party );
|
||||
return apply_filters( 'woocommerce_rest_is_request_to_rest_api', WC()->is_rest_api_request() || $third_party );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -210,7 +210,7 @@ class WC_REST_Orders_Controller extends WC_REST_Orders_V2_Controller {
|
|||
* @return array
|
||||
*/
|
||||
protected function prepare_objects_query( $request ) {
|
||||
// This is needed to get around an array to string notice in WC_REST_Orders_Controller::prepare_objects_query.
|
||||
// This is needed to get around an array to string notice in WC_REST_Orders_V2_Controller::prepare_objects_query.
|
||||
$statuses = $request['status'];
|
||||
unset( $request['status'] );
|
||||
$args = parent::prepare_objects_query( $request );
|
||||
|
@ -228,6 +228,9 @@ class WC_REST_Orders_Controller extends WC_REST_Orders_V2_Controller {
|
|||
}
|
||||
}
|
||||
|
||||
// Put the statuses back for further processing (next/prev links, etc).
|
||||
$request['status'] = $statuses;
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
@ -254,7 +257,7 @@ class WC_REST_Orders_Controller extends WC_REST_Orders_V2_Controller {
|
|||
|
||||
$params['status'] = array(
|
||||
'default' => 'any',
|
||||
'description' => __( 'Limit result set to orders assigned a specific status.', 'woocommerce' ),
|
||||
'description' => __( 'Limit result set to orders which have specific statuses.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
|
|
|
@ -48,32 +48,27 @@ class WC_API_JSON_Handler implements WC_API_Handler {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_response( $data ) {
|
||||
|
||||
if ( isset( $_GET['_jsonp'] ) ) {
|
||||
|
||||
// JSONP enabled by default
|
||||
if ( ! apply_filters( 'woocommerce_api_jsonp_enabled', true ) ) {
|
||||
|
||||
WC()->api->server->send_status( 400 );
|
||||
|
||||
$data = array( array( 'code' => 'woocommerce_api_jsonp_disabled', 'message' => __( 'JSONP support is disabled on this site', 'woocommerce' ) ) );
|
||||
return wp_json_encode( array( array( 'code' => 'woocommerce_api_jsonp_disabled', 'message' => __( 'JSONP support is disabled on this site', 'woocommerce' ) ) ) );
|
||||
}
|
||||
|
||||
// Check for invalid characters (only alphanumeric allowed)
|
||||
if ( preg_match( '/\W/', $_GET['_jsonp'] ) ) {
|
||||
$jsonp_callback = $_GET['_jsonp'];
|
||||
|
||||
if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) {
|
||||
WC()->api->server->send_status( 400 );
|
||||
|
||||
$data = array( array( 'code' => 'woocommerce_api_jsonp_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) );
|
||||
return wp_json_encode( array( array( 'code' => 'woocommerce_api_jsonp_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) ) );
|
||||
}
|
||||
|
||||
// see http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
|
||||
WC()->api->server->header( 'X-Content-Type-Options', 'nosniff' );
|
||||
|
||||
// Prepend '/**/' to mitigate possible JSONP Flash attacks
|
||||
return '/**/' . $_GET['_jsonp'] . '(' . json_encode( $data ) . ')';
|
||||
// Prepend '/**/' to mitigate possible JSONP Flash attacks.
|
||||
// https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
|
||||
return '/**/' . $jsonp_callback . '(' . wp_json_encode( $data ) . ')';
|
||||
}
|
||||
|
||||
return json_encode( $data );
|
||||
return wp_json_encode( $data );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,32 +47,27 @@ class WC_API_JSON_Handler implements WC_API_Handler {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_response( $data ) {
|
||||
|
||||
if ( isset( $_GET['_jsonp'] ) ) {
|
||||
|
||||
// JSONP enabled by default
|
||||
if ( ! apply_filters( 'woocommerce_api_jsonp_enabled', true ) ) {
|
||||
|
||||
WC()->api->server->send_status( 400 );
|
||||
|
||||
$data = array( array( 'code' => 'woocommerce_api_jsonp_disabled', 'message' => __( 'JSONP support is disabled on this site', 'woocommerce' ) ) );
|
||||
return wp_json_encode( array( array( 'code' => 'woocommerce_api_jsonp_disabled', 'message' => __( 'JSONP support is disabled on this site', 'woocommerce' ) ) ) );
|
||||
}
|
||||
|
||||
// Check for invalid characters (only alphanumeric allowed)
|
||||
if ( preg_match( '/\W/', $_GET['_jsonp'] ) ) {
|
||||
$jsonp_callback = $_GET['_jsonp'];
|
||||
|
||||
if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) {
|
||||
WC()->api->server->send_status( 400 );
|
||||
|
||||
$data = array( array( 'code' => 'woocommerce_api_jsonp_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) );
|
||||
return wp_json_encode( array( array( 'code' => 'woocommerce_api_jsonp_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) ) );
|
||||
}
|
||||
|
||||
// see http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
|
||||
WC()->api->server->header( 'X-Content-Type-Options', 'nosniff' );
|
||||
|
||||
// Prepend '/**/' to mitigate possible JSONP Flash attacks
|
||||
return '/**/' . $_GET['_jsonp'] . '(' . json_encode( $data ) . ')';
|
||||
// Prepend '/**/' to mitigate possible JSONP Flash attacks.
|
||||
// https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
|
||||
return '/**/' . $jsonp_callback . '(' . wp_json_encode( $data ) . ')';
|
||||
}
|
||||
|
||||
return json_encode( $data );
|
||||
return wp_json_encode( $data );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -326,21 +326,6 @@ class WC_API_Webhooks extends WC_API_Resource {
|
|||
return $webhook->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get webhooks total results
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @param array $args Request arguments for filtering query.
|
||||
* @return array
|
||||
*/
|
||||
private function get_webhooks_total_results( $args = array() ) {
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$args['limit'] = -1;
|
||||
$args['offset'] = 0;
|
||||
|
||||
return count( $data_store->search_webhooks( $args ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get webhook post objects
|
||||
*
|
||||
|
@ -390,6 +375,8 @@ class WC_API_Webhooks extends WC_API_Resource {
|
|||
unset( $args['date_query'] );
|
||||
}
|
||||
|
||||
$args['paginate'] = true;
|
||||
|
||||
// Get the webhooks.
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$results = $data_store->search_webhooks( $args );
|
||||
|
@ -397,12 +384,12 @@ class WC_API_Webhooks extends WC_API_Resource {
|
|||
// Get total items.
|
||||
$headers = new stdClass;
|
||||
$headers->page = $page;
|
||||
$headers->total = $this->get_webhooks_total_results( $args );
|
||||
$headers->total = $results->total;
|
||||
$headers->is_single = $args['limit'] > $headers->total;
|
||||
$headers->total_pages = ceil( $headers->total / $args['limit'] );
|
||||
$headers->total_pages = $results->max_num_pages;
|
||||
|
||||
return array(
|
||||
'results' => $results,
|
||||
'results' => $results->webhooks,
|
||||
'headers' => $headers,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -47,32 +47,27 @@ class WC_API_JSON_Handler implements WC_API_Handler {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_response( $data ) {
|
||||
|
||||
if ( isset( $_GET['_jsonp'] ) ) {
|
||||
|
||||
// JSONP enabled by default
|
||||
if ( ! apply_filters( 'woocommerce_api_jsonp_enabled', true ) ) {
|
||||
|
||||
WC()->api->server->send_status( 400 );
|
||||
|
||||
$data = array( array( 'code' => 'woocommerce_api_jsonp_disabled', 'message' => __( 'JSONP support is disabled on this site', 'woocommerce' ) ) );
|
||||
return wp_json_encode( array( array( 'code' => 'woocommerce_api_jsonp_disabled', 'message' => __( 'JSONP support is disabled on this site', 'woocommerce' ) ) ) );
|
||||
}
|
||||
|
||||
// Check for invalid characters (only alphanumeric allowed)
|
||||
if ( preg_match( '/\W/', $_GET['_jsonp'] ) ) {
|
||||
$jsonp_callback = $_GET['_jsonp'];
|
||||
|
||||
if ( ! wp_check_jsonp_callback( $jsonp_callback ) ) {
|
||||
WC()->api->server->send_status( 400 );
|
||||
|
||||
$data = array( array( 'code' => 'woocommerce_api_jsonp_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) );
|
||||
return wp_json_encode( array( array( 'code' => 'woocommerce_api_jsonp_callback_invalid', __( 'The JSONP callback function is invalid', 'woocommerce' ) ) ) );
|
||||
}
|
||||
|
||||
// see http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
|
||||
WC()->api->server->header( 'X-Content-Type-Options', 'nosniff' );
|
||||
|
||||
// Prepend '/**/' to mitigate possible JSONP Flash attacks
|
||||
return '/**/' . $_GET['_jsonp'] . '(' . json_encode( $data ) . ')';
|
||||
// Prepend '/**/' to mitigate possible JSONP Flash attacks.
|
||||
// https://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
|
||||
return '/**/' . $jsonp_callback . '(' . wp_json_encode( $data ) . ')';
|
||||
}
|
||||
|
||||
return json_encode( $data );
|
||||
return wp_json_encode( $data );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -326,21 +326,6 @@ class WC_API_Webhooks extends WC_API_Resource {
|
|||
return $webhook->delete( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get webhooks total results
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @param array $args Request arguments for filtering query.
|
||||
* @return array
|
||||
*/
|
||||
private function get_webhooks_total_results( $args = array() ) {
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$args['limit'] = -1;
|
||||
$args['offset'] = 0;
|
||||
|
||||
return count( $data_store->search_webhooks( $args ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get webhook post objects
|
||||
*
|
||||
|
@ -390,6 +375,8 @@ class WC_API_Webhooks extends WC_API_Resource {
|
|||
unset( $args['date_query'] );
|
||||
}
|
||||
|
||||
$args['paginate'] = true;
|
||||
|
||||
// Get the webhooks.
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$results = $data_store->search_webhooks( $args );
|
||||
|
@ -397,12 +384,12 @@ class WC_API_Webhooks extends WC_API_Resource {
|
|||
// Get total items.
|
||||
$headers = new stdClass;
|
||||
$headers->page = $page;
|
||||
$headers->total = $this->get_webhooks_total_results( $args );
|
||||
$headers->total = $results->total;
|
||||
$headers->is_single = $args['limit'] > $headers->total;
|
||||
$headers->total_pages = ceil( $headers->total / $args['limit'] );
|
||||
$headers->total_pages = $results->max_num_pages;
|
||||
|
||||
return array(
|
||||
'results' => $results,
|
||||
'results' => $results->webhooks,
|
||||
'headers' => $headers,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -247,32 +247,29 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Controller {
|
|||
*/
|
||||
$prepared_args = apply_filters( 'woocommerce_rest_webhook_query', $args, $request );
|
||||
unset( $prepared_args['page'] );
|
||||
$prepared_args['paginate'] = true;
|
||||
|
||||
// Get the webhooks.
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$results = $data_store->search_webhooks( $prepared_args );
|
||||
$webhooks = array();
|
||||
$data_store = WC_Data_Store::load( 'webhook' );
|
||||
$results = $data_store->search_webhooks( $prepared_args );
|
||||
$webhook_ids = $results->webhooks;
|
||||
|
||||
$webhooks = array();
|
||||
foreach ( $results as $webhook_id ) {
|
||||
foreach ( $webhook_ids as $webhook_id ) {
|
||||
$data = $this->prepare_item_for_response( $webhook_id, $request );
|
||||
$webhooks[] = $this->prepare_response_for_collection( $data );
|
||||
}
|
||||
|
||||
$response = rest_ensure_response( $webhooks );
|
||||
$response = rest_ensure_response( $webhooks );
|
||||
$per_page = (int) $prepared_args['limit'];
|
||||
$page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
|
||||
$total_webhooks = $results->total;
|
||||
$max_pages = $results->max_num_pages;
|
||||
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
|
||||
|
||||
// Store pagination values for headers then unset for count query.
|
||||
$per_page = (int) $prepared_args['limit'];
|
||||
$page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
|
||||
$response->header( 'X-WP-Total', $total_webhooks );
|
||||
$response->header( 'X-WP-TotalPages', $max_pages );
|
||||
|
||||
// Calculate totals.
|
||||
$prepared_args['limit'] = -1;
|
||||
$prepared_args['offset'] = 0;
|
||||
$total_webhooks = count( $data_store->search_webhooks( $prepared_args ) );
|
||||
$response->header( 'X-WP-Total', (int) $total_webhooks );
|
||||
$max_pages = ceil( $total_webhooks / $per_page );
|
||||
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
||||
|
||||
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
|
||||
if ( $page > 1 ) {
|
||||
$prev_page = $page - 1;
|
||||
if ( $prev_page > $max_pages ) {
|
||||
|
|
|
@ -28,7 +28,7 @@ class WC_Breadcrumb {
|
|||
*/
|
||||
public function add_crumb( $name, $link = '' ) {
|
||||
$this->crumbs[] = array(
|
||||
strip_tags( $name ),
|
||||
wp_strip_all_tags( $name ),
|
||||
$link,
|
||||
);
|
||||
}
|
||||
|
@ -148,8 +148,11 @@ class WC_Breadcrumb {
|
|||
$this->prepend_shop_page();
|
||||
|
||||
$terms = wc_get_product_terms(
|
||||
$post->ID, 'product_cat', apply_filters(
|
||||
'woocommerce_breadcrumb_product_terms_args', array(
|
||||
$post->ID,
|
||||
'product_cat',
|
||||
apply_filters(
|
||||
'woocommerce_breadcrumb_product_terms_args',
|
||||
array(
|
||||
'orderby' => 'parent',
|
||||
'order' => 'DESC',
|
||||
)
|
||||
|
@ -240,7 +243,7 @@ class WC_Breadcrumb {
|
|||
|
||||
if ( ! $_name ) {
|
||||
$product_post_type = get_post_type_object( 'product' );
|
||||
$_name = $product_post_type->labels->singular_name;
|
||||
$_name = $product_post_type->labels->name;
|
||||
}
|
||||
|
||||
$this->add_crumb( $_name, get_post_type_archive_link( 'product' ) );
|
||||
|
@ -253,7 +256,7 @@ class WC_Breadcrumb {
|
|||
$post_type = get_post_type_object( get_post_type() );
|
||||
|
||||
if ( $post_type ) {
|
||||
$this->add_crumb( $post_type->labels->singular_name, get_post_type_archive_link( get_post_type() ) );
|
||||
$this->add_crumb( $post_type->labels->name, get_post_type_archive_link( get_post_type() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,7 +371,7 @@ class WC_Breadcrumb {
|
|||
* Add a breadcrumb for pagination.
|
||||
*/
|
||||
private function paged_trail() {
|
||||
if ( get_query_var( 'paged' ) ) {
|
||||
if ( get_query_var( 'paged' ) && 'subcategories' !== woocommerce_get_loop_display_mode() ) {
|
||||
/* translators: %d: page number */
|
||||
$this->add_crumb( sprintf( __( 'Page %d', 'woocommerce' ), get_query_var( 'paged' ) ) );
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ class WC_Cache_Helper {
|
|||
* Hook in methods.
|
||||
*/
|
||||
public static function init() {
|
||||
add_filter( 'nocache_headers', array( __CLASS__, 'additional_nocache_headers' ), 10 );
|
||||
add_action( 'shutdown', array( __CLASS__, 'delete_transients_on_shutdown' ), 10 );
|
||||
add_action( 'template_redirect', array( __CLASS__, 'geolocation_ajax_redirect' ) );
|
||||
add_action( 'admin_notices', array( __CLASS__, 'notices' ) );
|
||||
|
@ -32,6 +33,18 @@ class WC_Cache_Helper {
|
|||
add_action( 'edit_terms', array( __CLASS__, 'clean_term_cache' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set additonal nocache headers.
|
||||
*
|
||||
* @param array $headers Header names and field values.
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public static function additional_nocache_headers( $headers ) {
|
||||
// Opt-out of Google weblight if page is dynamic e.g. cart/checkout. https://support.google.com/webmasters/answer/6211428?hl=en.
|
||||
$headers['Cache-Control'] = 'no-transform, no-cache, must-revalidate, max-age=0';
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a transient to delete on shutdown.
|
||||
*
|
||||
|
|
|
@ -159,6 +159,7 @@ final class WC_Cart_Totals {
|
|||
'price_includes_tax' => false,
|
||||
'subtotal' => 0,
|
||||
'subtotal_tax' => 0,
|
||||
'subtotal_taxes' => array(),
|
||||
'total' => 0,
|
||||
'total_tax' => 0,
|
||||
'taxes' => array(),
|
||||
|
@ -704,6 +705,8 @@ final class WC_Cart_Totals {
|
|||
* @since 3.2.0
|
||||
*/
|
||||
protected function calculate_item_subtotals() {
|
||||
$merged_subtotal_taxes = array(); // Taxes indexed by tax rate ID for storage later.
|
||||
|
||||
foreach ( $this->items as $item_key => $item ) {
|
||||
if ( $item->price_includes_tax ) {
|
||||
if ( $this->cart->get_customer()->get_is_vat_exempt() ) {
|
||||
|
@ -714,24 +717,31 @@ final class WC_Cart_Totals {
|
|||
}
|
||||
|
||||
$item->subtotal = $item->price;
|
||||
$subtotal_taxes = array();
|
||||
|
||||
if ( $this->calculate_tax && $item->product->is_taxable() ) {
|
||||
$subtotal_taxes = WC_Tax::calc_tax( $item->subtotal, $item->tax_rates, $item->price_includes_tax );
|
||||
$item->subtotal_tax = array_sum( array_map( array( $this, 'round_line_tax' ), $subtotal_taxes ) );
|
||||
$item->subtotal_taxes = WC_Tax::calc_tax( $item->subtotal, $item->tax_rates, $item->price_includes_tax );
|
||||
$item->subtotal_tax = array_sum( array_map( array( $this, 'round_line_tax' ), $item->subtotal_taxes ) );
|
||||
|
||||
if ( $item->price_includes_tax ) {
|
||||
// Use unrounded taxes so we can re-calculate from the orders screen accurately later.
|
||||
$item->subtotal = $item->subtotal - array_sum( $subtotal_taxes );
|
||||
$item->subtotal = $item->subtotal - array_sum( $item->subtotal_taxes );
|
||||
}
|
||||
|
||||
foreach ( $item->subtotal_taxes as $rate_id => $rate ) {
|
||||
if ( ! isset( $merged_subtotal_taxes[ $rate_id ] ) ) {
|
||||
$merged_subtotal_taxes[ $rate_id ] = 0;
|
||||
}
|
||||
$merged_subtotal_taxes[ $rate_id ] += $this->round_line_tax( $rate );
|
||||
}
|
||||
}
|
||||
|
||||
$this->cart->cart_contents[ $item_key ]['line_tax_data'] = array( 'subtotal' => wc_remove_number_precision_deep( $subtotal_taxes ) );
|
||||
$this->cart->cart_contents[ $item_key ]['line_tax_data'] = array( 'subtotal' => wc_remove_number_precision_deep( $item->subtotal_taxes ) );
|
||||
$this->cart->cart_contents[ $item_key ]['line_subtotal'] = wc_remove_number_precision( $item->subtotal );
|
||||
$this->cart->cart_contents[ $item_key ]['line_subtotal_tax'] = wc_remove_number_precision( $item->subtotal_tax );
|
||||
}
|
||||
|
||||
$this->set_total( 'items_subtotal', array_sum( array_map( 'round', array_values( wp_list_pluck( $this->items, 'subtotal' ) ) ) ) );
|
||||
$this->set_total( 'items_subtotal_tax', array_sum( array_values( wp_list_pluck( $this->items, 'subtotal_tax' ) ) ) );
|
||||
$this->set_total( 'items_subtotal_tax', array_sum( $this->round_merged_taxes( $merged_subtotal_taxes ) ) );
|
||||
|
||||
$this->cart->set_subtotal( $this->get_total( 'items_subtotal' ) );
|
||||
$this->cart->set_subtotal_tax( $this->get_total( 'items_subtotal_tax' ) );
|
||||
|
|
|
@ -634,6 +634,9 @@ class WC_Cart extends WC_Legacy_Cart {
|
|||
* @param bool $clear_persistent_cart Should the persistant cart be cleared too. Defaults to true.
|
||||
*/
|
||||
public function empty_cart( $clear_persistent_cart = true ) {
|
||||
|
||||
do_action( 'woocommerce_before_cart_emptied' );
|
||||
|
||||
$this->cart_contents = array();
|
||||
$this->removed_cart_contents = array();
|
||||
$this->shipping_methods = array();
|
||||
|
@ -869,7 +872,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
|||
$tax_totals[ $code ]->is_compound = WC_Tax::is_compound( $key );
|
||||
$tax_totals[ $code ]->label = WC_Tax::get_rate_label( $key );
|
||||
$tax_totals[ $code ]->amount += wc_round_tax_total( $tax );
|
||||
$tax_totals[ $code ]->formatted_amount = wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ) );
|
||||
$tax_totals[ $code ]->formatted_amount = wc_price( $tax_totals[ $code ]->amount );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1425,7 +1428,7 @@ class WC_Cart extends WC_Legacy_Cart {
|
|||
if ( $coupon->is_valid() ) {
|
||||
|
||||
// Get user and posted emails to compare.
|
||||
$current_user = wp_get_current_user();
|
||||
$current_user = wp_get_current_user();
|
||||
$billing_email = isset( $posted['billing_email'] ) ? $posted['billing_email'] : '';
|
||||
$check_emails = array_unique(
|
||||
array_filter(
|
||||
|
@ -1916,10 +1919,10 @@ class WC_Cart extends WC_Legacy_Cart {
|
|||
if ( ! $compound && WC_Tax::is_compound( $key ) ) {
|
||||
continue;
|
||||
}
|
||||
$total += $tax;
|
||||
$total += wc_round_tax_total( $tax );
|
||||
}
|
||||
if ( $display ) {
|
||||
$total = wc_round_tax_total( $total );
|
||||
$total = wc_format_decimal( $total, wc_get_price_decimals() );
|
||||
}
|
||||
return apply_filters( 'woocommerce_cart_taxes_total', $total, $compound, $display, $this );
|
||||
}
|
||||
|
|
|
@ -205,13 +205,30 @@ class WC_Checkout {
|
|||
return $fieldset ? $this->fields[ $fieldset ] : $this->fields;
|
||||
}
|
||||
|
||||
// Fields are based on billing/shipping country. Grab those values but ensure they are valid for the store before using.
|
||||
$billing_country = $this->get_value( 'billing_country' );
|
||||
$billing_country = empty( $billing_country ) ? WC()->countries->get_base_country() : $billing_country;
|
||||
$allowed_countries = WC()->countries->get_allowed_countries();
|
||||
|
||||
if ( ! array_key_exists( $billing_country, $allowed_countries ) ) {
|
||||
$billing_country = current( array_keys( $allowed_countries ) );
|
||||
}
|
||||
|
||||
$shipping_country = $this->get_value( 'shipping_country' );
|
||||
$shipping_country = empty( $shipping_country ) ? WC()->countries->get_base_country() : $shipping_country;
|
||||
$allowed_countries = WC()->countries->get_shipping_countries();
|
||||
|
||||
if ( ! array_key_exists( $shipping_country, $allowed_countries ) ) {
|
||||
$shipping_country = current( array_keys( $allowed_countries ) );
|
||||
}
|
||||
|
||||
$this->fields = array(
|
||||
'billing' => WC()->countries->get_address_fields(
|
||||
$this->get_value( 'billing_country' ),
|
||||
$billing_country,
|
||||
'billing_'
|
||||
),
|
||||
'shipping' => WC()->countries->get_address_fields(
|
||||
$this->get_value( 'shipping_country' ),
|
||||
$shipping_country,
|
||||
'shipping_'
|
||||
),
|
||||
'account' => array(),
|
||||
|
@ -948,13 +965,20 @@ class WC_Checkout {
|
|||
if ( ! is_user_logged_in() && ( $this->is_registration_required() || ! empty( $data['createaccount'] ) ) ) {
|
||||
$username = ! empty( $data['account_username'] ) ? $data['account_username'] : '';
|
||||
$password = ! empty( $data['account_password'] ) ? $data['account_password'] : '';
|
||||
$customer_id = wc_create_new_customer( $data['billing_email'], $username, $password );
|
||||
$customer_id = wc_create_new_customer(
|
||||
$data['billing_email'],
|
||||
$username,
|
||||
$password,
|
||||
array(
|
||||
'first_name' => ! empty( $data['billing_first_name'] ) ? $data['billing_first_name'] : '',
|
||||
'last_name' => ! empty( $data['billing_last_name'] ) ? $data['billing_last_name'] : '',
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $customer_id ) ) {
|
||||
throw new Exception( $customer_id->get_error_message() );
|
||||
}
|
||||
|
||||
wp_set_current_user( $customer_id );
|
||||
wc_set_customer_auth_cookie( $customer_id );
|
||||
|
||||
// As we are now logged in, checkout will need to refresh to show logged in data.
|
||||
|
@ -973,17 +997,17 @@ class WC_Checkout {
|
|||
if ( $customer_id && apply_filters( 'woocommerce_checkout_update_customer_data', true, $this ) ) {
|
||||
$customer = new WC_Customer( $customer_id );
|
||||
|
||||
if ( ! empty( $data['billing_first_name'] ) ) {
|
||||
if ( ! empty( $data['billing_first_name'] ) && '' === $customer->get_first_name() ) {
|
||||
$customer->set_first_name( $data['billing_first_name'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $data['billing_last_name'] ) ) {
|
||||
if ( ! empty( $data['billing_last_name'] ) && '' === $customer->get_last_name() ) {
|
||||
$customer->set_last_name( $data['billing_last_name'] );
|
||||
}
|
||||
|
||||
// If the display name is an email, update to the user's full name.
|
||||
if ( is_email( $customer->get_display_name() ) ) {
|
||||
$customer->set_display_name( $data['billing_first_name'] . ' ' . $data['billing_last_name'] );
|
||||
$customer->set_display_name( $customer->get_first_name() . ' ' . $customer->get_last_name() );
|
||||
}
|
||||
|
||||
foreach ( $data as $key => $value ) {
|
||||
|
|
|
@ -477,7 +477,7 @@ class WC_Countries {
|
|||
'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
|
||||
'AT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
|
||||
'BE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
|
||||
'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
|
||||
'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state_code} {postcode}\n{country}",
|
||||
'CH' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
|
||||
'CL' => "{company}\n{name}\n{address_1}\n{address_2}\n{state}\n{postcode} {city}\n{country}",
|
||||
'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}",
|
||||
|
@ -984,12 +984,21 @@ class WC_Countries {
|
|||
),
|
||||
),
|
||||
'JP' => array(
|
||||
'postcode' => array(
|
||||
'priority' => 65,
|
||||
),
|
||||
'state' => array(
|
||||
'label' => __( 'Prefecture', 'woocommerce' ),
|
||||
'priority' => 66,
|
||||
),
|
||||
'postcode' => array(
|
||||
'priority' => 65,
|
||||
'city' => array(
|
||||
'priority' => 67,
|
||||
),
|
||||
'address_1' => array(
|
||||
'priority' => 68,
|
||||
),
|
||||
'address_2' => array(
|
||||
'priority' => 69,
|
||||
),
|
||||
),
|
||||
'KR' => array(
|
||||
|
@ -1277,6 +1286,7 @@ class WC_Countries {
|
|||
foreach ( $fields as $key => $value ) {
|
||||
if ( 'state' === $key ) {
|
||||
$value['country_field'] = $type . 'country';
|
||||
$value['country'] = $country;
|
||||
}
|
||||
$address_fields[ $type . $key ] = $value;
|
||||
}
|
||||
|
|
|
@ -910,7 +910,13 @@ class WC_Discounts {
|
|||
return wc_add_number_precision( $this->object->get_displayed_subtotal() );
|
||||
} elseif ( is_a( $this->object, 'WC_Order' ) ) {
|
||||
$subtotal = wc_add_number_precision( $this->object->get_subtotal() );
|
||||
return $this->object->get_prices_include_tax() ? $subtotal + round( $this->object->get_total_tax(), wc_get_price_decimals() ) : $subtotal;
|
||||
|
||||
if ( $this->object->get_prices_include_tax() ) {
|
||||
// Add tax to tax-exclusive subtotal.
|
||||
$subtotal = $subtotal + wc_add_number_precision( round( $this->object->get_total_tax(), wc_get_price_decimals() ) );
|
||||
}
|
||||
|
||||
return $subtotal;
|
||||
} else {
|
||||
return array_sum( wp_list_pluck( $this->items, 'price' ) );
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
/**
|
||||
* Handle frontend forms.
|
||||
*
|
||||
* @version 2.2.0
|
||||
* @package WooCommerce/Classes/
|
||||
* @package WooCommerce/Classes/
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
@ -40,17 +39,17 @@ class WC_Form_Handler {
|
|||
* Remove key and user ID (or user login, as a fallback) from query string, set cookie, and redirect to account page to show the form.
|
||||
*/
|
||||
public static function redirect_reset_password_link() {
|
||||
if ( is_account_page() && isset( $_GET['key'] ) && ( isset( $_GET['id'] ) || isset( $_GET['login'] ) ) ) {
|
||||
if ( is_account_page() && isset( $_GET['key'] ) && ( isset( $_GET['id'] ) || isset( $_GET['login'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
|
||||
// If available, get $user_id from query string parameter for fallback purposes.
|
||||
if ( isset( $_GET['login'] ) ) {
|
||||
$user = get_user_by( 'login', sanitize_user( wp_unslash( $_GET['login'] ) ) );
|
||||
if ( isset( $_GET['login'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
$user = get_user_by( 'login', sanitize_user( wp_unslash( $_GET['login'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
$user_id = $user ? $user->ID : 0;
|
||||
} else {
|
||||
$user_id = absint( $_GET['id'] );
|
||||
}
|
||||
|
||||
$value = sprintf( '%d:%s', $user_id, wp_unslash( $_GET['key'] ) );
|
||||
$value = sprintf( '%d:%s', $user_id, wp_unslash( $_GET['key'] ) ); // phpcs:ignore
|
||||
WC_Shortcode_My_Account::set_reset_password_cookie( $value );
|
||||
wp_safe_redirect( add_query_arg( 'show-reset-form', 'true', wc_lostpassword_url() ) );
|
||||
exit;
|
||||
|
@ -64,7 +63,9 @@ class WC_Form_Handler {
|
|||
public static function save_address() {
|
||||
global $wp;
|
||||
|
||||
if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
|
||||
$nonce_value = wc_get_var( $_REQUEST['woocommerce-edit-address-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! wp_verify_nonce( $nonce_value, 'woocommerce-edit_address' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -74,70 +75,72 @@ class WC_Form_Handler {
|
|||
|
||||
wc_nocache_headers();
|
||||
|
||||
$nonce_value = wc_get_var( $_REQUEST['woocommerce-edit-address-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! wp_verify_nonce( $nonce_value, 'woocommerce-edit_address' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
if ( $user_id <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$customer = new WC_Customer( $user_id );
|
||||
|
||||
if ( ! $customer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$load_address = isset( $wp->query_vars['edit-address'] ) ? wc_edit_address_i18n( sanitize_title( $wp->query_vars['edit-address'] ), true ) : 'billing';
|
||||
|
||||
$address = WC()->countries->get_address_fields( esc_attr( $_POST[ $load_address . '_country' ] ), $load_address . '_' );
|
||||
if ( ! isset( $_POST[ $load_address . '_country' ] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$address = WC()->countries->get_address_fields( wc_clean( wp_unslash( $_POST[ $load_address . '_country' ] ) ), $load_address . '_' );
|
||||
|
||||
foreach ( $address as $key => $field ) {
|
||||
|
||||
if ( ! isset( $field['type'] ) ) {
|
||||
$field['type'] = 'text';
|
||||
}
|
||||
|
||||
// Get Value.
|
||||
switch ( $field['type'] ) {
|
||||
case 'checkbox' :
|
||||
$_POST[ $key ] = (int) isset( $_POST[ $key ] );
|
||||
break;
|
||||
default :
|
||||
$_POST[ $key ] = isset( $_POST[ $key ] ) ? wc_clean( $_POST[ $key ] ) : '';
|
||||
break;
|
||||
if ( 'checkbox' === $field['type'] ) {
|
||||
$value = (int) isset( $_POST[ $key ] );
|
||||
} else {
|
||||
$value = isset( $_POST[ $key ] ) ? wc_clean( wp_unslash( $_POST[ $key ] ) ) : '';
|
||||
}
|
||||
|
||||
// Hook to allow modification of value.
|
||||
$_POST[ $key ] = apply_filters( 'woocommerce_process_myaccount_field_' . $key, $_POST[ $key ] );
|
||||
$value = apply_filters( 'woocommerce_process_myaccount_field_' . $key, $value );
|
||||
|
||||
// Validation: Required fields.
|
||||
if ( ! empty( $field['required'] ) && empty( $_POST[ $key ] ) ) {
|
||||
if ( ! empty( $field['required'] ) && empty( $value ) ) {
|
||||
/* translators: %s: Field name. */
|
||||
wc_add_notice( sprintf( __( '%s is a required field.', 'woocommerce' ), $field['label'] ), 'error' );
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST[ $key ] ) ) {
|
||||
|
||||
// Validation rules.
|
||||
if ( ! empty( $value ) ) {
|
||||
// Validation and formatting rules.
|
||||
if ( ! empty( $field['validate'] ) && is_array( $field['validate'] ) ) {
|
||||
foreach ( $field['validate'] as $rule ) {
|
||||
switch ( $rule ) {
|
||||
case 'postcode' :
|
||||
$_POST[ $key ] = strtoupper( str_replace( ' ', '', $_POST[ $key ] ) );
|
||||
case 'postcode':
|
||||
$value = strtoupper( str_replace( ' ', '', $value ) );
|
||||
|
||||
if ( ! WC_Validation::is_postcode( $_POST[ $key ], $_POST[ $load_address . '_country' ] ) ) {
|
||||
if ( ! WC_Validation::is_postcode( $value, wc_clean( wp_unslash( $_POST[ $load_address . '_country' ] ) ) ) ) {
|
||||
wc_add_notice( __( 'Please enter a valid postcode / ZIP.', 'woocommerce' ), 'error' );
|
||||
} else {
|
||||
$_POST[ $key ] = wc_format_postcode( $_POST[ $key ], $_POST[ $load_address . '_country' ] );
|
||||
$value = wc_format_postcode( $value, wc_clean( wp_unslash( $_POST[ $load_address . '_country' ] ) ) );
|
||||
}
|
||||
break;
|
||||
case 'phone' :
|
||||
if ( ! WC_Validation::is_phone( $_POST[ $key ] ) ) {
|
||||
case 'phone':
|
||||
if ( ! WC_Validation::is_phone( $value ) ) {
|
||||
/* translators: %s: Phone number. */
|
||||
wc_add_notice( sprintf( __( '%s is not a valid phone number.', 'woocommerce' ), '<strong>' . $field['label'] . '</strong>' ), 'error' );
|
||||
}
|
||||
break;
|
||||
case 'email' :
|
||||
$_POST[ $key ] = strtolower( $_POST[ $key ] );
|
||||
case 'email':
|
||||
$value = strtolower( $value );
|
||||
|
||||
if ( ! is_email( $_POST[ $key ] ) ) {
|
||||
if ( ! is_email( $value ) ) {
|
||||
/* translators: %s: Email address. */
|
||||
wc_add_notice( sprintf( __( '%s is not a valid email address.', 'woocommerce' ), '<strong>' . $field['label'] . '</strong>' ), 'error' );
|
||||
}
|
||||
break;
|
||||
|
@ -145,43 +148,55 @@ class WC_Form_Handler {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_after_save_address_validation', $user_id, $load_address, $address );
|
||||
|
||||
if ( 0 === wc_notice_count( 'error' ) ) {
|
||||
|
||||
$customer = new WC_Customer( $user_id );
|
||||
|
||||
if ( $customer ) {
|
||||
foreach ( $address as $key => $field ) {
|
||||
if ( is_callable( array( $customer, "set_$key" ) ) ) {
|
||||
$customer->{"set_$key"}( wc_clean( $_POST[ $key ] ) );
|
||||
} else {
|
||||
$customer->update_meta_data( $key, wc_clean( $_POST[ $key ] ) );
|
||||
}
|
||||
|
||||
if ( WC()->customer && is_callable( array( WC()->customer, "set_$key" ) ) ) {
|
||||
WC()->customer->{"set_$key"}( wc_clean( $_POST[ $key ] ) );
|
||||
}
|
||||
try {
|
||||
// Set prop in customer object.
|
||||
if ( is_callable( array( $customer, "set_$key" ) ) ) {
|
||||
$customer->{"set_$key"}( $value );
|
||||
} else {
|
||||
$customer->update_meta_data( $key, $value );
|
||||
}
|
||||
} catch ( WC_Data_Exception $e ) {
|
||||
// Set notices. Ignore invalid billing email, since is already validated.
|
||||
if ( 'customer_invalid_billing_email' !== $e->getErrorCode() ) {
|
||||
wc_add_notice( $e->getMessage(), 'error' );
|
||||
}
|
||||
$customer->save();
|
||||
}
|
||||
|
||||
wc_add_notice( __( 'Address changed successfully.', 'woocommerce' ) );
|
||||
|
||||
do_action( 'woocommerce_customer_save_address', $user_id, $load_address );
|
||||
|
||||
wp_safe_redirect( wc_get_endpoint_url( 'edit-address', '', wc_get_page_permalink( 'myaccount' ) ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook: woocommerce_after_save_address_validation.
|
||||
*
|
||||
* Allow developers to add custom validation logic and throw an error to prevent save.
|
||||
*
|
||||
* @param int $user_id User ID being saved.
|
||||
* @param string $load_address Type of address e.g. billing or shipping.
|
||||
* @param array $address The address fields.
|
||||
* @param WC_Customer $customer The customer object being saved. @since 3.6.0
|
||||
*/
|
||||
do_action( 'woocommerce_after_save_address_validation', $user_id, $load_address, $address, $customer );
|
||||
|
||||
if ( 0 < wc_notice_count( 'error' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$customer->save();
|
||||
|
||||
wc_add_notice( __( 'Address changed successfully.', 'woocommerce' ) );
|
||||
|
||||
do_action( 'woocommerce_customer_save_address', $user_id, $load_address );
|
||||
|
||||
wp_safe_redirect( wc_get_endpoint_url( 'edit-address', '', wc_get_page_permalink( 'myaccount' ) ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the password/account details and redirect back to the my account page.
|
||||
*/
|
||||
public static function save_account_details() {
|
||||
if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
|
||||
$nonce_value = wc_get_var( $_REQUEST['save-account-details-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! wp_verify_nonce( $nonce_value, 'save_account_details' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -191,25 +206,19 @@ class WC_Form_Handler {
|
|||
|
||||
wc_nocache_headers();
|
||||
|
||||
$nonce_value = wc_get_var( $_REQUEST['save-account-details-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! wp_verify_nonce( $nonce_value, 'save_account_details' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
|
||||
if ( $user_id <= 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$account_first_name = ! empty( $_POST['account_first_name'] ) ? wc_clean( $_POST['account_first_name'] ): '';
|
||||
$account_last_name = ! empty( $_POST['account_last_name'] ) ? wc_clean( $_POST['account_last_name'] ) : '';
|
||||
$account_display_name = ! empty( $_POST['account_display_name'] ) ? wc_clean( $_POST['account_display_name'] ) : '';
|
||||
$account_email = ! empty( $_POST['account_email'] ) ? wc_clean( $_POST['account_email'] ) : '';
|
||||
$pass_cur = ! empty( $_POST['password_current'] ) ? $_POST['password_current'] : '';
|
||||
$pass1 = ! empty( $_POST['password_1'] ) ? $_POST['password_1'] : '';
|
||||
$pass2 = ! empty( $_POST['password_2'] ) ? $_POST['password_2'] : '';
|
||||
$account_first_name = ! empty( $_POST['account_first_name'] ) ? wc_clean( wp_unslash( $_POST['account_first_name'] ) ) : '';
|
||||
$account_last_name = ! empty( $_POST['account_last_name'] ) ? wc_clean( wp_unslash( $_POST['account_last_name'] ) ) : '';
|
||||
$account_display_name = ! empty( $_POST['account_display_name'] ) ? wc_clean( wp_unslash( $_POST['account_display_name'] ) ) : '';
|
||||
$account_email = ! empty( $_POST['account_email'] ) ? wc_clean( wp_unslash( $_POST['account_email'] ) ) : '';
|
||||
$pass_cur = ! empty( $_POST['password_current'] ) ? wp_unslash( $_POST['password_current'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$pass1 = ! empty( $_POST['password_1'] ) ? wp_unslash( $_POST['password_1'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$pass2 = ! empty( $_POST['password_2'] ) ? wp_unslash( $_POST['password_2'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$save_pass = true;
|
||||
|
||||
// Current user data.
|
||||
|
@ -219,11 +228,11 @@ class WC_Form_Handler {
|
|||
$current_email = $current_user->user_email;
|
||||
|
||||
// New user data.
|
||||
$user = new stdClass();
|
||||
$user->ID = $user_id;
|
||||
$user->first_name = $account_first_name;
|
||||
$user->last_name = $account_last_name;
|
||||
$user->display_name = $account_display_name;
|
||||
$user = new stdClass();
|
||||
$user->ID = $user_id;
|
||||
$user->first_name = $account_first_name;
|
||||
$user->last_name = $account_last_name;
|
||||
$user->display_name = $account_display_name;
|
||||
|
||||
// Prevent display name to be changed to email.
|
||||
if ( is_email( $account_display_name ) ) {
|
||||
|
@ -231,15 +240,19 @@ class WC_Form_Handler {
|
|||
}
|
||||
|
||||
// Handle required fields.
|
||||
$required_fields = apply_filters( 'woocommerce_save_account_details_required_fields', array(
|
||||
'account_first_name' => __( 'First name', 'woocommerce' ),
|
||||
'account_last_name' => __( 'Last name', 'woocommerce' ),
|
||||
'account_display_name' => __( 'Display name', 'woocommerce' ),
|
||||
'account_email' => __( 'Email address', 'woocommerce' ),
|
||||
) );
|
||||
$required_fields = apply_filters(
|
||||
'woocommerce_save_account_details_required_fields',
|
||||
array(
|
||||
'account_first_name' => __( 'First name', 'woocommerce' ),
|
||||
'account_last_name' => __( 'Last name', 'woocommerce' ),
|
||||
'account_display_name' => __( 'Display name', 'woocommerce' ),
|
||||
'account_email' => __( 'Email address', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $required_fields as $field_key => $field_name ) {
|
||||
if ( empty( $_POST[ $field_key ] ) ) {
|
||||
/* translators: %s: Field name. */
|
||||
wc_add_notice( sprintf( __( '%s is a required field.', 'woocommerce' ), '<strong>' . esc_html( $field_name ) . '</strong>' ), 'error' );
|
||||
}
|
||||
}
|
||||
|
@ -321,11 +334,11 @@ class WC_Form_Handler {
|
|||
* Process the checkout form.
|
||||
*/
|
||||
public static function checkout_action() {
|
||||
if ( isset( $_POST['woocommerce_checkout_place_order'] ) || isset( $_POST['woocommerce_checkout_update_totals'] ) ) {
|
||||
if ( isset( $_POST['woocommerce_checkout_place_order'] ) || isset( $_POST['woocommerce_checkout_update_totals'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
wc_nocache_headers();
|
||||
|
||||
if ( WC()->cart->is_empty() ) {
|
||||
wp_redirect( wc_get_page_permalink( 'cart' ) );
|
||||
wp_safe_redirect( wc_get_page_permalink( 'cart' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
|
@ -341,7 +354,7 @@ class WC_Form_Handler {
|
|||
public static function pay_action() {
|
||||
global $wp;
|
||||
|
||||
if ( isset( $_POST['woocommerce_pay'] ) ) {
|
||||
if ( isset( $_POST['woocommerce_pay'], $_GET['key'] ) ) {
|
||||
wc_nocache_headers();
|
||||
|
||||
$nonce_value = wc_get_var( $_REQUEST['woocommerce-pay-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
@ -352,32 +365,33 @@ class WC_Form_Handler {
|
|||
|
||||
ob_start();
|
||||
|
||||
// Pay for existing order
|
||||
$order_key = $_GET['key'];
|
||||
$order_id = absint( $wp->query_vars['order-pay'] );
|
||||
$order = wc_get_order( $order_id );
|
||||
// Pay for existing order.
|
||||
$order_key = wp_unslash( $_GET['key'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$order_id = absint( $wp->query_vars['order-pay'] );
|
||||
$order = wc_get_order( $order_id );
|
||||
|
||||
if ( $order_id === $order->get_id() && hash_equals( $order->get_order_key(), $order_key ) && $order->needs_payment() ) {
|
||||
|
||||
do_action( 'woocommerce_before_pay_action', $order );
|
||||
|
||||
WC()->customer->set_props( array(
|
||||
'billing_country' => $order->get_billing_country() ? $order->get_billing_country() : null,
|
||||
'billing_state' => $order->get_billing_state() ? $order->get_billing_state() : null,
|
||||
'billing_postcode' => $order->get_billing_postcode() ? $order->get_billing_postcode() : null,
|
||||
'billing_city' => $order->get_billing_city() ? $order->get_billing_city() : null,
|
||||
) );
|
||||
WC()->customer->set_props(
|
||||
array(
|
||||
'billing_country' => $order->get_billing_country() ? $order->get_billing_country() : null,
|
||||
'billing_state' => $order->get_billing_state() ? $order->get_billing_state() : null,
|
||||
'billing_postcode' => $order->get_billing_postcode() ? $order->get_billing_postcode() : null,
|
||||
'billing_city' => $order->get_billing_city() ? $order->get_billing_city() : null,
|
||||
)
|
||||
);
|
||||
WC()->customer->save();
|
||||
|
||||
// Terms
|
||||
if ( ! empty( $_POST['terms-field'] ) && empty( $_POST['terms'] ) ) {
|
||||
wc_add_notice( __( 'Please read and accept the terms and conditions to proceed with your order.', 'woocommerce' ), 'error' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Update payment method
|
||||
// Update payment method.
|
||||
if ( $order->needs_payment() ) {
|
||||
$payment_method = isset( $_POST['payment_method'] ) ? wc_clean( $_POST['payment_method'] ) : false;
|
||||
$payment_method = isset( $_POST['payment_method'] ) ? wc_clean( wp_unslash( $_POST['payment_method'] ) ) : false;
|
||||
$available_gateways = WC()->payment_gateways->get_available_payment_gateways();
|
||||
|
||||
if ( ! $payment_method ) {
|
||||
|
@ -385,7 +399,6 @@ class WC_Form_Handler {
|
|||
return;
|
||||
}
|
||||
|
||||
// Update meta
|
||||
update_post_meta( $order_id, '_payment_method', $payment_method );
|
||||
|
||||
if ( isset( $available_gateways[ $payment_method ] ) ) {
|
||||
|
@ -396,22 +409,20 @@ class WC_Form_Handler {
|
|||
|
||||
update_post_meta( $order_id, '_payment_method_title', $payment_method_title );
|
||||
|
||||
// Validate
|
||||
$available_gateways[ $payment_method ]->validate_fields();
|
||||
|
||||
// Process
|
||||
if ( 0 === wc_notice_count( 'error' ) ) {
|
||||
|
||||
$result = $available_gateways[ $payment_method ]->process_payment( $order_id );
|
||||
|
||||
// Redirect to success/confirmation/payment page
|
||||
// Redirect to success/confirmation/payment page.
|
||||
if ( 'success' === $result['result'] ) {
|
||||
wp_redirect( $result['redirect'] );
|
||||
wp_redirect( $result['redirect'] ); //phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
|
||||
exit;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No payment was required for order
|
||||
// No payment was required for order.
|
||||
$order->payment_complete();
|
||||
wp_safe_redirect( $order->get_checkout_order_received_url() );
|
||||
exit;
|
||||
|
@ -466,7 +477,7 @@ class WC_Form_Handler {
|
|||
}
|
||||
|
||||
if ( ! empty( $result['redirect'] ) ) {
|
||||
wp_redirect( $result['redirect'] );
|
||||
wp_redirect( $result['redirect'] ); //phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
@ -485,14 +496,14 @@ class WC_Form_Handler {
|
|||
$token_id = absint( $wp->query_vars['delete-payment-method'] );
|
||||
$token = WC_Payment_Tokens::get( $token_id );
|
||||
|
||||
if ( is_null( $token ) || get_current_user_id() !== $token->get_user_id() || false === wp_verify_nonce( $_REQUEST['_wpnonce'], 'delete-payment-method-' . $token_id ) ) {
|
||||
if ( is_null( $token ) || get_current_user_id() !== $token->get_user_id() || ! isset( $_REQUEST['_wpnonce'] ) || false === wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'delete-payment-method-' . $token_id ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
wc_add_notice( __( 'Invalid payment method.', 'woocommerce' ), 'error' );
|
||||
} else {
|
||||
WC_Payment_Tokens::delete( $token_id );
|
||||
wc_add_notice( __( 'Payment method deleted.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
wp_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
|
||||
wp_safe_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
|
||||
exit();
|
||||
}
|
||||
|
||||
|
@ -510,14 +521,14 @@ class WC_Form_Handler {
|
|||
$token_id = absint( $wp->query_vars['set-default-payment-method'] );
|
||||
$token = WC_Payment_Tokens::get( $token_id );
|
||||
|
||||
if ( is_null( $token ) || get_current_user_id() !== $token->get_user_id() || false === wp_verify_nonce( $_REQUEST['_wpnonce'], 'set-default-payment-method-' . $token_id ) ) {
|
||||
if ( is_null( $token ) || get_current_user_id() !== $token->get_user_id() || ! isset( $_REQUEST['_wpnonce'] ) || false === wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'set-default-payment-method-' . $token_id ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
wc_add_notice( __( 'Invalid payment method.', 'woocommerce' ), 'error' );
|
||||
} else {
|
||||
WC_Payment_Tokens::set_users_default( $token->get_user_id(), intval( $token_id ) );
|
||||
wc_add_notice( __( 'This payment method was successfully set as your default.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
wp_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
|
||||
wp_safe_redirect( wc_get_account_endpoint_url( 'payment-methods' ) );
|
||||
exit();
|
||||
}
|
||||
|
||||
|
@ -536,10 +547,10 @@ class WC_Form_Handler {
|
|||
$nonce_value = wc_get_var( $_REQUEST['woocommerce-cart-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! empty( $_POST['apply_coupon'] ) && ! empty( $_POST['coupon_code'] ) ) {
|
||||
WC()->cart->add_discount( sanitize_text_field( wp_unslash( $_POST['coupon_code'] ) ) );
|
||||
WC()->cart->add_discount( sanitize_text_field( wp_unslash( $_POST['coupon_code'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
|
||||
} elseif ( isset( $_GET['remove_coupon'] ) ) {
|
||||
WC()->cart->remove_coupon( wc_clean( wp_unslash( $_GET['remove_coupon'] ) ) );
|
||||
WC()->cart->remove_coupon( wc_clean( wp_unslash( $_GET['remove_coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
|
||||
} elseif ( ! empty( $_GET['remove_item'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-cart' ) ) {
|
||||
$cart_item_key = sanitize_text_field( wp_unslash( $_GET['remove_item'] ) );
|
||||
|
@ -550,6 +561,7 @@ class WC_Form_Handler {
|
|||
|
||||
$product = wc_get_product( $cart_item['product_id'] );
|
||||
|
||||
/* translators: %s: Item name. */
|
||||
$item_removed_title = apply_filters( 'woocommerce_cart_item_removed_title', $product ? sprintf( _x( '“%s”', 'Item name in quotes', 'woocommerce' ), $product->get_name() ) : __( 'Item', 'woocommerce' ), $cart_item );
|
||||
|
||||
// Don't show undo link if removed item is out of stock.
|
||||
|
@ -565,7 +577,7 @@ class WC_Form_Handler {
|
|||
wc_add_notice( $removed_notice );
|
||||
}
|
||||
|
||||
$referer = wp_get_referer() ? remove_query_arg( array( 'remove_item', 'add-to-cart', 'added-to-cart', 'order_again', '_wpnonce' ), add_query_arg( 'removed_item', '1', wp_get_referer() ) ) : wc_get_cart_url();
|
||||
$referer = wp_get_referer() ? remove_query_arg( array( 'remove_item', 'add-to-cart', 'added-to-cart', 'order_again', '_wpnonce' ), add_query_arg( 'removed_item', '1', wp_get_referer() ) ) : wc_get_cart_url();
|
||||
wp_safe_redirect( $referer );
|
||||
exit;
|
||||
|
||||
|
@ -576,7 +588,7 @@ class WC_Form_Handler {
|
|||
|
||||
WC()->cart->restore_cart_item( $cart_item_key );
|
||||
|
||||
$referer = wp_get_referer() ? remove_query_arg( array( 'undo_item', '_wpnonce' ), wp_get_referer() ) : wc_get_cart_url();
|
||||
$referer = wp_get_referer() ? remove_query_arg( array( 'undo_item', '_wpnonce' ), wp_get_referer() ) : wc_get_cart_url();
|
||||
wp_safe_redirect( $referer );
|
||||
exit;
|
||||
|
||||
|
@ -658,26 +670,23 @@ class WC_Form_Handler {
|
|||
isset( $_GET['cancel_order'] ) &&
|
||||
isset( $_GET['order'] ) &&
|
||||
isset( $_GET['order_id'] ) &&
|
||||
( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-cancel_order' ) )
|
||||
( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'woocommerce-cancel_order' ) ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
) {
|
||||
wc_nocache_headers();
|
||||
|
||||
$order_key = $_GET['order'];
|
||||
$order_key = wp_unslash( $_GET['order'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$order_id = absint( $_GET['order_id'] );
|
||||
$order = wc_get_order( $order_id );
|
||||
$user_can_cancel = current_user_can( 'cancel_order', $order_id );
|
||||
$order_can_cancel = $order->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ) ) );
|
||||
$redirect = $_GET['redirect'];
|
||||
$redirect = isset( $_GET['redirect'] ) ? wp_unslash( $_GET['redirect'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
if ( $order->has_status( 'cancelled' ) ) {
|
||||
// Already cancelled - take no action
|
||||
} elseif ( $user_can_cancel && $order_can_cancel && $order->get_id() === $order_id && hash_equals( $order->get_order_key(), $order_key ) ) {
|
||||
if ( $user_can_cancel && $order_can_cancel && $order->get_id() === $order_id && hash_equals( $order->get_order_key(), $order_key ) ) {
|
||||
|
||||
// Cancel the order + restore stock
|
||||
// Cancel the order + restore stock.
|
||||
WC()->session->set( 'order_awaiting_payment', false );
|
||||
$order->update_status( 'cancelled', __( 'Order cancelled by customer.', 'woocommerce' ) );
|
||||
|
||||
// Message
|
||||
wc_add_notice( apply_filters( 'woocommerce_order_cancelled_notice', __( 'Your order was cancelled.', 'woocommerce' ) ), apply_filters( 'woocommerce_order_cancelled_notice_type', 'notice' ) );
|
||||
|
||||
do_action( 'woocommerce_cancelled_order', $order->get_id() );
|
||||
|
@ -700,18 +709,18 @@ class WC_Form_Handler {
|
|||
*
|
||||
* Checks for a valid request, does validation (via hooks) and then redirects if valid.
|
||||
*
|
||||
* @param bool $url (default: false)
|
||||
* @param bool $url (default: false) URL to redirect to.
|
||||
*/
|
||||
public static function add_to_cart_action( $url = false ) {
|
||||
if ( empty( $_REQUEST['add-to-cart'] ) || ! is_numeric( $_REQUEST['add-to-cart'] ) ) {
|
||||
if ( ! isset( $_REQUEST['add-to-cart'] ) || ! is_numeric( wp_unslash( $_REQUEST['add-to-cart'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
return;
|
||||
}
|
||||
|
||||
wc_nocache_headers();
|
||||
|
||||
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
|
||||
$was_added_to_cart = false;
|
||||
$adding_to_cart = wc_get_product( $product_id );
|
||||
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( wp_unslash( $_REQUEST['add-to-cart'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
$was_added_to_cart = false;
|
||||
$adding_to_cart = wc_get_product( $product_id );
|
||||
|
||||
if ( ! $adding_to_cart ) {
|
||||
return;
|
||||
|
@ -731,7 +740,9 @@ class WC_Form_Handler {
|
|||
|
||||
// If we added the product to the cart we can now optionally do a redirect.
|
||||
if ( $was_added_to_cart && 0 === wc_notice_count( 'error' ) ) {
|
||||
if ( $url = apply_filters( 'woocommerce_add_to_cart_redirect', $url, $adding_to_cart ) ) {
|
||||
$url = apply_filters( 'woocommerce_add_to_cart_redirect', $url, $adding_to_cart );
|
||||
|
||||
if ( $url ) {
|
||||
wp_safe_redirect( $url );
|
||||
exit;
|
||||
} elseif ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) {
|
||||
|
@ -749,8 +760,8 @@ class WC_Form_Handler {
|
|||
* @return bool success or not
|
||||
*/
|
||||
private static function add_to_cart_handler_simple( $product_id ) {
|
||||
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
|
||||
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
|
||||
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
|
||||
|
||||
if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
|
||||
wc_add_to_cart_message( array( $product_id => $quantity ), true );
|
||||
|
@ -769,24 +780,25 @@ class WC_Form_Handler {
|
|||
private static function add_to_cart_handler_grouped( $product_id ) {
|
||||
$was_added_to_cart = false;
|
||||
$added_to_cart = array();
|
||||
$items = isset( $_REQUEST['quantity'] ) && is_array( $_REQUEST['quantity'] ) ? wp_unslash( $_REQUEST['quantity'] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
if ( ! empty( $_REQUEST['quantity'] ) && is_array( $_REQUEST['quantity'] ) ) {
|
||||
if ( ! empty( $items ) ) {
|
||||
$quantity_set = false;
|
||||
|
||||
foreach ( $_REQUEST['quantity'] as $item => $quantity ) {
|
||||
foreach ( $items as $item => $quantity ) {
|
||||
if ( $quantity <= 0 ) {
|
||||
continue;
|
||||
}
|
||||
$quantity_set = true;
|
||||
|
||||
// Add to cart validation
|
||||
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $item, $quantity );
|
||||
// Add to cart validation.
|
||||
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $item, $quantity );
|
||||
|
||||
// Suppress total recalculation until finished.
|
||||
remove_action( 'woocommerce_add_to_cart', array( WC()->cart, 'calculate_totals' ), 20, 0 );
|
||||
|
||||
if ( $passed_validation && false !== WC()->cart->add_to_cart( $item, $quantity ) ) {
|
||||
$was_added_to_cart = true;
|
||||
$was_added_to_cart = true;
|
||||
$added_to_cart[ $item ] = $quantity;
|
||||
}
|
||||
|
||||
|
@ -811,13 +823,14 @@ class WC_Form_Handler {
|
|||
* Handle adding variable products to the cart.
|
||||
*
|
||||
* @since 2.4.6 Split from add_to_cart_action.
|
||||
* @throws Exception If add to cart fails.
|
||||
* @param int $product_id Product ID to add to the cart.
|
||||
* @return bool success or not
|
||||
*/
|
||||
private static function add_to_cart_handler_variable( $product_id ) {
|
||||
try {
|
||||
$variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) );
|
||||
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // WPCS: sanitization ok.
|
||||
$variation_id = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
$missing_attributes = array();
|
||||
$variations = array();
|
||||
$adding_to_cart = wc_get_product( $product_id );
|
||||
|
@ -846,12 +859,12 @@ class WC_Form_Handler {
|
|||
}
|
||||
$attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );
|
||||
|
||||
if ( isset( $_REQUEST[ $attribute_key ] ) ) {
|
||||
if ( isset( $_REQUEST[ $attribute_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
if ( $attribute['is_taxonomy'] ) {
|
||||
// Don't use wc_clean as it destroys sanitized characters.
|
||||
$value = sanitize_title( wp_unslash( $_REQUEST[ $attribute_key ] ) );
|
||||
$value = sanitize_title( wp_unslash( $_REQUEST[ $attribute_key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
} else {
|
||||
$value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok.
|
||||
$value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
|
||||
}
|
||||
|
||||
$posted_attributes[ $attribute_key ] = $value;
|
||||
|
@ -879,7 +892,7 @@ class WC_Form_Handler {
|
|||
|
||||
// Get valid value from variation data.
|
||||
$attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );
|
||||
$valid_value = isset( $variation_data[ $attribute_key ] ) ? $variation_data[ $attribute_key ]: '';
|
||||
$valid_value = isset( $variation_data[ $attribute_key ] ) ? $variation_data[ $attribute_key ] : '';
|
||||
|
||||
/**
|
||||
* If the attribute value was posted, check if it's valid.
|
||||
|
@ -892,10 +905,11 @@ class WC_Form_Handler {
|
|||
// Allow if valid or show error.
|
||||
if ( $valid_value === $value ) {
|
||||
$variations[ $attribute_key ] = $value;
|
||||
} elseif ( '' === $valid_value && in_array( $value, $attribute->get_slugs() ) ) {
|
||||
} elseif ( '' === $valid_value && in_array( $value, $attribute->get_slugs(), true ) ) {
|
||||
// If valid values are empty, this is an 'any' variation so get all possible values.
|
||||
$variations[ $attribute_key ] = $value;
|
||||
} else {
|
||||
/* translators: %s: Attribute name. */
|
||||
throw new Exception( sprintf( __( 'Invalid value posted for %s', 'woocommerce' ), wc_attribute_label( $attribute['name'] ) ) );
|
||||
}
|
||||
} elseif ( '' === $valid_value ) {
|
||||
|
@ -903,6 +917,7 @@ class WC_Form_Handler {
|
|||
}
|
||||
}
|
||||
if ( ! empty( $missing_attributes ) ) {
|
||||
/* translators: %s: Attribute name. */
|
||||
throw new Exception( sprintf( _n( '%s is a required field', '%s are required fields', count( $missing_attributes ), 'woocommerce' ), wc_format_list_of_items( $missing_attributes ) ) );
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
|
@ -922,22 +937,24 @@ class WC_Form_Handler {
|
|||
|
||||
/**
|
||||
* Process the login form.
|
||||
*
|
||||
* @throws Exception On login error.
|
||||
*/
|
||||
public static function process_login() {
|
||||
// The global form-login.php template used `_wpnonce` in template versions < 3.3.0.
|
||||
$nonce_value = wc_get_var( $_REQUEST['woocommerce-login-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! empty( $_POST['login'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-login' ) ) {
|
||||
if ( isset( $_POST['login'], $_POST['username'], $_POST['password'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-login' ) ) {
|
||||
|
||||
try {
|
||||
$creds = array(
|
||||
'user_login' => trim( $_POST['username'] ),
|
||||
'user_password' => $_POST['password'],
|
||||
'remember' => isset( $_POST['rememberme'] ),
|
||||
'user_login' => trim( wp_unslash( $_POST['username'] ) ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
'user_password' => wp_unslash( $_POST['password'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
'remember' => isset( $_POST['rememberme'] ), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
);
|
||||
|
||||
$validation_error = new WP_Error();
|
||||
$validation_error = apply_filters( 'woocommerce_process_login_errors', $validation_error, $_POST['username'], $_POST['password'] );
|
||||
$validation_error = apply_filters( 'woocommerce_process_login_errors', $validation_error, $creds['user_login'], $creds['user_password'] );
|
||||
|
||||
if ( $validation_error->get_error_code() ) {
|
||||
throw new Exception( '<strong>' . __( 'Error:', 'woocommerce' ) . '</strong> ' . $validation_error->get_error_message() );
|
||||
|
@ -956,7 +973,7 @@ class WC_Form_Handler {
|
|||
}
|
||||
}
|
||||
|
||||
// Perform the login
|
||||
// Perform the login.
|
||||
$user = wp_signon( apply_filters( 'woocommerce_login_credentials', $creds ), is_ssl() );
|
||||
|
||||
if ( is_wp_error( $user ) ) {
|
||||
|
@ -966,14 +983,14 @@ class WC_Form_Handler {
|
|||
} else {
|
||||
|
||||
if ( ! empty( $_POST['redirect'] ) ) {
|
||||
$redirect = $_POST['redirect'];
|
||||
$redirect = wp_unslash( $_POST['redirect'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
} elseif ( wc_get_raw_referer() ) {
|
||||
$redirect = wc_get_raw_referer();
|
||||
} else {
|
||||
$redirect = wc_get_page_permalink( 'myaccount' );
|
||||
}
|
||||
|
||||
wp_redirect( wp_validate_redirect( apply_filters( 'woocommerce_login_redirect', remove_query_arg( 'wc_error', $redirect ), $user ), wc_get_page_permalink( 'myaccount' ) ) );
|
||||
wp_redirect( wp_validate_redirect( apply_filters( 'woocommerce_login_redirect', remove_query_arg( 'wc_error', $redirect ), $user ), wc_get_page_permalink( 'myaccount' ) ) ); // phpcs:ignore
|
||||
exit;
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
|
@ -998,7 +1015,7 @@ class WC_Form_Handler {
|
|||
|
||||
// If successful, redirect to my account with query arg set.
|
||||
if ( $success ) {
|
||||
wp_redirect( add_query_arg( 'reset-link-sent', 'true', wc_get_account_endpoint_url( 'lost-password' ) ) );
|
||||
wp_safe_redirect( add_query_arg( 'reset-link-sent', 'true', wc_get_account_endpoint_url( 'lost-password' ) ) );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
@ -1008,19 +1025,19 @@ class WC_Form_Handler {
|
|||
* Handle reset password form.
|
||||
*/
|
||||
public static function process_reset_password() {
|
||||
$nonce_value = wc_get_var( $_REQUEST['woocommerce-reset-password-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! wp_verify_nonce( $nonce_value, 'reset_password' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$posted_fields = array( 'wc_reset_password', 'password_1', 'password_2', 'reset_key', 'reset_login' );
|
||||
|
||||
foreach ( $posted_fields as $field ) {
|
||||
if ( ! isset( $_POST[ $field ] ) ) {
|
||||
return;
|
||||
}
|
||||
$posted_fields[ $field ] = $_POST[ $field ];
|
||||
}
|
||||
|
||||
$nonce_value = wc_get_var( $_REQUEST['woocommerce-reset-password-nonce'], wc_get_var( $_REQUEST['_wpnonce'], '' ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
if ( ! wp_verify_nonce( $nonce_value, 'reset_password' ) ) {
|
||||
return;
|
||||
$posted_fields[ $field ] = wp_unslash( $_POST[ $field ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
}
|
||||
|
||||
$user = WC_Shortcode_My_Account::check_password_reset_key( $posted_fields['reset_key'], $posted_fields['reset_login'] );
|
||||
|
@ -1045,7 +1062,7 @@ class WC_Form_Handler {
|
|||
|
||||
do_action( 'woocommerce_customer_reset_password', $user );
|
||||
|
||||
wp_redirect( add_query_arg( 'password-reset', 'true', wc_get_page_permalink( 'myaccount' ) ) );
|
||||
wp_safe_redirect( add_query_arg( 'password-reset', 'true', wc_get_page_permalink( 'myaccount' ) ) );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
@ -1053,15 +1070,17 @@ class WC_Form_Handler {
|
|||
|
||||
/**
|
||||
* Process the registration form.
|
||||
*
|
||||
* @throws Exception On registration error.
|
||||
*/
|
||||
public static function process_registration() {
|
||||
$nonce_value = isset( $_POST['_wpnonce'] ) ? $_POST['_wpnonce'] : '';
|
||||
$nonce_value = isset( $_POST['woocommerce-register-nonce'] ) ? $_POST['woocommerce-register-nonce'] : $nonce_value;
|
||||
$nonce_value = isset( $_POST['_wpnonce'] ) ? wp_unslash( $_POST['_wpnonce'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.NoNonceVerification
|
||||
$nonce_value = isset( $_POST['woocommerce-register-nonce'] ) ? wp_unslash( $_POST['woocommerce-register-nonce'] ) : $nonce_value; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.NoNonceVerification
|
||||
|
||||
if ( ! empty( $_POST['register'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-register' ) ) {
|
||||
$username = 'no' === get_option( 'woocommerce_registration_generate_username' ) ? $_POST['username'] : '';
|
||||
$password = 'no' === get_option( 'woocommerce_registration_generate_password' ) ? $_POST['password'] : '';
|
||||
$email = $_POST['email'];
|
||||
if ( isset( $_POST['register'], $_POST['email'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-register' ) ) {
|
||||
$username = 'no' === get_option( 'woocommerce_registration_generate_username' ) && isset( $_POST['username'] ) ? wp_unslash( $_POST['username'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$password = 'no' === get_option( 'woocommerce_registration_generate_password' ) && isset( $_POST['password'] ) ? wp_unslash( $_POST['password'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$email = wp_unslash( $_POST['email'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
try {
|
||||
$validation_error = new WP_Error();
|
||||
|
@ -1077,21 +1096,27 @@ class WC_Form_Handler {
|
|||
throw new Exception( $new_customer->get_error_message() );
|
||||
}
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_registration_generate_password' ) ) {
|
||||
wc_add_notice( __( 'Your account was created successfully and a password has been sent to your email address.', 'woocommerce' ) );
|
||||
} else {
|
||||
wc_add_notice( __( 'Your account was created successfully. Your login details have been sent to your email address.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
// Only redirect after a forced login - otherwise output a success notice.
|
||||
if ( apply_filters( 'woocommerce_registration_auth_new_customer', true, $new_customer ) ) {
|
||||
wc_set_customer_auth_cookie( $new_customer );
|
||||
|
||||
if ( ! empty( $_POST['redirect'] ) ) {
|
||||
$redirect = wp_sanitize_redirect( wp_unslash( $_POST['redirect'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
} elseif ( wc_get_raw_referer() ) {
|
||||
$redirect = wc_get_raw_referer();
|
||||
} else {
|
||||
$redirect = wc_get_page_permalink( 'myaccount' );
|
||||
}
|
||||
|
||||
wp_redirect( wp_validate_redirect( apply_filters( 'woocommerce_registration_redirect', $redirect ), wc_get_page_permalink( 'myaccount' ) ) ); //phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST['redirect'] ) ) {
|
||||
$redirect = wp_sanitize_redirect( $_POST['redirect'] );
|
||||
} elseif ( wc_get_raw_referer() ) {
|
||||
$redirect = wc_get_raw_referer();
|
||||
} else {
|
||||
$redirect = wc_get_page_permalink( 'myaccount' );
|
||||
}
|
||||
|
||||
wp_redirect( wp_validate_redirect( apply_filters( 'woocommerce_registration_redirect', $redirect ), wc_get_page_permalink( 'myaccount' ) ) );
|
||||
exit;
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
wc_add_notice( '<strong>' . __( 'Error:', 'woocommerce' ) . '</strong> ' . $e->getMessage(), 'error' );
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ class WC_Geolocation {
|
|||
|
||||
/**
|
||||
* Get user IP Address using an external service.
|
||||
* This is used mainly as a fallback for users on localhost where
|
||||
* This can be used as a fallback for users on localhost where
|
||||
* get_ip_address() will be a local IP and non-geolocatable.
|
||||
*
|
||||
* @return string
|
||||
|
@ -191,7 +191,7 @@ class WC_Geolocation {
|
|||
* @param bool $api_fallback If true, uses geolocation APIs if the database file doesn't exist (can be slower).
|
||||
* @return array
|
||||
*/
|
||||
public static function geolocate_ip( $ip_address = '', $fallback = true, $api_fallback = true ) {
|
||||
public static function geolocate_ip( $ip_address = '', $fallback = false, $api_fallback = true ) {
|
||||
// Filter to allow custom geolocation of the IP address.
|
||||
$country_code = apply_filters( 'woocommerce_geolocate_ip', false, $ip_address, $fallback, $api_fallback );
|
||||
|
||||
|
|
|
@ -124,6 +124,10 @@ class WC_Install {
|
|||
'wc_update_354_modify_shop_manager_caps',
|
||||
'wc_update_354_db_version',
|
||||
),
|
||||
'3.6.0' => array(
|
||||
'wc_update_360_downloadable_product_permissions_index',
|
||||
'wc_update_360_db_version',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -144,8 +148,6 @@ class WC_Install {
|
|||
add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_row_meta' ), 10, 2 );
|
||||
add_filter( 'wpmu_drop_tables', array( __CLASS__, 'wpmu_drop_tables' ) );
|
||||
add_filter( 'cron_schedules', array( __CLASS__, 'cron_schedules' ) );
|
||||
add_action( 'woocommerce_plugin_background_installer', array( __CLASS__, 'background_installer' ), 10, 2 );
|
||||
add_action( 'woocommerce_theme_background_installer', array( __CLASS__, 'theme_background_installer' ), 10, 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -694,7 +696,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_downloadable_product_permissions (
|
|||
PRIMARY KEY (permission_id),
|
||||
KEY download_order_key_product (product_id,order_id,order_key(16),download_id),
|
||||
KEY download_order_product (download_id,order_id,product_id),
|
||||
KEY order_id (order_id)
|
||||
KEY order_id (order_id),
|
||||
KEY user_order_remaining_expires (user_id,order_id,downloads_remaining,access_expires)
|
||||
) $collate;
|
||||
CREATE TABLE {$wpdb->prefix}woocommerce_order_items (
|
||||
order_item_id BIGINT UNSIGNED NOT NULL auto_increment,
|
||||
|
@ -1235,7 +1238,6 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
|
|||
public static function background_installer( $plugin_to_install_id, $plugin_to_install ) {
|
||||
// Explicitly clear the event.
|
||||
$args = func_get_args();
|
||||
wp_clear_scheduled_hook( 'woocommerce_plugin_background_installer', $args );
|
||||
|
||||
if ( ! empty( $plugin_to_install['repo-slug'] ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
|
@ -1395,7 +1397,6 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta (
|
|||
public static function theme_background_installer( $theme_slug ) {
|
||||
// Explicitly clear the event.
|
||||
$args = func_get_args();
|
||||
wp_clear_scheduled_hook( 'woocommerce_theme_background_installer', $args );
|
||||
|
||||
if ( ! empty( $theme_slug ) ) {
|
||||
// Suppress feedback.
|
||||
|
|
|
@ -180,7 +180,12 @@ class WC_Order_Item_Fee extends WC_Order_Item {
|
|||
$tax_data['total'] = array_map( 'wc_format_decimal', $raw_tax_data['total'] );
|
||||
}
|
||||
$this->set_prop( 'taxes', $tax_data );
|
||||
$this->set_total_tax( array_sum( $tax_data['total'] ) );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$this->set_total_tax( array_sum( $tax_data['total'] ) );
|
||||
} else {
|
||||
$this->set_total_tax( array_sum( array_map( 'wc_round_tax_total', $tax_data['total'] ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -160,8 +160,14 @@ class WC_Order_Item_Product extends WC_Order_Item {
|
|||
}
|
||||
}
|
||||
$this->set_prop( 'taxes', $tax_data );
|
||||
$this->set_total_tax( array_sum( $tax_data['total'] ) );
|
||||
$this->set_subtotal_tax( array_sum( $tax_data['subtotal'] ) );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$this->set_total_tax( array_sum( $tax_data['total'] ) );
|
||||
$this->set_subtotal_tax( array_sum( $tax_data['subtotal'] ) );
|
||||
} else {
|
||||
$this->set_total_tax( array_sum( array_map( 'wc_round_tax_total', $tax_data['total'] ) ) );
|
||||
$this->set_subtotal_tax( array_sum( array_map( 'wc_round_tax_total', $tax_data['subtotal'] ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -347,7 +353,8 @@ class WC_Order_Item_Product extends WC_Order_Item {
|
|||
'order' => $order->get_order_key(),
|
||||
'email' => rawurlencode( $order->get_billing_email() ),
|
||||
'key' => $download_id,
|
||||
), trailingslashit( home_url() )
|
||||
),
|
||||
trailingslashit( home_url() )
|
||||
) : '';
|
||||
}
|
||||
|
||||
|
@ -386,7 +393,8 @@ class WC_Order_Item_Product extends WC_Order_Item {
|
|||
'order' => $order->get_order_key(),
|
||||
'uid' => $email_hash,
|
||||
'key' => $download_id,
|
||||
), trailingslashit( home_url() )
|
||||
),
|
||||
trailingslashit( home_url() )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,12 @@ class WC_Order_Item_Shipping extends WC_Order_Item {
|
|||
$tax_data['total'] = array_map( 'wc_format_decimal', $raw_tax_data );
|
||||
}
|
||||
$this->set_prop( 'taxes', $tax_data );
|
||||
$this->set_total_tax( array_sum( $tax_data['total'] ) );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' ) ) {
|
||||
$this->set_total_tax( array_sum( $tax_data['total'] ) );
|
||||
} else {
|
||||
$this->set_total_tax( array_sum( array_map( 'wc_round_tax_total', $tax_data['total'] ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -287,8 +287,18 @@ class WC_Order extends WC_Abstract_Order {
|
|||
* @since 3.0.0
|
||||
*/
|
||||
public function maybe_set_date_paid() {
|
||||
if ( ! $this->get_date_paid( 'edit' ) && $this->has_status( apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id(), $this ) ) ) {
|
||||
$this->set_date_paid( current_time( 'timestamp', true ) );
|
||||
// This logic only runs if the date_paid prop has not been set yet.
|
||||
if ( ! $this->get_date_paid( 'edit' ) ) {
|
||||
$payment_completed_status = apply_filters( 'woocommerce_payment_complete_order_status', $this->needs_processing() ? 'processing' : 'completed', $this->get_id(), $this );
|
||||
|
||||
if ( $this->has_status( $payment_completed_status ) ) {
|
||||
// If payment complete status is reached, set paid now.
|
||||
$this->set_date_paid( current_time( 'timestamp', true ) );
|
||||
|
||||
} elseif ( 'processing' === $payment_completed_status && $this->has_status( 'completed' ) ) {
|
||||
// If payment complete status was processing, but we've passed that and still have no date, set it now.
|
||||
$this->set_date_paid( current_time( 'timestamp', true ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,8 @@ class WC_Post_Data {
|
|||
public static function init() {
|
||||
add_filter( 'post_type_link', array( __CLASS__, 'variation_post_link' ), 10, 2 );
|
||||
add_action( 'shutdown', array( __CLASS__, 'do_deferred_product_sync' ), 10 );
|
||||
add_action( 'set_object_terms', array( __CLASS__, 'set_object_terms' ), 10, 6 );
|
||||
add_action( 'set_object_terms', array( __CLASS__, 'force_default_term' ), 10, 5 );
|
||||
|
||||
add_action( 'transition_post_status', array( __CLASS__, 'transition_post_status' ), 10, 3 );
|
||||
add_action( 'set_object_terms', array( __CLASS__, 'delete_product_query_transients' ) );
|
||||
add_action( 'woocommerce_product_set_stock_status', array( __CLASS__, 'delete_product_query_transients' ) );
|
||||
add_action( 'woocommerce_product_set_visibility', array( __CLASS__, 'delete_product_query_transients' ) );
|
||||
add_action( 'woocommerce_product_type_changed', array( __CLASS__, 'product_type_changed' ), 10, 3 );
|
||||
|
@ -44,6 +42,7 @@ class WC_Post_Data {
|
|||
add_filter( 'oembed_response_data', array( __CLASS__, 'filter_oembed_response_data' ), 10, 2 );
|
||||
|
||||
// Status transitions.
|
||||
add_action( 'transition_post_status', array( __CLASS__, 'transition_post_status' ), 10, 3 );
|
||||
add_action( 'delete_post', array( __CLASS__, 'delete_post' ) );
|
||||
add_action( 'wp_trash_post', array( __CLASS__, 'trash_post' ) );
|
||||
add_action( 'untrashed_post', array( __CLASS__, 'untrash_post' ) );
|
||||
|
@ -98,25 +97,6 @@ class WC_Post_Data {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete transients when terms are set.
|
||||
*
|
||||
* @param int $object_id Object ID.
|
||||
* @param mixed $terms An array of object terms.
|
||||
* @param array $tt_ids An array of term taxonomy IDs.
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
* @param mixed $append Whether to append new terms to the old terms.
|
||||
* @param array $old_tt_ids Old array of term taxonomy IDs.
|
||||
*/
|
||||
public static function set_object_terms( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
|
||||
foreach ( array_merge( $tt_ids, $old_tt_ids ) as $id ) {
|
||||
delete_transient( 'wc_ln_count_' . md5( sanitize_key( $taxonomy ) . sanitize_key( $id ) ) );
|
||||
}
|
||||
if ( in_array( get_post_type( $object_id ), array( 'product', 'product_variation' ), true ) ) {
|
||||
self::delete_product_query_transients();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When a post status changes.
|
||||
*
|
||||
|
@ -134,23 +114,7 @@ class WC_Post_Data {
|
|||
* Delete product view transients when needed e.g. when post status changes, or visibility/stock status is modified.
|
||||
*/
|
||||
public static function delete_product_query_transients() {
|
||||
// Increments the transient version to invalidate cache.
|
||||
WC_Cache_Helper::get_transient_version( 'product_query', true );
|
||||
|
||||
// If not using an external caching system, we can clear the transients out manually and avoid filling our DB.
|
||||
if ( ! wp_using_ext_object_cache() ) {
|
||||
global $wpdb;
|
||||
|
||||
$wpdb->query(
|
||||
"
|
||||
DELETE FROM `$wpdb->options`
|
||||
WHERE `option_name` LIKE ('\_transient\_wc\_uf\_pid\_%')
|
||||
OR `option_name` LIKE ('\_transient\_timeout\_wc\_uf\_pid\_%')
|
||||
OR `option_name` LIKE ('\_transient\_wc\_products\_will\_display\_%')
|
||||
OR `option_name` LIKE ('\_transient\_timeout\_wc\_products\_will\_display\_%')
|
||||
"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -266,17 +230,6 @@ class WC_Post_Data {
|
|||
return $check;
|
||||
}
|
||||
|
||||
/**
|
||||
* When setting stock level, ensure the stock status is kept in sync.
|
||||
*
|
||||
* @param int $meta_id Meta ID.
|
||||
* @param int $object_id Object ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value.
|
||||
* @deprecated
|
||||
*/
|
||||
public static function sync_product_stock_status( $meta_id, $object_id, $meta_key, $meta_value ) {}
|
||||
|
||||
/**
|
||||
* Forces the order posts to have a title in a certain format (containing the date).
|
||||
* Forces certain product data based on the product's type, e.g. grouped products cannot have a parent.
|
||||
|
@ -496,18 +449,6 @@ class WC_Post_Data {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update changed downloads.
|
||||
*
|
||||
* @deprecated 3.3.0 No action is necessary on changes to download paths since download_id is no longer based on file hash.
|
||||
* @param int $product_id Product ID.
|
||||
* @param int $variation_id Variation ID. Optional product variation identifier.
|
||||
* @param array $downloads Newly set files.
|
||||
*/
|
||||
public static function process_product_file_download_paths( $product_id, $variation_id, $downloads ) {
|
||||
wc_deprecated_function( __FUNCTION__, '3.3' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush meta cache for CRUD objects on direct update.
|
||||
*
|
||||
|
@ -540,6 +481,46 @@ class WC_Post_Data {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When setting stock level, ensure the stock status is kept in sync.
|
||||
*
|
||||
* @param int $meta_id Meta ID.
|
||||
* @param int $object_id Object ID.
|
||||
* @param string $meta_key Meta key.
|
||||
* @param mixed $meta_value Meta value.
|
||||
* @deprecated 3.3
|
||||
*/
|
||||
public static function sync_product_stock_status( $meta_id, $object_id, $meta_key, $meta_value ) {}
|
||||
|
||||
/**
|
||||
* Update changed downloads.
|
||||
*
|
||||
* @deprecated 3.3.0 No action is necessary on changes to download paths since download_id is no longer based on file hash.
|
||||
* @param int $product_id Product ID.
|
||||
* @param int $variation_id Variation ID. Optional product variation identifier.
|
||||
* @param array $downloads Newly set files.
|
||||
*/
|
||||
public static function process_product_file_download_paths( $product_id, $variation_id, $downloads ) {
|
||||
wc_deprecated_function( __FUNCTION__, '3.3' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete transients when terms are set.
|
||||
*
|
||||
* @deprecated 3.6
|
||||
* @param int $object_id Object ID.
|
||||
* @param mixed $terms An array of object terms.
|
||||
* @param array $tt_ids An array of term taxonomy IDs.
|
||||
* @param string $taxonomy Taxonomy slug.
|
||||
* @param mixed $append Whether to append new terms to the old terms.
|
||||
* @param array $old_tt_ids Old array of term taxonomy IDs.
|
||||
*/
|
||||
public static function set_object_terms( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {
|
||||
if ( in_array( get_post_type( $object_id ), array( 'product', 'product_variation' ), true ) ) {
|
||||
self::delete_product_query_transients();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WC_Post_Data::init();
|
||||
|
|
|
@ -484,14 +484,6 @@ class WC_Post_Types {
|
|||
$order_statuses = apply_filters(
|
||||
'woocommerce_register_shop_order_post_statuses',
|
||||
array(
|
||||
'wc-auto-draft' => array(
|
||||
'public' => false,
|
||||
'exclude_from_search' => false,
|
||||
'show_in_admin_all_list' => true,
|
||||
'show_in_admin_status_list' => true,
|
||||
/* translators: %s: number of orders */
|
||||
'label_count' => _n_noop( 'Draft <span class="count">(%s)</span>', 'Draft <span class="count">(%s)</span>', 'woocommerce' ),
|
||||
),
|
||||
'wc-pending' => array(
|
||||
'label' => _x( 'Pending payment', 'Order status', 'woocommerce' ),
|
||||
'public' => false,
|
||||
|
|
|
@ -219,7 +219,9 @@ class WC_Regenerate_Images {
|
|||
$imagedata['width'] = $imagedata['sizes']['full']['width'];
|
||||
}
|
||||
|
||||
$ratio_match = wp_image_matches_ratio( $image[1], $image[2], $imagedata['width'], $imagedata['height'] );
|
||||
if ( $imagedata['width'] && $imagedata['height'] ) {
|
||||
$ratio_match = wp_image_matches_ratio( $image[1], $image[2], $imagedata['width'], $imagedata['height'] );
|
||||
}
|
||||
} else {
|
||||
$ratio_match = wp_image_matches_ratio( $image[1], $image[2], $image_size['width'], $image_size['height'] );
|
||||
}
|
||||
|
|
|
@ -66,6 +66,24 @@ class WC_Session_Handler extends WC_Session {
|
|||
* @since 3.3.0
|
||||
*/
|
||||
public function init() {
|
||||
$this->init_session_cookie();
|
||||
$this->_data = $this->get_session_data();
|
||||
|
||||
add_action( 'woocommerce_set_cart_cookies', array( $this, 'set_customer_session_cookie' ), 10 );
|
||||
add_action( 'shutdown', array( $this, 'save_data' ), 20 );
|
||||
add_action( 'wp_logout', array( $this, 'destroy_session' ) );
|
||||
|
||||
if ( ! is_user_logged_in() ) {
|
||||
add_filter( 'nonce_user_logged_out', array( $this, 'nonce_user_logged_out' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup cookie and customer ID.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public function init_session_cookie() {
|
||||
$cookie = $this->get_session_cookie();
|
||||
|
||||
if ( $cookie ) {
|
||||
|
@ -83,16 +101,6 @@ class WC_Session_Handler extends WC_Session {
|
|||
$this->set_session_expiration();
|
||||
$this->_customer_id = $this->generate_customer_id();
|
||||
}
|
||||
|
||||
$this->_data = $this->get_session_data();
|
||||
|
||||
add_action( 'woocommerce_set_cart_cookies', array( $this, 'set_customer_session_cookie' ), 10 );
|
||||
add_action( 'shutdown', array( $this, 'save_data' ), 20 );
|
||||
add_action( 'wp_logout', array( $this, 'destroy_session' ) );
|
||||
|
||||
if ( ! is_user_logged_in() ) {
|
||||
add_filter( 'nonce_user_logged_out', array( $this, 'nonce_user_logged_out' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -588,6 +588,9 @@ class WC_Shortcodes {
|
|||
* @return string
|
||||
*/
|
||||
public static function shop_messages() {
|
||||
if ( ! function_exists( 'wc_print_notices' ) ) {
|
||||
return '';
|
||||
}
|
||||
return '<div class="woocommerce">' . wc_print_notices( true ) . '</div>';
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@ class WC_Structured_Data {
|
|||
// Generate structured data.
|
||||
add_action( 'woocommerce_before_main_content', array( $this, 'generate_website_data' ), 30 );
|
||||
add_action( 'woocommerce_breadcrumb', array( $this, 'generate_breadcrumblist_data' ), 10 );
|
||||
add_action( 'woocommerce_shop_loop', array( $this, 'generate_product_data' ), 10 );
|
||||
add_action( 'woocommerce_single_product_summary', array( $this, 'generate_product_data' ), 60 );
|
||||
add_action( 'woocommerce_review_meta', array( $this, 'generate_review_data' ), 20 );
|
||||
add_action( 'woocommerce_email_order_details', array( $this, 'generate_order_data' ), 20, 3 );
|
||||
|
@ -120,7 +119,7 @@ class WC_Structured_Data {
|
|||
$types[] = is_shop() || is_product_category() || is_product() ? 'product' : '';
|
||||
$types[] = is_shop() && is_front_page() ? 'website' : '';
|
||||
$types[] = is_product() ? 'review' : '';
|
||||
$types[] = ! is_shop() ? 'breadcrumblist' : '';
|
||||
$types[] = 'breadcrumblist';
|
||||
$types[] = 'order';
|
||||
|
||||
return array_filter( apply_filters( 'woocommerce_structured_data_type_for_page', $types ) );
|
||||
|
@ -153,7 +152,7 @@ class WC_Structured_Data {
|
|||
$data = $this->get_structured_data( $types );
|
||||
|
||||
if ( $data ) {
|
||||
echo '<script type="application/ld+json">' . wp_json_encode( $data ) . '</script>';
|
||||
echo '<script type="application/ld+json">' . wc_esc_json( wp_json_encode( $data ), true ) . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,23 +197,25 @@ class WC_Structured_Data {
|
|||
$permalink = get_permalink( $product->get_id() );
|
||||
|
||||
$markup = array(
|
||||
'@type' => 'Product',
|
||||
'@id' => $permalink . '#product', // Append '#product' to differentiate between this @id and the @id generated for the Breadcrumblist.
|
||||
'name' => $product->get_name(),
|
||||
'@type' => 'Product',
|
||||
'@id' => $permalink . '#product', // Append '#product' to differentiate between this @id and the @id generated for the Breadcrumblist.
|
||||
'name' => $product->get_name(),
|
||||
'url' => $permalink,
|
||||
'image' => wp_get_attachment_url( $product->get_image_id() ),
|
||||
'description' => wp_strip_all_tags( do_shortcode( $product->get_short_description() ? $product->get_short_description() : $product->get_description() ) ),
|
||||
);
|
||||
|
||||
if ( apply_filters( 'woocommerce_structured_data_product_limit', is_product_taxonomy() || is_shop() ) ) {
|
||||
$markup['url'] = $permalink;
|
||||
|
||||
$this->set_data( apply_filters( 'woocommerce_structured_data_product_limited', $markup, $product ) );
|
||||
return;
|
||||
// Declare SKU or fallback to ID.
|
||||
if ( $product->get_sku() ) {
|
||||
$markup['sku'] = $product->get_sku();
|
||||
} else {
|
||||
$markup['sku'] = $product->get_id();
|
||||
}
|
||||
|
||||
$markup['image'] = wp_get_attachment_url( $product->get_image_id() );
|
||||
$markup['description'] = wp_strip_all_tags( do_shortcode( $product->get_short_description() ? $product->get_short_description() : $product->get_description() ) );
|
||||
$markup['sku'] = $product->get_sku();
|
||||
|
||||
if ( '' !== $product->get_price() ) {
|
||||
// Assume prices will be valid until the end of next year, unless on sale and there is an end date.
|
||||
$price_valid_until = date( 'Y-12-31', current_time( 'timestamp', true ) + YEAR_IN_SECONDS );
|
||||
|
||||
if ( $product->is_type( 'variable' ) ) {
|
||||
$lowest = $product->get_variation_price( 'min', false );
|
||||
$highest = $product->get_variation_price( 'max', false );
|
||||
|
@ -223,6 +224,7 @@ class WC_Structured_Data {
|
|||
$markup_offer = array(
|
||||
'@type' => 'Offer',
|
||||
'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
|
||||
'priceValidUntil' => $price_valid_until,
|
||||
'priceSpecification' => array(
|
||||
'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
|
||||
'priceCurrency' => $currency,
|
||||
|
@ -237,9 +239,13 @@ class WC_Structured_Data {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
if ( $product->is_on_sale() && $product->get_date_on_sale_to() ) {
|
||||
$price_valid_until = date( 'Y-m-d', $product->get_date_on_sale_to()->getTimestamp() );
|
||||
}
|
||||
$markup_offer = array(
|
||||
'@type' => 'Offer',
|
||||
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
|
||||
'priceValidUntil' => $price_valid_until,
|
||||
'priceSpecification' => array(
|
||||
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
|
||||
'priceCurrency' => $currency,
|
||||
|
@ -268,6 +274,47 @@ class WC_Structured_Data {
|
|||
'ratingValue' => $product->get_average_rating(),
|
||||
'reviewCount' => $product->get_review_count(),
|
||||
);
|
||||
|
||||
// Markup most recent rating/review.
|
||||
$comments = get_comments(
|
||||
array(
|
||||
'number' => 1,
|
||||
'post_id' => $product->get_id(),
|
||||
'status' => 'approve',
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'product',
|
||||
'parent' => 0,
|
||||
'meta_key' => 'rating',
|
||||
'orderby' => 'meta_value_num',
|
||||
)
|
||||
);
|
||||
|
||||
if ( $comments ) {
|
||||
foreach ( $comments as $comment ) {
|
||||
$rating = get_comment_meta( $comment->comment_ID, 'rating', true );
|
||||
|
||||
if ( ! $rating ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$markup['review'] = array(
|
||||
'@type' => 'Review',
|
||||
'reviewRating' => array(
|
||||
'@type' => 'Rating',
|
||||
'ratingValue' => $rating,
|
||||
),
|
||||
'author' => array(
|
||||
'@type' => 'Person',
|
||||
'name' => get_comment_author( $comment->comment_ID ),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check we have required data.
|
||||
if ( empty( $markup['aggregateRating'] ) && empty( $markup['offers'] ) && empty( $markup['review'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->set_data( apply_filters( 'woocommerce_structured_data_product', $markup, $product ) );
|
||||
|
@ -296,7 +343,7 @@ class WC_Structured_Data {
|
|||
|
||||
if ( $rating ) {
|
||||
$markup['reviewRating'] = array(
|
||||
'@type' => 'rating',
|
||||
'@type' => 'Rating',
|
||||
'ratingValue' => $rating,
|
||||
);
|
||||
} elseif ( $comment->comment_parent ) {
|
||||
|
@ -340,6 +387,10 @@ class WC_Structured_Data {
|
|||
|
||||
if ( ! empty( $crumb[1] ) ) {
|
||||
$markup['itemListElement'][ $key ]['item'] += array( '@id' => $crumb[1] );
|
||||
} elseif ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
|
||||
$current_url = set_url_scheme( 'http://' . wp_unslash( $_SERVER['HTTP_HOST'] ) . wp_unslash( $_SERVER['REQUEST_URI'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
$markup['itemListElement'][ $key ]['item'] += array( '@id' => $current_url );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* Tax calculation and rate finding class.
|
||||
*
|
||||
* @package WooCommerce/Classes
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Performs tax calculations and loads tax rates
|
||||
*
|
||||
* @class WC_Tax
|
||||
* @version 2.2.0
|
||||
* @package WooCommerce/Classes
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
* @class WC_Tax
|
||||
*/
|
||||
class WC_Tax {
|
||||
|
||||
|
@ -31,8 +30,6 @@ class WC_Tax {
|
|||
|
||||
/**
|
||||
* Load options.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public static function init() {
|
||||
self::$precision = wc_get_rounding_precision();
|
||||
|
@ -42,8 +39,9 @@ class WC_Tax {
|
|||
|
||||
/**
|
||||
* When the woocommerce_tax_classes option is changed, remove any orphan rates.
|
||||
* @param string $old_value
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $old_value Old rates value.
|
||||
* @param string $value New rates value.
|
||||
*/
|
||||
public static function maybe_remove_tax_class_rates( $old_value, $value ) {
|
||||
$old = array_filter( array_map( 'trim', explode( "\n", $old_value ) ) );
|
||||
|
@ -83,9 +81,9 @@ class WC_Tax {
|
|||
/**
|
||||
* Calculate the shipping tax using a passed array of rates.
|
||||
*
|
||||
* @param float Price
|
||||
* @param array Taxation Rate
|
||||
* @return array
|
||||
* @param float $price Shipping cost.
|
||||
* @param array $rates Taxation Rate.
|
||||
* @return array
|
||||
*/
|
||||
public static function calc_shipping_tax( $price, $rates ) {
|
||||
$taxes = self::calc_exclusive_tax( $price, $rates );
|
||||
|
@ -102,8 +100,7 @@ class WC_Tax {
|
|||
* }
|
||||
* add_filter( 'woocommerce_tax_round', 'euro_5cent_rounding' );
|
||||
*
|
||||
* @param float|int $in
|
||||
*
|
||||
* @param float|int $in Value to round.
|
||||
* @return float
|
||||
*/
|
||||
public static function round( $in ) {
|
||||
|
@ -153,6 +150,13 @@ class WC_Tax {
|
|||
$taxes[ $key ] += $tax_amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Round all taxes to precision (4DP) before passing them back. Note, this is not the same rounding
|
||||
* as in the cart calculation class which, depending on settings, will round to 2DP when calculating
|
||||
* final totals. Also unlike that class, this rounds .5 up for all cases.
|
||||
*/
|
||||
$taxes = array_map( array( __CLASS__, 'round' ), $taxes );
|
||||
|
||||
return $taxes;
|
||||
}
|
||||
|
||||
|
@ -203,31 +207,44 @@ class WC_Tax {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Round all taxes to precision (4DP) before passing them back. Note, this is not the same rounding
|
||||
* as in the cart calculation class which, depending on settings, will round to 2DP when calculating
|
||||
* final totals. Also unlike that class, this rounds .5 up for all cases.
|
||||
*/
|
||||
$taxes = array_map( array( __CLASS__, 'round' ), $taxes );
|
||||
|
||||
return $taxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for all matching country/state/postcode tax rates.
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $args Args that determine the rate to find.
|
||||
* @return array
|
||||
*/
|
||||
public static function find_rates( $args = array() ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'country' => '',
|
||||
'state' => '',
|
||||
'city' => '',
|
||||
'postcode' => '',
|
||||
'tax_class' => '',
|
||||
) );
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'country' => '',
|
||||
'state' => '',
|
||||
'city' => '',
|
||||
'postcode' => '',
|
||||
'tax_class' => '',
|
||||
)
|
||||
);
|
||||
|
||||
extract( $args, EXTR_SKIP );
|
||||
$country = $args['country'];
|
||||
$state = $args['state'];
|
||||
$city = $args['city'];
|
||||
$postcode = wc_normalize_postcode( wc_clean( $args['postcode'] ) );
|
||||
$tax_class = $args['tax_class'];
|
||||
|
||||
if ( ! $country ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$postcode = wc_normalize_postcode( wc_clean( $postcode ) );
|
||||
$cache_key = WC_Cache_Helper::get_cache_prefix( 'taxes' ) . 'wc_tax_rates_' . md5( sprintf( '%s+%s+%s+%s+%s', $country, $state, $city, $postcode, $tax_class ) );
|
||||
$matched_tax_rates = wp_cache_get( $cache_key, 'taxes' );
|
||||
|
||||
|
@ -242,7 +259,7 @@ class WC_Tax {
|
|||
/**
|
||||
* Searches for all matching country/state/postcode tax rates.
|
||||
*
|
||||
* @param array $args
|
||||
* @param array $args Args that determine the rate to find.
|
||||
* @return array
|
||||
*/
|
||||
public static function find_shipping_rates( $args = array() ) {
|
||||
|
@ -262,12 +279,12 @@ class WC_Tax {
|
|||
|
||||
/**
|
||||
* Does the sort comparison. Compares (in this order):
|
||||
* - Priority
|
||||
* - Country
|
||||
* - State
|
||||
* - Number of postcodes
|
||||
* - Number of cities
|
||||
* - ID
|
||||
* - Priority
|
||||
* - Country
|
||||
* - State
|
||||
* - Number of postcodes
|
||||
* - Number of cities
|
||||
* - ID
|
||||
*
|
||||
* @param object $rate1 First rate to compare.
|
||||
* @param object $rate2 Second rate to compare.
|
||||
|
@ -275,7 +292,7 @@ class WC_Tax {
|
|||
*/
|
||||
private static function sort_rates_callback( $rate1, $rate2 ) {
|
||||
if ( $rate1->tax_rate_priority !== $rate2->tax_rate_priority ) {
|
||||
return $rate1->tax_rate_priority < $rate2->tax_rate_priority ? -1 : 1; // ASC
|
||||
return $rate1->tax_rate_priority < $rate2->tax_rate_priority ? -1 : 1; // ASC.
|
||||
}
|
||||
|
||||
if ( $rate1->tax_rate_country !== $rate2->tax_rate_country ) {
|
||||
|
@ -361,10 +378,10 @@ class WC_Tax {
|
|||
/**
|
||||
* Location matching criteria - ORed
|
||||
* Needs to match:
|
||||
* - rates with no postcodes and cities
|
||||
* - rates with a matching postcode and city
|
||||
* - rates with matching postcode, no city
|
||||
* - rates with matching city, no postcode
|
||||
* - rates with no postcodes and cities
|
||||
* - rates with a matching postcode and city
|
||||
* - rates with matching postcode, no city
|
||||
* - rates with matching city, no postcode
|
||||
*/
|
||||
$locations_criteria = array();
|
||||
$locations_criteria[] = 'locations.location_type IS NULL';
|
||||
|
@ -387,17 +404,24 @@ class WC_Tax {
|
|||
AND sub.tax_rate_id = tax_rates.tax_rate_id
|
||||
)
|
||||
";
|
||||
|
||||
$criteria[] = '( ( ' . implode( ' ) OR ( ', $locations_criteria ) . ' ) )';
|
||||
|
||||
$found_rates = $wpdb->get_results( "
|
||||
$criteria_string = implode( ' AND ', $criteria );
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||
$found_rates = $wpdb->get_results(
|
||||
"
|
||||
SELECT tax_rates.*, COUNT( locations.location_id ) as postcode_count, COUNT( locations2.location_id ) as city_count
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates as tax_rates
|
||||
LEFT OUTER JOIN {$wpdb->prefix}woocommerce_tax_rate_locations as locations ON tax_rates.tax_rate_id = locations.tax_rate_id
|
||||
LEFT OUTER JOIN {$wpdb->prefix}woocommerce_tax_rate_locations as locations2 ON tax_rates.tax_rate_id = locations2.tax_rate_id
|
||||
WHERE 1=1 AND " . implode( ' AND ', $criteria ) . "
|
||||
WHERE 1=1 AND {$criteria_string}
|
||||
GROUP BY tax_rates.tax_rate_id
|
||||
ORDER BY tax_rates.tax_rate_priority
|
||||
" );
|
||||
"
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
$found_rates = self::sort_rates( $found_rates );
|
||||
$matched_tax_rates = array();
|
||||
|
@ -426,14 +450,14 @@ class WC_Tax {
|
|||
*
|
||||
* Used by get_rates(), get_shipping_rates().
|
||||
*
|
||||
* @param $tax_class string Optional, passed to the filter for advanced tax setups.
|
||||
* @param string $tax_class string Optional, passed to the filter for advanced tax setups.
|
||||
* @param object $customer Override the customer object to get their location.
|
||||
* @return array
|
||||
*/
|
||||
public static function get_tax_location( $tax_class = '', $customer = null ) {
|
||||
$location = array();
|
||||
|
||||
if ( is_null( $customer ) && ! empty( WC()->customer ) ) {
|
||||
if ( is_null( $customer ) && WC()->customer ) {
|
||||
$customer = WC()->customer;
|
||||
}
|
||||
|
||||
|
@ -463,16 +487,18 @@ class WC_Tax {
|
|||
$location = self::get_tax_location( $tax_class, $customer );
|
||||
$matched_tax_rates = array();
|
||||
|
||||
if ( sizeof( $location ) === 4 ) {
|
||||
if ( count( $location ) === 4 ) {
|
||||
list( $country, $state, $postcode, $city ) = $location;
|
||||
|
||||
$matched_tax_rates = self::find_rates( array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $tax_class,
|
||||
) );
|
||||
$matched_tax_rates = self::find_rates(
|
||||
array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $tax_class,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_matched_rates', $matched_tax_rates, $tax_class );
|
||||
|
@ -481,25 +507,31 @@ class WC_Tax {
|
|||
/**
|
||||
* Get's an array of matching rates for the shop's base country.
|
||||
*
|
||||
* @param string Tax Class
|
||||
* @return array
|
||||
* @param string $tax_class Tax Class.
|
||||
* @return array
|
||||
*/
|
||||
public static function get_base_tax_rates( $tax_class = '' ) {
|
||||
return apply_filters( 'woocommerce_base_tax_rates', self::find_rates( array(
|
||||
'country' => WC()->countries->get_base_country(),
|
||||
'state' => WC()->countries->get_base_state(),
|
||||
'postcode' => WC()->countries->get_base_postcode(),
|
||||
'city' => WC()->countries->get_base_city(),
|
||||
'tax_class' => $tax_class,
|
||||
) ), $tax_class );
|
||||
return apply_filters(
|
||||
'woocommerce_base_tax_rates',
|
||||
self::find_rates(
|
||||
array(
|
||||
'country' => WC()->countries->get_base_country(),
|
||||
'state' => WC()->countries->get_base_state(),
|
||||
'postcode' => WC()->countries->get_base_postcode(),
|
||||
'city' => WC()->countries->get_base_city(),
|
||||
'tax_class' => $tax_class,
|
||||
)
|
||||
),
|
||||
$tax_class
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for get_base_tax_rates().
|
||||
*
|
||||
* @deprecated 2.3
|
||||
* @param string Tax Class
|
||||
* @return array
|
||||
* @param string $tax_class Tax Class.
|
||||
* @return array
|
||||
*/
|
||||
public static function get_shop_base_rate( $tax_class = '' ) {
|
||||
return self::get_base_tax_rates( $tax_class );
|
||||
|
@ -513,7 +545,7 @@ class WC_Tax {
|
|||
* @return mixed
|
||||
*/
|
||||
public static function get_shipping_tax_rates( $tax_class = null, $customer = null ) {
|
||||
// See if we have an explicitly set shipping tax class
|
||||
// See if we have an explicitly set shipping tax class.
|
||||
$shipping_tax_class = get_option( 'woocommerce_shipping_tax_class' );
|
||||
|
||||
if ( 'inherit' !== $shipping_tax_class ) {
|
||||
|
@ -523,22 +555,24 @@ class WC_Tax {
|
|||
$location = self::get_tax_location( $tax_class, $customer );
|
||||
$matched_tax_rates = array();
|
||||
|
||||
if ( sizeof( $location ) === 4 ) {
|
||||
if ( 4 === count( $location ) ) {
|
||||
list( $country, $state, $postcode, $city ) = $location;
|
||||
|
||||
if ( ! is_null( $tax_class ) ) {
|
||||
// This will be per item shipping
|
||||
$matched_tax_rates = self::find_shipping_rates( array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $tax_class,
|
||||
) );
|
||||
// This will be per item shipping.
|
||||
$matched_tax_rates = self::find_shipping_rates(
|
||||
array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $tax_class,
|
||||
)
|
||||
);
|
||||
|
||||
} elseif ( WC()->cart->get_cart() ) {
|
||||
|
||||
// This will be per order shipping - loop through the order and find the highest tax class rate
|
||||
// This will be per order shipping - loop through the order and find the highest tax class rate.
|
||||
$cart_tax_classes = WC()->cart->get_cart_item_tax_classes_for_shipping();
|
||||
|
||||
// No tax classes = no taxable items.
|
||||
|
@ -547,42 +581,47 @@ class WC_Tax {
|
|||
}
|
||||
|
||||
// If multiple classes are found, use the first one found unless a standard rate item is found. This will be the first listed in the 'additional tax class' section.
|
||||
if ( sizeof( $cart_tax_classes ) > 1 && ! in_array( '', $cart_tax_classes ) ) {
|
||||
if ( count( $cart_tax_classes ) > 1 && ! in_array( '', $cart_tax_classes, true ) ) {
|
||||
$tax_classes = self::get_tax_class_slugs();
|
||||
|
||||
foreach ( $tax_classes as $tax_class ) {
|
||||
if ( in_array( $tax_class, $cart_tax_classes ) ) {
|
||||
$matched_tax_rates = self::find_shipping_rates( array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $tax_class,
|
||||
) );
|
||||
if ( in_array( $tax_class, $cart_tax_classes, true ) ) {
|
||||
$matched_tax_rates = self::find_shipping_rates(
|
||||
array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $tax_class,
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If a single tax class is found, use it
|
||||
} elseif ( sizeof( $cart_tax_classes ) == 1 ) {
|
||||
$matched_tax_rates = self::find_shipping_rates( array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $cart_tax_classes[0],
|
||||
) );
|
||||
} elseif ( 1 === count( $cart_tax_classes ) ) {
|
||||
// If a single tax class is found, use it.
|
||||
$matched_tax_rates = self::find_shipping_rates(
|
||||
array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
'tax_class' => $cart_tax_classes[0],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Get standard rate if no taxes were found
|
||||
if ( ! sizeof( $matched_tax_rates ) ) {
|
||||
$matched_tax_rates = self::find_shipping_rates( array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
) );
|
||||
// Get standard rate if no taxes were found.
|
||||
if ( ! count( $matched_tax_rates ) ) {
|
||||
$matched_tax_rates = self::find_shipping_rates(
|
||||
array(
|
||||
'country' => $country,
|
||||
'state' => $state,
|
||||
'postcode' => $postcode,
|
||||
'city' => $city,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -592,18 +631,18 @@ class WC_Tax {
|
|||
/**
|
||||
* Return true/false depending on if a rate is a compound rate.
|
||||
*
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_compound( $key_or_rate ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( is_object( $key_or_rate ) ) {
|
||||
$key = $key_or_rate->tax_rate_id;
|
||||
$compound = $key_or_rate->tax_rate_compound;
|
||||
$key = $key_or_rate->tax_rate_id;
|
||||
$compound = $key_or_rate->tax_rate_compound;
|
||||
} else {
|
||||
$key = $key_or_rate;
|
||||
$compound = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate_compound FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $key ) );
|
||||
$key = $key_or_rate;
|
||||
$compound = (bool) $wpdb->get_var( $wpdb->prepare( "SELECT tax_rate_compound FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $key ) );
|
||||
}
|
||||
|
||||
return (bool) apply_filters( 'woocommerce_rate_compound', $compound, $key );
|
||||
|
@ -612,7 +651,7 @@ class WC_Tax {
|
|||
/**
|
||||
* Return a given rates label.
|
||||
*
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_rate_label( $key_or_rate ) {
|
||||
|
@ -636,7 +675,7 @@ class WC_Tax {
|
|||
/**
|
||||
* Return a given rates percent.
|
||||
*
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_rate_percent( $key_or_rate ) {
|
||||
|
@ -656,8 +695,7 @@ class WC_Tax {
|
|||
/**
|
||||
* Get a rates code. Code is made up of COUNTRY-STATE-NAME-Priority. E.g GB-VAT-1, US-AL-TAX-1.
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format
|
||||
* @param mixed $key_or_rate Tax rate ID, or the db row itself in object format.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_rate_code( $key_or_rate ) {
|
||||
|
@ -674,11 +712,11 @@ class WC_Tax {
|
|||
$code_string = '';
|
||||
|
||||
if ( null !== $rate ) {
|
||||
$code = array();
|
||||
$code[] = $rate->tax_rate_country;
|
||||
$code[] = $rate->tax_rate_state;
|
||||
$code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
|
||||
$code[] = absint( $rate->tax_rate_priority );
|
||||
$code = array();
|
||||
$code[] = $rate->tax_rate_country;
|
||||
$code[] = $rate->tax_rate_state;
|
||||
$code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
|
||||
$code[] = absint( $rate->tax_rate_priority );
|
||||
$code_string = strtoupper( implode( '-', array_filter( $code ) ) );
|
||||
}
|
||||
|
||||
|
@ -686,13 +724,13 @@ class WC_Tax {
|
|||
}
|
||||
|
||||
/**
|
||||
* Round tax lines and return the sum.
|
||||
* Sums a set of taxes to form a single total. Values are pre-rounded to precision from 3.6.0.
|
||||
*
|
||||
* @param array
|
||||
* @return float
|
||||
* @param array $taxes Array of taxes.
|
||||
* @return float
|
||||
*/
|
||||
public static function get_tax_total( $taxes ) {
|
||||
return array_sum( array_map( array( __CLASS__, 'round' ), $taxes ) );
|
||||
return array_sum( $taxes );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -721,12 +759,22 @@ class WC_Tax {
|
|||
* @return array Array of class slugs ("reduced-rate", "zero-rate", etc).
|
||||
*/
|
||||
public static function get_tax_class_slugs() {
|
||||
return array_filter( array_map( 'sanitize_title', self::get_tax_classes() ) );
|
||||
$cache_key = WC_Cache_Helper::get_cache_prefix( 'taxes' ) . '-slugs';
|
||||
$slugs = wp_cache_get( $cache_key, 'taxes' );
|
||||
|
||||
if ( ! $slugs ) {
|
||||
$slugs = array_filter( array_map( 'sanitize_title', self::get_tax_classes() ) );
|
||||
|
||||
wp_cache_set( $cache_key, $slugs, 'taxes' );
|
||||
}
|
||||
|
||||
return $slugs;
|
||||
}
|
||||
|
||||
/**
|
||||
* format the city.
|
||||
* @param string $city
|
||||
* Format the city.
|
||||
*
|
||||
* @param string $city Value to format.
|
||||
* @return string
|
||||
*/
|
||||
private static function format_tax_rate_city( $city ) {
|
||||
|
@ -734,8 +782,9 @@ class WC_Tax {
|
|||
}
|
||||
|
||||
/**
|
||||
* format the state.
|
||||
* @param string $state
|
||||
* Format the state.
|
||||
*
|
||||
* @param string $state Value to format.
|
||||
* @return string
|
||||
*/
|
||||
private static function format_tax_rate_state( $state ) {
|
||||
|
@ -744,8 +793,9 @@ class WC_Tax {
|
|||
}
|
||||
|
||||
/**
|
||||
* format the country.
|
||||
* @param string $country
|
||||
* Format the country.
|
||||
*
|
||||
* @param string $country Value to format.
|
||||
* @return string
|
||||
*/
|
||||
private static function format_tax_rate_country( $country ) {
|
||||
|
@ -754,8 +804,9 @@ class WC_Tax {
|
|||
}
|
||||
|
||||
/**
|
||||
* format the tax rate name.
|
||||
* @param string $name
|
||||
* Format the tax rate name.
|
||||
*
|
||||
* @param string $name Value to format.
|
||||
* @return string
|
||||
*/
|
||||
private static function format_tax_rate_name( $name ) {
|
||||
|
@ -763,17 +814,19 @@ class WC_Tax {
|
|||
}
|
||||
|
||||
/**
|
||||
* format the rate.
|
||||
* @param double $rate
|
||||
* Format the rate.
|
||||
*
|
||||
* @param float $rate Value to format.
|
||||
* @return string
|
||||
*/
|
||||
private static function format_tax_rate( $rate ) {
|
||||
return number_format( (double) $rate, 4, '.', '' );
|
||||
return number_format( (float) $rate, 4, '.', '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* format the priority.
|
||||
* @param string $priority
|
||||
* Format the priority.
|
||||
*
|
||||
* @param string $priority Value to format.
|
||||
* @return int
|
||||
*/
|
||||
private static function format_tax_rate_priority( $priority ) {
|
||||
|
@ -781,14 +834,15 @@ class WC_Tax {
|
|||
}
|
||||
|
||||
/**
|
||||
* format the class.
|
||||
* @param string $class
|
||||
* Format the class.
|
||||
*
|
||||
* @param string $class Value to format.
|
||||
* @return string
|
||||
*/
|
||||
public static function format_tax_rate_class( $class ) {
|
||||
$class = sanitize_title( $class );
|
||||
$classes = self::get_tax_class_slugs();
|
||||
if ( ! in_array( $class, $classes ) ) {
|
||||
if ( ! in_array( $class, $classes, true ) ) {
|
||||
$class = '';
|
||||
}
|
||||
return ( 'standard' === $class ) ? '' : $class;
|
||||
|
@ -796,7 +850,8 @@ class WC_Tax {
|
|||
|
||||
/**
|
||||
* Prepare and format tax rate for DB insertion.
|
||||
* @param array $tax_rate
|
||||
*
|
||||
* @param array $tax_rate Tax rate to format.
|
||||
* @return array
|
||||
*/
|
||||
private static function prepare_tax_rate( $tax_rate ) {
|
||||
|
@ -818,10 +873,8 @@ class WC_Tax {
|
|||
* Internal use only.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*
|
||||
* @param array $tax_rate
|
||||
*
|
||||
* @param array $tax_rate Tax rate to insert.
|
||||
* @return int tax rate id
|
||||
*/
|
||||
public static function _insert_tax_rate( $tax_rate ) {
|
||||
|
@ -829,11 +882,13 @@ class WC_Tax {
|
|||
|
||||
$wpdb->insert( $wpdb->prefix . 'woocommerce_tax_rates', self::prepare_tax_rate( $tax_rate ) );
|
||||
|
||||
$tax_rate_id = $wpdb->insert_id;
|
||||
|
||||
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
|
||||
|
||||
do_action( 'woocommerce_tax_rate_added', $wpdb->insert_id, $tax_rate );
|
||||
do_action( 'woocommerce_tax_rate_added', $tax_rate_id, $tax_rate );
|
||||
|
||||
return $wpdb->insert_id;
|
||||
return $tax_rate_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -842,21 +897,25 @@ class WC_Tax {
|
|||
* Internal use only.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @access private
|
||||
*
|
||||
* @param int $tax_rate_id
|
||||
* @param string $output_type
|
||||
*
|
||||
* @param int $tax_rate_id Tax rate ID.
|
||||
* @param string $output_type Type of output.
|
||||
* @return array|object
|
||||
*/
|
||||
public static function _get_tax_rate( $tax_rate_id, $output_type = ARRAY_A ) {
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->get_row( $wpdb->prepare( "
|
||||
SELECT *
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates
|
||||
WHERE tax_rate_id = %d
|
||||
", $tax_rate_id ), $output_type );
|
||||
return $wpdb->get_row(
|
||||
$wpdb->prepare(
|
||||
"
|
||||
SELECT *
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates
|
||||
WHERE tax_rate_id = %d
|
||||
",
|
||||
$tax_rate_id
|
||||
),
|
||||
$output_type
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -865,10 +924,9 @@ class WC_Tax {
|
|||
* Internal use only.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*
|
||||
* @param int $tax_rate_id
|
||||
* @param array $tax_rate
|
||||
* @param int $tax_rate_id Tax rate to update.
|
||||
* @param array $tax_rate Tax rate values.
|
||||
*/
|
||||
public static function _update_tax_rate( $tax_rate_id, $tax_rate ) {
|
||||
global $wpdb;
|
||||
|
@ -876,7 +934,7 @@ class WC_Tax {
|
|||
$tax_rate_id = absint( $tax_rate_id );
|
||||
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . "woocommerce_tax_rates",
|
||||
$wpdb->prefix . 'woocommerce_tax_rates',
|
||||
self::prepare_tax_rate( $tax_rate ),
|
||||
array(
|
||||
'tax_rate_id' => $tax_rate_id,
|
||||
|
@ -894,9 +952,7 @@ class WC_Tax {
|
|||
* Internal use only.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*
|
||||
* @param int $tax_rate_id
|
||||
* @param int $tax_rate_id Tax rate to delete.
|
||||
*/
|
||||
public static function _delete_tax_rate( $tax_rate_id ) {
|
||||
global $wpdb;
|
||||
|
@ -915,10 +971,9 @@ class WC_Tax {
|
|||
* Internal use only.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*
|
||||
* @param int $tax_rate_id
|
||||
* @param string $postcodes String of postcodes separated by ; characters
|
||||
* @param int $tax_rate_id Tax rate to update.
|
||||
* @param string $postcodes String of postcodes separated by ; characters.
|
||||
*/
|
||||
public static function _update_tax_rate_postcodes( $tax_rate_id, $postcodes ) {
|
||||
if ( ! is_array( $postcodes ) ) {
|
||||
|
@ -928,7 +983,7 @@ class WC_Tax {
|
|||
foreach ( $postcodes as $key => $postcode ) {
|
||||
$postcodes[ $key ] = strtoupper( trim( str_replace( chr( 226 ) . chr( 128 ) . chr( 166 ), '...', $postcode ) ) );
|
||||
}
|
||||
self::_update_tax_rate_locations( $tax_rate_id, array_diff( array_filter( $postcodes ), array( '*' ) ), 'postcode' );
|
||||
self::update_tax_rate_locations( $tax_rate_id, array_diff( array_filter( $postcodes ), array( '*' ) ), 'postcode' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -937,10 +992,9 @@ class WC_Tax {
|
|||
* Internal use only.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*
|
||||
* @param int $tax_rate_id
|
||||
* @param string $cities
|
||||
* @param int $tax_rate_id Tax rate to update.
|
||||
* @param string $cities Cities to set.
|
||||
*/
|
||||
public static function _update_tax_rate_cities( $tax_rate_id, $cities ) {
|
||||
if ( ! is_array( $cities ) ) {
|
||||
|
@ -948,7 +1002,7 @@ class WC_Tax {
|
|||
}
|
||||
$cities = array_filter( array_diff( array_map( array( __CLASS__, 'format_tax_rate_city' ), $cities ), array( '*' ) ) );
|
||||
|
||||
self::_update_tax_rate_locations( $tax_rate_id, $cities, 'city' );
|
||||
self::update_tax_rate_locations( $tax_rate_id, $cities, 'city' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -957,30 +1011,28 @@ class WC_Tax {
|
|||
* Internal use only.
|
||||
*
|
||||
* @since 2.3.0
|
||||
* @access private
|
||||
*
|
||||
* @param int $tax_rate_id
|
||||
* @param array $values
|
||||
* @param string $type
|
||||
* @param int $tax_rate_id Tax rate ID to update.
|
||||
* @param array $values Values to set.
|
||||
* @param string $type Location type.
|
||||
*/
|
||||
private static function _update_tax_rate_locations( $tax_rate_id, $values, $type ) {
|
||||
private static function update_tax_rate_locations( $tax_rate_id, $values, $type ) {
|
||||
global $wpdb;
|
||||
|
||||
$tax_rate_id = absint( $tax_rate_id );
|
||||
|
||||
$wpdb->query(
|
||||
$wpdb->prepare( "
|
||||
DELETE FROM {$wpdb->prefix}woocommerce_tax_rate_locations WHERE tax_rate_id = %d AND location_type = %s;
|
||||
", $tax_rate_id, $type
|
||||
$wpdb->prepare(
|
||||
"DELETE FROM {$wpdb->prefix}woocommerce_tax_rate_locations WHERE tax_rate_id = %d AND location_type = %s;",
|
||||
$tax_rate_id,
|
||||
$type
|
||||
)
|
||||
);
|
||||
|
||||
if ( sizeof( $values ) > 0 ) {
|
||||
if ( count( $values ) > 0 ) {
|
||||
$sql = "( '" . implode( "', $tax_rate_id, '" . esc_sql( $type ) . "' ),( '", array_map( 'esc_sql', $values ) ) . "', $tax_rate_id, '" . esc_sql( $type ) . "' )";
|
||||
|
||||
$wpdb->query( "
|
||||
INSERT INTO {$wpdb->prefix}woocommerce_tax_rate_locations ( location_code, tax_rate_id, location_type ) VALUES $sql;
|
||||
" );
|
||||
$wpdb->query( "INSERT INTO {$wpdb->prefix}woocommerce_tax_rate_locations ( location_code, tax_rate_id, location_type ) VALUES $sql;" ); // @codingStandardsIgnoreLine.
|
||||
}
|
||||
|
||||
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
|
||||
|
@ -989,7 +1041,7 @@ class WC_Tax {
|
|||
/**
|
||||
* Used by admin settings page.
|
||||
*
|
||||
* @param string $tax_class
|
||||
* @param string $tax_class Tax class slug.
|
||||
*
|
||||
* @return array|null|object
|
||||
*/
|
||||
|
|
|
@ -123,62 +123,158 @@ class WC_Webhook extends WC_Legacy_Webhook {
|
|||
* @return bool True if webhook should be delivered, false otherwise.
|
||||
*/
|
||||
private function should_deliver( $arg ) {
|
||||
$should_deliver = true;
|
||||
$current_action = current_action();
|
||||
$should_deliver = $this->is_active() && $this->is_valid_topic() && $this->is_valid_action( $arg ) && $this->is_valid_resource( $arg );
|
||||
|
||||
// Only active webhooks can be delivered.
|
||||
if ( 'active' !== $this->get_status() ) {
|
||||
$should_deliver = false;
|
||||
} elseif ( in_array( $current_action, array( 'delete_post', 'wp_trash_post', 'untrashed_post' ), true ) ) {
|
||||
// Only deliver deleted/restored event for coupons, orders, and products.
|
||||
if ( isset( $GLOBALS['post_type'] ) && ! in_array( $GLOBALS['post_type'], array( 'shop_coupon', 'shop_order', 'product' ), true ) ) {
|
||||
$should_deliver = false;
|
||||
}
|
||||
|
||||
// Check if is delivering for the correct resource.
|
||||
if ( isset( $GLOBALS['post_type'] ) && str_replace( 'shop_', '', $GLOBALS['post_type'] ) !== $this->get_resource() ) {
|
||||
$should_deliver = false;
|
||||
}
|
||||
} elseif ( 'delete_user' === $current_action ) {
|
||||
$user = get_userdata( absint( $arg ) );
|
||||
|
||||
// Only deliver deleted customer event for users with customer role.
|
||||
if ( ! $user || ! in_array( 'customer', (array) $user->roles, true ) ) {
|
||||
$should_deliver = false;
|
||||
}
|
||||
} elseif ( 'order' === $this->get_resource() && ! in_array( get_post_type( absint( $arg ) ), wc_get_order_types( 'order-webhooks' ), true ) ) {
|
||||
// Only if the custom order type has chosen to exclude order webhooks from triggering along with its own webhooks.
|
||||
$should_deliver = false;
|
||||
|
||||
} elseif ( 0 === strpos( $current_action, 'woocommerce_process_shop' ) || 0 === strpos( $current_action, 'woocommerce_process_product' ) ) {
|
||||
// The `woocommerce_process_shop_*` and `woocommerce_process_product_*` hooks
|
||||
// fire for create and update of products and orders, so check the post
|
||||
// creation date to determine the actual event.
|
||||
$resource = get_post( absint( $arg ) );
|
||||
|
||||
// Drafts don't have post_date_gmt so calculate it here.
|
||||
$gmt_date = get_gmt_from_date( $resource->post_date );
|
||||
|
||||
// A resource is considered created when the hook is executed within 10 seconds of the post creation date.
|
||||
$resource_created = ( ( time() - 10 ) <= strtotime( $gmt_date ) );
|
||||
|
||||
if ( 'created' === $this->get_event() && ! $resource_created ) {
|
||||
$should_deliver = false;
|
||||
} elseif ( 'updated' === $this->get_event() && $resource_created ) {
|
||||
$should_deliver = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! wc_is_webhook_valid_topic( $this->get_topic() ) ) {
|
||||
$should_deliver = false;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Let other plugins intercept deliver for some messages queue like rabbit/zeromq.
|
||||
*
|
||||
* @param bool $should_deliver True if the webhook should be sent, or false to not send it.
|
||||
* @param WC_Webhook $this The current webhook class.
|
||||
* @param mixed $arg First hook argument.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_webhook_should_deliver', $should_deliver, $this, $arg );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if webhook is active.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @return bool True if validation passes.
|
||||
*/
|
||||
private function is_active() {
|
||||
return 'active' === $this->get_status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if topic is valid.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @return bool True if validation passes.
|
||||
*/
|
||||
private function is_valid_topic() {
|
||||
return wc_is_webhook_valid_topic( $this->get_topic() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the criteria for certain actions.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param mixed $arg First hook argument.
|
||||
* @return bool True if validation passes.
|
||||
*/
|
||||
private function is_valid_action( $arg ) {
|
||||
$current_action = current_action();
|
||||
$return = true;
|
||||
|
||||
switch ( $current_action ) {
|
||||
case 'delete_post':
|
||||
case 'wp_trash_post':
|
||||
case 'untrashed_post':
|
||||
$return = $this->is_valid_post_action( $arg );
|
||||
break;
|
||||
case 'delete_user':
|
||||
$return = $this->is_valid_user_action( $arg );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( 0 === strpos( $current_action, 'woocommerce_process_shop' ) || 0 === strpos( $current_action, 'woocommerce_process_product' ) ) {
|
||||
$return = $this->is_valid_processing_action( $arg );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates post actions.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param mixed $arg First hook argument.
|
||||
* @return bool True if validation passes.
|
||||
*/
|
||||
private function is_valid_post_action( $arg ) {
|
||||
// Only deliver deleted/restored event for coupons, orders, and products.
|
||||
if ( isset( $GLOBALS['post_type'] ) && ! in_array( $GLOBALS['post_type'], array( 'shop_coupon', 'shop_order', 'product' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if is delivering for the correct resource.
|
||||
if ( isset( $GLOBALS['post_type'] ) && str_replace( 'shop_', '', $GLOBALS['post_type'] ) !== $this->get_resource() ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates user actions.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param mixed $arg First hook argument.
|
||||
* @return bool True if validation passes.
|
||||
*/
|
||||
private function is_valid_user_action( $arg ) {
|
||||
$user = get_userdata( absint( $arg ) );
|
||||
|
||||
// Only deliver deleted customer event for users with customer role.
|
||||
if ( ! $user || ! in_array( 'customer', (array) $user->roles, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates WC processing actions.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param mixed $arg First hook argument.
|
||||
* @return bool True if validation passes.
|
||||
*/
|
||||
private function is_valid_processing_action( $arg ) {
|
||||
// The `woocommerce_process_shop_*` and `woocommerce_process_product_*` hooks
|
||||
// fire for create and update of products and orders, so check the post
|
||||
// creation date to determine the actual event.
|
||||
$resource = get_post( absint( $arg ) );
|
||||
|
||||
// Drafts don't have post_date_gmt so calculate it here.
|
||||
$gmt_date = get_gmt_from_date( $resource->post_date );
|
||||
|
||||
// A resource is considered created when the hook is executed within 10 seconds of the post creation date.
|
||||
$resource_created = ( ( time() - 10 ) <= strtotime( $gmt_date ) );
|
||||
|
||||
if ( 'created' === $this->get_event() && ! $resource_created ) {
|
||||
return false;
|
||||
} elseif ( 'updated' === $this->get_event() && $resource_created ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the resource for this webhook is valid e.g. valid post status.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param mixed $arg First hook argument.
|
||||
* @return bool True if validation passes.
|
||||
*/
|
||||
private function is_valid_resource( $arg ) {
|
||||
$resource = $this->get_resource();
|
||||
|
||||
if ( in_array( $resource, array( 'order', 'product', 'coupon' ), true ) ) {
|
||||
$status = get_post_status( absint( $arg ) );
|
||||
|
||||
// Ignore auto drafts for all resources.
|
||||
if ( in_array( $status, array( 'auto-draft', 'new' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore standard drafts for orders.
|
||||
if ( 'order' === $resource && 'draft' === $status ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deliver the webhook payload using wp_safe_remote_request().
|
||||
*
|
||||
|
@ -290,6 +386,11 @@ class WC_Webhook extends WC_Legacy_Webhook {
|
|||
$rest_api_versions = wc_get_webhook_rest_api_versions();
|
||||
$version_suffix = end( $rest_api_versions ) !== $this->get_api_version() ? strtoupper( str_replace( 'wp_api', '', $this->get_api_version() ) ) : '';
|
||||
|
||||
// Load REST API endpoints to generate payload.
|
||||
if ( ! did_action( 'rest_api_init' ) ) {
|
||||
WC()->api->rest_api_includes();
|
||||
}
|
||||
|
||||
switch ( $resource ) {
|
||||
case 'coupon':
|
||||
case 'customer':
|
||||
|
@ -373,7 +474,7 @@ class WC_Webhook extends WC_Legacy_Webhook {
|
|||
public function generate_signature( $payload ) {
|
||||
$hash_algo = apply_filters( 'woocommerce_webhook_hash_algorithm', 'sha256', $payload, $this->get_id() );
|
||||
|
||||
return base64_encode( hash_hmac( $hash_algo, $payload, $this->get_secret(), true ) );
|
||||
return base64_encode( hash_hmac( $hash_algo, $payload, wp_specialchars_decode( $this->get_secret(), ENT_QUOTES ), true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -863,11 +964,9 @@ class WC_Webhook extends WC_Legacy_Webhook {
|
|||
'delete_user',
|
||||
),
|
||||
'order.created' => array(
|
||||
'woocommerce_process_shop_order_meta',
|
||||
'woocommerce_new_order',
|
||||
),
|
||||
'order.updated' => array(
|
||||
'woocommerce_process_shop_order_meta',
|
||||
'woocommerce_update_order',
|
||||
'woocommerce_order_refunded',
|
||||
),
|
||||
|
|
|
@ -154,7 +154,18 @@ final class WooCommerce {
|
|||
$this->define_constants();
|
||||
$this->includes();
|
||||
$this->init_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* When WP has loaded all plugins, trigger the `woocommerce_loaded` hook.
|
||||
*
|
||||
* This ensures `woocommerce_loaded` is called only after all other plugins
|
||||
* are loaded, to avoid issues caused by plugin directory naming changing
|
||||
* the load order. See #21524 for details.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*/
|
||||
public function on_plugins_loaded() {
|
||||
do_action( 'woocommerce_loaded' );
|
||||
}
|
||||
|
||||
|
@ -166,6 +177,8 @@ final class WooCommerce {
|
|||
private function init_hooks() {
|
||||
register_activation_hook( WC_PLUGIN_FILE, array( 'WC_Install', 'install' ) );
|
||||
register_shutdown_function( array( $this, 'log_errors' ) );
|
||||
|
||||
add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ), -1 );
|
||||
add_action( 'after_setup_theme', array( $this, 'setup_environment' ) );
|
||||
add_action( 'after_setup_theme', array( $this, 'include_template_functions' ), 11 );
|
||||
add_action( 'init', array( $this, 'init' ), 0 );
|
||||
|
@ -183,7 +196,7 @@ final class WooCommerce {
|
|||
*/
|
||||
public function log_errors() {
|
||||
$error = error_get_last();
|
||||
if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ) ) ) {
|
||||
if ( in_array( $error['type'], array( E_ERROR, E_PARSE, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR ), true ) ) {
|
||||
$logger = wc_get_logger();
|
||||
$logger->critical(
|
||||
/* translators: 1: error message 2: file name and path 3: line number */
|
||||
|
@ -227,6 +240,29 @@ final class WooCommerce {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the request is a non-legacy REST API request.
|
||||
*
|
||||
* Legacy REST requests should still run some extra code for backwards compatibility.
|
||||
*
|
||||
* @todo: replace this function once core WP function is available: https://core.trac.wordpress.org/ticket/42061.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_rest_api_request() {
|
||||
if ( empty( $_SERVER['REQUEST_URI'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// REST API prefix.
|
||||
$rest_prefix = trailingslashit( rest_get_url_prefix() );
|
||||
|
||||
// Check if this is a WC endpoint.
|
||||
$is_woocommerce_endpoint = ( false !== strpos( $_SERVER['REQUEST_URI'], $rest_prefix . 'wc/' ) ); // phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
|
||||
return apply_filters( 'woocommerce_is_rest_api_request', $is_woocommerce_endpoint );
|
||||
}
|
||||
|
||||
/**
|
||||
* What type of request is this?
|
||||
*
|
||||
|
@ -242,7 +278,7 @@ final class WooCommerce {
|
|||
case 'cron':
|
||||
return defined( 'DOING_CRON' );
|
||||
case 'frontend':
|
||||
return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' ) && ! defined( 'REST_REQUEST' );
|
||||
return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' ) && ! $this->is_rest_api_request();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -525,7 +561,11 @@ final class WooCommerce {
|
|||
* Ensure theme and server variable compatibility and setup image sizes.
|
||||
*/
|
||||
public function setup_environment() {
|
||||
/* @deprecated 2.2 Use WC()->template_path() instead. */
|
||||
/**
|
||||
* WC_TEMPLATE_PATH constant.
|
||||
*
|
||||
* @deprecated 2.2 Use WC()->template_path() instead.
|
||||
*/
|
||||
$this->define( 'WC_TEMPLATE_PATH', $this->template_path() );
|
||||
|
||||
$this->add_thumbnail_support();
|
||||
|
@ -564,7 +604,11 @@ final class WooCommerce {
|
|||
add_image_size( 'woocommerce_single', $single['width'], $single['height'], $single['crop'] );
|
||||
add_image_size( 'woocommerce_gallery_thumbnail', $gallery_thumbnail['width'], $gallery_thumbnail['height'], $gallery_thumbnail['crop'] );
|
||||
|
||||
// Registered for bw compat. @todo remove in 4.0.
|
||||
/**
|
||||
* Legacy image sizes.
|
||||
*
|
||||
* @deprecated These sizes will be removed in 4.0.
|
||||
*/
|
||||
add_image_size( 'shop_catalog', $thumbnail['width'], $thumbnail['height'], $thumbnail['crop'] );
|
||||
add_image_size( 'shop_single', $single['width'], $single['height'], $single['crop'] );
|
||||
add_image_size( 'shop_thumbnail', $gallery_thumbnail['width'], $gallery_thumbnail['height'], $gallery_thumbnail['crop'] );
|
||||
|
@ -644,7 +688,15 @@ final class WooCommerce {
|
|||
return;
|
||||
}
|
||||
|
||||
wc_load_webhooks();
|
||||
/**
|
||||
* Hook: woocommerce_load_webhooks_limit.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param int $limit Used to limit how many webhooks are loaded. Default: no limit.
|
||||
*/
|
||||
$limit = apply_filters( 'woocommerce_load_webhooks_limit', null );
|
||||
|
||||
wc_load_webhooks( 'active', $limit );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,6 +58,9 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
|||
$order->set_date_created( current_time( 'timestamp', true ) );
|
||||
$order->set_currency( $order->get_currency() ? $order->get_currency() : get_woocommerce_currency() );
|
||||
|
||||
$raw_status = $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' );
|
||||
$status = wc_is_order_status( 'wc-' . $raw_status ) ? 'wc-' . $raw_status : $raw_status;
|
||||
|
||||
$id = wp_insert_post(
|
||||
apply_filters(
|
||||
'woocommerce_new_order_data',
|
||||
|
@ -65,7 +68,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
|||
'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
|
||||
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
|
||||
'post_type' => $order->get_type( 'edit' ),
|
||||
'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ),
|
||||
'post_status' => $status,
|
||||
'ping_status' => 'closed',
|
||||
'post_author' => 1,
|
||||
'post_title' => $this->get_post_title(),
|
||||
|
@ -73,7 +76,8 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
|||
'post_parent' => $order->get_parent_id( 'edit' ),
|
||||
'post_excerpt' => $this->get_post_excerpt( $order ),
|
||||
)
|
||||
), true
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
if ( $id && ! is_wp_error( $id ) ) {
|
||||
|
@ -119,7 +123,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
|||
* stored. @todo When meta is flattened, handle this during migration.
|
||||
*/
|
||||
if ( version_compare( $order->get_version( 'edit' ), '2.3.7', '<' ) && $order->get_prices_include_tax( 'edit' ) ) {
|
||||
$order->set_discount_total( (double) get_post_meta( $order->get_id(), '_cart_discount', true ) - (double) get_post_meta( $order->get_id(), '_cart_discount_tax', true ) );
|
||||
$order->set_discount_total( (float) get_post_meta( $order->get_id(), '_cart_discount', true ) - (float) get_post_meta( $order->get_id(), '_cart_discount_tax', true ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,10 +144,12 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
|
|||
|
||||
// Only update the post when the post data changes.
|
||||
if ( array_intersect( array( 'date_created', 'date_modified', 'status', 'parent_id', 'post_excerpt' ), array_keys( $changes ) ) ) {
|
||||
$raw_status = $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' );
|
||||
$status = wc_is_order_status( 'wc-' . $raw_status ) ? 'wc-' . $raw_status : $raw_status;
|
||||
$post_data = array(
|
||||
'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ),
|
||||
'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ),
|
||||
'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ),
|
||||
'post_status' => $status,
|
||||
'post_parent' => $order->get_parent_id(),
|
||||
'post_excerpt' => $this->get_post_excerpt( $order ),
|
||||
'post_modified' => isset( $changes['date_modified'] ) ? gmdate( 'Y-m-d H:i:s', $order->get_date_modified( 'edit' )->getOffsetTimestamp() ) : current_time( 'mysql' ),
|
||||
|
|
|
@ -156,10 +156,20 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
|
|||
$order->set_date_paid( $order->get_date_created( 'edit' ) );
|
||||
}
|
||||
|
||||
// Also grab the current status so we can compare.
|
||||
$previous_status = get_post_status( $order->get_id() );
|
||||
|
||||
// Update the order.
|
||||
parent::update( $order );
|
||||
|
||||
do_action( 'woocommerce_update_order', $order->get_id() );
|
||||
// Fire a hook depending on the status - this should be considered a creation if it was previously draft status.
|
||||
$new_status = $order->get_status( 'edit' );
|
||||
|
||||
if ( $new_status !== $previous_status && in_array( $previous_status, array( 'new', 'auto-draft', 'draft' ), true ) ) {
|
||||
do_action( 'woocommerce_new_order', $order->get_id() );
|
||||
} else {
|
||||
do_action( 'woocommerce_update_order', $order->get_id() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -482,8 +492,10 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
|
|||
* @var array
|
||||
*/
|
||||
$search_fields = array_map(
|
||||
'wc_clean', apply_filters(
|
||||
'woocommerce_shop_order_search_fields', array(
|
||||
'wc_clean',
|
||||
apply_filters(
|
||||
'woocommerce_shop_order_search_fields',
|
||||
array(
|
||||
'_billing_address_index',
|
||||
'_shipping_address_index',
|
||||
'_billing_last_name',
|
||||
|
|
|
@ -287,7 +287,7 @@ class WC_Payment_Token_Data_Store extends WC_Data_Store_WP implements WC_Payment
|
|||
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param id $user_id User ID.
|
||||
* @param int $user_id User ID.
|
||||
* @return object
|
||||
*/
|
||||
public function get_users_default_token( $user_id ) {
|
||||
|
|
|
@ -748,6 +748,9 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
if ( taxonomy_exists( $attribute_key ) ) {
|
||||
// Handle attributes that have been unset.
|
||||
wp_set_object_terms( $product->get_id(), array(), $attribute_key );
|
||||
} elseif ( taxonomy_exists( urldecode( $attribute_key ) ) ) {
|
||||
// Handle attributes that have been unset.
|
||||
wp_set_object_terms( $product->get_id(), array(), urldecode( $attribute_key ) );
|
||||
}
|
||||
continue;
|
||||
|
||||
|
@ -1061,20 +1064,11 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
* @return int Matching variation ID or 0.
|
||||
*/
|
||||
public function find_matching_product_variation( $product, $match_attributes = array() ) {
|
||||
$query_args = array(
|
||||
'post_parent' => $product->get_id(),
|
||||
'post_type' => 'product_variation',
|
||||
'orderby' => 'menu_order',
|
||||
'order' => 'ASC',
|
||||
'fields' => 'ids',
|
||||
'post_status' => 'publish',
|
||||
'numberposts' => 1,
|
||||
'meta_query' => array(), // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
|
||||
);
|
||||
global $wpdb;
|
||||
|
||||
// Allow large queries in case user has many variations or attributes.
|
||||
$GLOBALS['wpdb']->query( 'SET SESSION SQL_BIG_SELECTS=1' );
|
||||
$meta_attribute_names = array();
|
||||
|
||||
// Get attributes to match in meta.
|
||||
foreach ( $product->get_attributes() as $attribute ) {
|
||||
if ( ! $attribute->get_variation() ) {
|
||||
continue;
|
||||
|
@ -1086,36 +1080,66 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Note not wc_clean here to prevent removal of entities.
|
||||
$value = $match_attributes[ $attribute_field_name ];
|
||||
|
||||
$query_args['meta_query'][] = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'key' => $attribute_field_name,
|
||||
'value' => array( '', $value ),
|
||||
'compare' => 'IN',
|
||||
),
|
||||
array(
|
||||
'key' => $attribute_field_name,
|
||||
'compare' => 'NOT EXISTS',
|
||||
),
|
||||
);
|
||||
$meta_attribute_names[] = $attribute_field_name;
|
||||
}
|
||||
|
||||
$variations = get_posts( $query_args );
|
||||
// Get the attributes of the variations.
|
||||
$query = $wpdb->prepare(
|
||||
"
|
||||
SELECT post_id, meta_key, meta_value FROM {$wpdb->postmeta}
|
||||
WHERE post_id IN (
|
||||
SELECT ID FROM {$wpdb->posts}
|
||||
WHERE {$wpdb->posts}.post_parent = %d
|
||||
AND {$wpdb->posts}.post_status = 'publish'
|
||||
AND {$wpdb->posts}.post_type = 'product_variation'
|
||||
ORDER BY menu_order ASC, ID ASC
|
||||
)
|
||||
",
|
||||
$product->get_id()
|
||||
);
|
||||
|
||||
if ( $variations && ! is_wp_error( $variations ) ) {
|
||||
return current( $variations );
|
||||
} elseif ( version_compare( get_post_meta( $product->get_id(), '_product_version', true ), '2.4.0', '<' ) ) {
|
||||
$query .= ' AND meta_key IN ( "' . implode( '","', array_map( 'esc_sql', $meta_attribute_names ) ) . '" );';
|
||||
|
||||
$attributes = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
if ( ! $attributes ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$sorted_meta = array();
|
||||
|
||||
foreach ( $attributes as $m ) {
|
||||
$sorted_meta[ $m->post_id ][ $m->meta_key ] = $m->meta_value; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
|
||||
}
|
||||
|
||||
/**
|
||||
* Check each variation to find the one that matches the $match_attributes.
|
||||
*
|
||||
* Note: Not all meta fields will be set which is why we check existance.
|
||||
*/
|
||||
foreach ( $sorted_meta as $variation_id => $variation ) {
|
||||
$match = true;
|
||||
|
||||
foreach ( $match_attributes as $attribute_key => $attribute_value ) {
|
||||
if ( array_key_exists( $attribute_key, $variation ) ) {
|
||||
if ( $variation[ $attribute_key ] !== $attribute_value && ! empty( $variation[ $attribute_key ] ) ) {
|
||||
$match = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( true === $match ) {
|
||||
return $variation_id;
|
||||
}
|
||||
}
|
||||
|
||||
if ( version_compare( get_post_meta( $product->get_id(), '_product_version', true ), '2.4.0', '<' ) ) {
|
||||
/**
|
||||
* Pre 2.4 handling where 'slugs' were saved instead of the full text attribute.
|
||||
* Fallback is here because there are cases where data will be 'synced' but the product version will remain the same.
|
||||
*/
|
||||
return ( array_map( 'sanitize_title', $match_attributes ) === $match_attributes ) ? 0 : $this->find_matching_product_variation( $product, array_map( 'sanitize_title', $match_attributes ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1244,37 +1268,33 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
// Update stock in DB directly.
|
||||
switch ( $operation ) {
|
||||
case 'increase':
|
||||
// phpcs:ignore WordPress.VIP.DirectDatabaseQuery.DirectQuery
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"UPDATE {$wpdb->postmeta} SET meta_value = meta_value + %f WHERE post_id = %d AND meta_key='_stock'",
|
||||
$stock_quantity,
|
||||
$product_id_with_stock
|
||||
)
|
||||
$sql = $wpdb->prepare(
|
||||
"UPDATE {$wpdb->postmeta} SET meta_value = meta_value + %f WHERE post_id = %d AND meta_key='_stock'",
|
||||
$stock_quantity,
|
||||
$product_id_with_stock
|
||||
);
|
||||
break;
|
||||
case 'decrease':
|
||||
// phpcs:ignore WordPress.VIP.DirectDatabaseQuery.DirectQuery
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"UPDATE {$wpdb->postmeta} SET meta_value = meta_value - %f WHERE post_id = %d AND meta_key='_stock'",
|
||||
$stock_quantity,
|
||||
$product_id_with_stock
|
||||
)
|
||||
$sql = $wpdb->prepare(
|
||||
"UPDATE {$wpdb->postmeta} SET meta_value = meta_value - %f WHERE post_id = %d AND meta_key='_stock'",
|
||||
$stock_quantity,
|
||||
$product_id_with_stock
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// phpcs:ignore WordPress.VIP.DirectDatabaseQuery.DirectQuery
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"UPDATE {$wpdb->postmeta} SET meta_value = %f WHERE post_id = %d AND meta_key='_stock'",
|
||||
$stock_quantity,
|
||||
$product_id_with_stock
|
||||
)
|
||||
$sql = $wpdb->prepare(
|
||||
"UPDATE {$wpdb->postmeta} SET meta_value = %f WHERE post_id = %d AND meta_key='_stock'",
|
||||
$stock_quantity,
|
||||
$product_id_with_stock
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
$sql = apply_filters( 'woocommerce_update_product_stock_query', $sql, $product_id_with_stock, $stock_quantity, $operation );
|
||||
|
||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared
|
||||
$wpdb->query( $sql );
|
||||
|
||||
wp_cache_delete( $product_id_with_stock, 'post_meta' );
|
||||
}
|
||||
|
||||
|
@ -1512,15 +1532,27 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
|||
* @return bool|string
|
||||
*/
|
||||
public function get_product_type( $product_id ) {
|
||||
$post_type = get_post_type( $product_id );
|
||||
if ( 'product_variation' === $post_type ) {
|
||||
return 'variation';
|
||||
} elseif ( 'product' === $post_type ) {
|
||||
$terms = get_the_terms( $product_id, 'product_type' );
|
||||
return ! empty( $terms ) ? sanitize_title( current( $terms )->name ) : 'simple';
|
||||
} else {
|
||||
return false;
|
||||
$cache_key = WC_Cache_Helper::get_cache_prefix( 'product_' . $product_id ) . '_type_' . $product_id;
|
||||
$product_type = wp_cache_get( $cache_key, 'products' );
|
||||
|
||||
if ( $product_type ) {
|
||||
return $product_type;
|
||||
}
|
||||
|
||||
$post_type = get_post_type( $product_id );
|
||||
|
||||
if ( 'product_variation' === $post_type ) {
|
||||
$product_type = 'variation';
|
||||
} elseif ( 'product' === $post_type ) {
|
||||
$terms = get_the_terms( $product_id, 'product_type' );
|
||||
$product_type = ! empty( $terms ) ? sanitize_title( current( $terms )->name ) : 'simple';
|
||||
} else {
|
||||
$product_type = false;
|
||||
}
|
||||
|
||||
wp_cache_set( $cache_key, $product_type, 'products' );
|
||||
|
||||
return $product_type;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -59,7 +59,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
$webhook->set_id( $webhook_id );
|
||||
$webhook->apply_changes();
|
||||
|
||||
delete_transient( 'woocommerce_webhook_ids' );
|
||||
$this->delete_transients( $webhook->get_status( 'edit' ) );
|
||||
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
|
||||
do_action( 'woocommerce_new_webhook', $webhook_id );
|
||||
}
|
||||
|
@ -152,6 +152,10 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
|
||||
$webhook->apply_changes();
|
||||
|
||||
if ( isset( $changes['status'] ) ) {
|
||||
// We need to delete all transients, because we can't be sure of the old status.
|
||||
$this->delete_transients( 'all' );
|
||||
}
|
||||
wp_cache_delete( $webhook->get_id(), 'webhooks' );
|
||||
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
|
||||
|
||||
|
@ -179,7 +183,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
array( '%d' )
|
||||
); // WPCS: cache ok, DB call ok.
|
||||
|
||||
delete_transient( 'woocommerce_webhook_ids' );
|
||||
$this->delete_transients( 'all' );
|
||||
WC_Cache_Helper::incr_cache_prefix( 'webhooks' );
|
||||
do_action( 'woocommerce_webhook_deleted', $webhook->get_id(), $webhook );
|
||||
}
|
||||
|
@ -196,21 +200,29 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all webhooks IDs.
|
||||
* Get webhooks IDs from the database.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @throws InvalidArgumentException If a $status value is passed in that is not in the known wc_get_webhook_statuses() keys.
|
||||
* @param string $status Optional - status to filter results by. Must be a key in return value of @see wc_get_webhook_statuses(). @since 3.6.0.
|
||||
* @return int[]
|
||||
*/
|
||||
public function get_webhooks_ids() {
|
||||
global $wpdb;
|
||||
public function get_webhooks_ids( $status = '' ) {
|
||||
if ( ! empty( $status ) ) {
|
||||
$this->validate_status( $status );
|
||||
}
|
||||
|
||||
$ids = get_transient( 'woocommerce_webhook_ids' );
|
||||
$ids = get_transient( $this->get_transient_key( $status ) );
|
||||
|
||||
if ( false === $ids ) {
|
||||
$results = $wpdb->get_results( "SELECT webhook_id FROM {$wpdb->prefix}wc_webhooks" ); // WPCS: cache ok, DB call ok.
|
||||
$ids = array_map( 'intval', wp_list_pluck( $results, 'webhook_id' ) );
|
||||
|
||||
set_transient( 'woocommerce_webhook_ids', $ids );
|
||||
$ids = $this->search_webhooks(
|
||||
array(
|
||||
'limit' => -1,
|
||||
'status' => $status,
|
||||
)
|
||||
);
|
||||
$ids = array_map( 'absint', $ids );
|
||||
set_transient( $this->get_transient_key( $status ), $ids );
|
||||
}
|
||||
|
||||
return $ids;
|
||||
|
@ -220,7 +232,7 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
* Search webhooks.
|
||||
*
|
||||
* @param array $args Search arguments.
|
||||
* @return array
|
||||
* @return array|object
|
||||
*/
|
||||
public function search_webhooks( $args ) {
|
||||
global $wpdb;
|
||||
|
@ -228,10 +240,11 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'limit' => 10,
|
||||
'offset' => 0,
|
||||
'order' => 'DESC',
|
||||
'orderby' => 'id',
|
||||
'limit' => 10,
|
||||
'offset' => 0,
|
||||
'order' => 'DESC',
|
||||
'orderby' => 'id',
|
||||
'paginate' => false,
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -258,15 +271,15 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
'post_modified' => 'date_modified_gmt',
|
||||
);
|
||||
$orderby = isset( $orderby_mapping[ $args['orderby'] ] ) ? $orderby_mapping[ $args['orderby'] ] : 'webhook_id';
|
||||
|
||||
$limit = -1 < $args['limit'] ? sprintf( 'LIMIT %d', $args['limit'] ) : '';
|
||||
$offset = 0 < $args['offset'] ? sprintf( 'OFFSET %d', $args['offset'] ) : '';
|
||||
$status = ! empty( $args['status'] ) ? "AND `status` = '" . sanitize_key( isset( $statuses[ $args['status'] ] ) ? $statuses[ $args['status'] ] : $args['status'] ) . "'" : '';
|
||||
$search = ! empty( $args['search'] ) ? "AND `name` LIKE '%" . $wpdb->esc_like( sanitize_text_field( $args['search'] ) ) . "%'" : '';
|
||||
$include = '';
|
||||
$exclude = '';
|
||||
$date_created = '';
|
||||
$date_modified = '';
|
||||
$order = "ORDER BY {$orderby} " . esc_sql( strtoupper( $args['order'] ) );
|
||||
$limit = -1 < $args['limit'] ? $wpdb->prepare( 'LIMIT %d', $args['limit'] ) : '';
|
||||
$offset = 0 < $args['offset'] ? $wpdb->prepare( 'OFFSET %d', $args['offset'] ) : '';
|
||||
$status = ! empty( $args['status'] ) ? $wpdb->prepare( 'AND `status` = %s', isset( $statuses[ $args['status'] ] ) ? $statuses[ $args['status'] ] : $args['status'] ) : '';
|
||||
$search = ! empty( $args['search'] ) ? "AND `name` LIKE '%" . $wpdb->esc_like( sanitize_text_field( $args['search'] ) ) . "%'" : '';
|
||||
$include = '';
|
||||
$exclude = '';
|
||||
$date_created = '';
|
||||
$date_modified = '';
|
||||
|
||||
if ( ! empty( $args['include'] ) ) {
|
||||
$args['include'] = implode( ',', wp_parse_id_list( $args['include'] ) );
|
||||
|
@ -282,47 +295,91 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
$args['after'] = empty( $args['after'] ) ? '0000-00-00' : $args['after'];
|
||||
$args['before'] = empty( $args['before'] ) ? current_time( 'mysql', 1 ) : $args['before'];
|
||||
|
||||
$date_created = "AND `date_created_gmt` BETWEEN STR_TO_DATE('" . $args['after'] . "', '%Y-%m-%d %H:%i:%s') and STR_TO_DATE('" . $args['before'] . "', '%Y-%m-%d %H:%i:%s')";
|
||||
$date_created = "AND `date_created_gmt` BETWEEN STR_TO_DATE('" . esc_sql( $args['after'] ) . "', '%Y-%m-%d %H:%i:%s') and STR_TO_DATE('" . esc_sql( $args['before'] ) . "', '%Y-%m-%d %H:%i:%s')";
|
||||
}
|
||||
|
||||
if ( ! empty( $args['modified_after'] ) || ! empty( $args['modified_before'] ) ) {
|
||||
$args['modified_after'] = empty( $args['modified_after'] ) ? '0000-00-00' : $args['modified_after'];
|
||||
$args['modified_before'] = empty( $args['modified_before'] ) ? current_time( 'mysql', 1 ) : $args['modified_before'];
|
||||
|
||||
$date_modified = "AND `date_modified_gmt` BETWEEN STR_TO_DATE('" . $args['modified_after'] . "', '%Y-%m-%d %H:%i:%s') and STR_TO_DATE('" . $args['modified_before'] . "', '%Y-%m-%d %H:%i:%s')";
|
||||
$date_modified = "AND `date_modified_gmt` BETWEEN STR_TO_DATE('" . esc_sql( $args['modified_after'] ) . "', '%Y-%m-%d %H:%i:%s') and STR_TO_DATE('" . esc_sql( $args['modified_before'] ) . "', '%Y-%m-%d %H:%i:%s')";
|
||||
}
|
||||
|
||||
$order = "ORDER BY {$orderby} " . strtoupper( sanitize_key( $args['order'] ) );
|
||||
|
||||
// Check for cache.
|
||||
$cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'search_webhooks' . md5( implode( ',', $args ) );
|
||||
$ids = wp_cache_get( $cache_key, 'webhook_search_results' );
|
||||
$cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'search_webhooks' . md5( implode( ',', $args ) );
|
||||
$cache_value = wp_cache_get( $cache_key, 'webhook_search_results' );
|
||||
|
||||
if ( false !== $ids ) {
|
||||
return $ids;
|
||||
if ( $cache_value ) {
|
||||
return $cache_value;
|
||||
}
|
||||
|
||||
$query = trim(
|
||||
"SELECT webhook_id
|
||||
FROM {$wpdb->prefix}wc_webhooks
|
||||
WHERE 1=1
|
||||
{$status}
|
||||
{$search}
|
||||
{$include}
|
||||
{$exclude}
|
||||
{$date_created}
|
||||
{$date_modified}
|
||||
{$order}
|
||||
{$limit}
|
||||
{$offset}"
|
||||
);
|
||||
if ( $args['paginate'] ) {
|
||||
$query = trim(
|
||||
"SELECT SQL_CALC_FOUND_ROWS webhook_id
|
||||
FROM {$wpdb->prefix}wc_webhooks
|
||||
WHERE 1=1
|
||||
{$status}
|
||||
{$search}
|
||||
{$include}
|
||||
{$exclude}
|
||||
{$date_created}
|
||||
{$date_modified}
|
||||
{$order}
|
||||
{$limit}
|
||||
{$offset}"
|
||||
);
|
||||
|
||||
$results = $wpdb->get_results( $query ); // WPCS: cache ok, DB call ok, unprepared SQL ok.
|
||||
$webhook_ids = wp_parse_id_list( $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
$total = (int) $wpdb->get_var( 'SELECT FOUND_ROWS();' );
|
||||
$return_value = (object) array(
|
||||
'webhooks' => $webhook_ids,
|
||||
'total' => $total,
|
||||
'max_num_pages' => $args['limit'] > 1 ? ceil( $total / $args['limit'] ) : 1,
|
||||
);
|
||||
} else {
|
||||
$query = trim(
|
||||
"SELECT webhook_id
|
||||
FROM {$wpdb->prefix}wc_webhooks
|
||||
WHERE 1=1
|
||||
{$status}
|
||||
{$search}
|
||||
{$include}
|
||||
{$exclude}
|
||||
{$date_created}
|
||||
{$date_modified}
|
||||
{$order}
|
||||
{$limit}
|
||||
{$offset}"
|
||||
);
|
||||
|
||||
$ids = wp_list_pluck( $results, 'webhook_id' );
|
||||
wp_cache_set( $cache_key, $ids, 'webhook_search_results' );
|
||||
$webhook_ids = wp_parse_id_list( $wpdb->get_col( $query ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
$return_value = $webhook_ids;
|
||||
}
|
||||
|
||||
return $ids;
|
||||
wp_cache_set( $cache_key, $return_value, 'webhook_search_results' );
|
||||
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count webhooks.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param string $status Status to count.
|
||||
* @return int
|
||||
*/
|
||||
protected function get_webhook_count( $status = 'active' ) {
|
||||
global $wpdb;
|
||||
|
||||
$count = wp_cache_get( $status . '_count', 'webhooks' );
|
||||
|
||||
if ( false === $count ) {
|
||||
$count = absint( $wpdb->get_var( $wpdb->prepare( "SELECT count( webhook_id ) FROM {$wpdb->prefix}wc_webhooks WHERE `status` = %s;", $status ) ) );
|
||||
|
||||
wp_cache_add( $status . '_count', $count, 'webhooks' );
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -335,18 +392,55 @@ class WC_Webhook_Data_Store implements WC_Webhook_Data_Store_Interface {
|
|||
$counts = array();
|
||||
|
||||
foreach ( $statuses as $status ) {
|
||||
$count = count(
|
||||
$this->search_webhooks(
|
||||
array(
|
||||
'limit' => -1,
|
||||
'status' => $status,
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$counts[ $status ] = $count;
|
||||
$counts[ $status ] = $this->get_webhook_count( $status );
|
||||
}
|
||||
|
||||
return $counts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given string is in known statuses, based on return value of @see wc_get_webhook_statuses().
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @throws InvalidArgumentException If $status is not empty and not in the known wc_get_webhook_statuses() keys.
|
||||
* @param string $status Status to check.
|
||||
*/
|
||||
private function validate_status( $status ) {
|
||||
if ( ! array_key_exists( $status, wc_get_webhook_statuses() ) ) {
|
||||
throw new InvalidArgumentException( sprintf( 'Invalid status given: %s. Status must be one of: %s.', $status, implode( ', ', array_keys( wc_get_webhook_statuses() ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transient key used to cache a set of webhook IDs, optionally filtered by status.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param string $status Optional - status of cache key.
|
||||
* @return string
|
||||
*/
|
||||
private function get_transient_key( $status = '' ) {
|
||||
return empty( $status ) ? 'woocommerce_webhook_ids' : sprintf( 'woocommerce_webhook_ids_status_%s', $status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the transients used to cache a set of webhook IDs, optionally filtered by status.
|
||||
*
|
||||
* @since 3.6.0
|
||||
* @param string $status Optional - status of cache to delete, or 'all' to delete all caches.
|
||||
*/
|
||||
private function delete_transients( $status = '' ) {
|
||||
|
||||
// Always delete the non-filtered cache.
|
||||
delete_transient( $this->get_transient_key( '' ) );
|
||||
|
||||
if ( ! empty( $status ) ) {
|
||||
if ( 'all' === $status ) {
|
||||
foreach ( wc_get_webhook_statuses() as $status_key => $status_string ) {
|
||||
delete_transient( $this->get_transient_key( $status_key ) );
|
||||
}
|
||||
} else {
|
||||
delete_transient( $this->get_transient_key( $status ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,12 +201,11 @@ class WC_Gateway_Paypal_IPN_Handler extends WC_Gateway_Paypal_Response {
|
|||
$this->payment_status_paid_cancelled_order( $order, $posted );
|
||||
}
|
||||
|
||||
$this->payment_complete( $order, ( ! empty( $posted['txn_id'] ) ? wc_clean( $posted['txn_id'] ) : '' ), __( 'IPN payment completed', 'woocommerce' ) );
|
||||
|
||||
if ( ! empty( $posted['mc_fee'] ) ) {
|
||||
// Log paypal transaction fee.
|
||||
update_post_meta( $order->get_id(), 'PayPal Transaction Fee', wc_clean( $posted['mc_fee'] ) );
|
||||
$order->add_meta_data( 'PayPal Transaction Fee', wc_clean( $posted['mc_fee'] ) );
|
||||
}
|
||||
|
||||
$this->payment_complete( $order, ( ! empty( $posted['txn_id'] ) ? wc_clean( $posted['txn_id'] ) : '' ), __( 'IPN payment completed', 'woocommerce' ) );
|
||||
} else {
|
||||
if ( 'authorization' === $posted['pending_reason'] ) {
|
||||
$this->payment_on_hold( $order, __( 'Payment authorized. Change payment status to processing or complete to capture funds.', 'woocommerce' ) );
|
||||
|
|
|
@ -89,7 +89,7 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
|
|||
|
||||
$order_id = wc_clean( wp_unslash( $_REQUEST['cm'] ) ); // WPCS: input var ok, CSRF ok, sanitization ok.
|
||||
$status = wc_clean( strtolower( wp_unslash( $_REQUEST['st'] ) ) ); // WPCS: input var ok, CSRF ok, sanitization ok.
|
||||
$amount = wc_clean( wp_unslash( $_REQUEST['amt'] ) ); // WPCS: input var ok, CSRF ok, sanitization ok.
|
||||
$amount = isset( $_REQUEST['amt'] ) ? wc_clean( wp_unslash( $_REQUEST['amt'] ) ) : 0; // WPCS: input var ok, CSRF ok, sanitization ok.
|
||||
$transaction = wc_clean( wp_unslash( $_REQUEST['tx'] ) ); // WPCS: input var ok, CSRF ok, sanitization ok.
|
||||
$order = $this->get_paypal_order( $order_id );
|
||||
|
||||
|
@ -102,8 +102,8 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
|
|||
if ( $transaction_result ) {
|
||||
WC_Gateway_Paypal::log( 'PDT Transaction Status: ' . wc_print_r( $status, true ) );
|
||||
|
||||
update_post_meta( $order->get_id(), '_paypal_status', $status );
|
||||
update_post_meta( $order->get_id(), '_transaction_id', $transaction );
|
||||
$order->add_meta_data( '_paypal_status', $status );
|
||||
$order->set_transaction_id( $transaction );
|
||||
|
||||
if ( 'completed' === $status ) {
|
||||
if ( number_format( $order->get_total(), 2, '.', '' ) !== number_format( $amount, 2, '.', '' ) ) {
|
||||
|
@ -111,15 +111,15 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
|
|||
/* translators: 1: Payment amount */
|
||||
$this->payment_on_hold( $order, sprintf( __( 'Validation error: PayPal amounts do not match (amt %s).', 'woocommerce' ), $amount ) );
|
||||
} else {
|
||||
$this->payment_complete( $order, $transaction, __( 'PDT payment completed', 'woocommerce' ) );
|
||||
|
||||
// Log paypal transaction fee and payment type.
|
||||
if ( ! empty( $transaction_result['mc_fee'] ) ) {
|
||||
update_post_meta( $order->get_id(), 'PayPal Transaction Fee', $transaction_result['mc_fee'] );
|
||||
$order->add_meta_data( 'PayPal Transaction Fee', wc_clean( $transaction_result['mc_fee'] ) );
|
||||
}
|
||||
if ( ! empty( $transaction_result['payment_type'] ) ) {
|
||||
update_post_meta( $order->get_id(), 'Payment type', $transaction_result['payment_type'] );
|
||||
$order->add_meta_data( 'Payment type', wc_clean( $transaction_result['payment_type'] ) );
|
||||
}
|
||||
|
||||
$this->payment_complete( $order, $transaction, __( 'PDT payment completed', 'woocommerce' ) );
|
||||
}
|
||||
} else {
|
||||
if ( 'authorization' === $transaction_result['pending_reason'] ) {
|
||||
|
|
|
@ -61,9 +61,12 @@ class WC_Gateway_Paypal_Request {
|
|||
* @return string
|
||||
*/
|
||||
public function get_request_url( $order, $sandbox = false ) {
|
||||
$this->endpoint = $sandbox ? 'https://www.sandbox.paypal.com/cgi-bin/webscr?test_ipn=1&' : 'https://www.paypal.com/cgi-bin/webscr?';
|
||||
$paypal_args = $this->get_paypal_args( $order );
|
||||
$mask = array(
|
||||
$this->endpoint = $sandbox ? 'https://www.sandbox.paypal.com/cgi-bin/webscr?test_ipn=1&' : 'https://www.paypal.com/cgi-bin/webscr?';
|
||||
$paypal_args = $this->get_paypal_args( $order );
|
||||
$paypal_args['bn'] = 'WooThemes_Cart'; // Append WooCommerce PayPal Partner Attribution ID. This should not be overridden for this gateway.
|
||||
|
||||
// Mask (remove) PII from the logs.
|
||||
$mask = array(
|
||||
'first_name' => '***',
|
||||
'last_name' => '***',
|
||||
'address1' => '***',
|
||||
|
@ -91,12 +94,15 @@ class WC_Gateway_Paypal_Request {
|
|||
* @return string
|
||||
*/
|
||||
protected function limit_length( $string, $limit = 127 ) {
|
||||
// As the output is to be used in http_build_query which applies URL encoding, the string needs to be
|
||||
// cut as if it was URL-encoded, but returned non-encoded (it will be encoded by http_build_query later).
|
||||
$url_encoded_str = rawurlencode( $string );
|
||||
|
||||
if ( strlen( $url_encoded_str ) > $limit ) {
|
||||
$string = rawurldecode( substr( $url_encoded_str, 0, $limit - 3 ) . '...' );
|
||||
$str_limit = $limit - 3;
|
||||
if ( function_exists( 'mb_strimwidth' ) ) {
|
||||
if ( mb_strlen( $string ) > $limit ) {
|
||||
$string = mb_strimwidth( $string, 0, $str_limit ) . '...';
|
||||
}
|
||||
} else {
|
||||
if ( strlen( $string ) > $limit ) {
|
||||
$string = substr( $string, 0, $str_limit ) . '...';
|
||||
}
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
@ -122,7 +128,6 @@ class WC_Gateway_Paypal_Request {
|
|||
'page_style' => $this->gateway->get_option( 'page_style' ),
|
||||
'image_url' => esc_url_raw( $this->gateway->get_option( 'image_url' ) ),
|
||||
'paymentaction' => $this->gateway->get_option( 'paymentaction' ),
|
||||
'bn' => 'WooThemes_Cart',
|
||||
'invoice' => $this->limit_length( $this->gateway->get_option( 'invoice_prefix' ) . $order->get_order_number(), 127 ),
|
||||
'custom' => wp_json_encode(
|
||||
array(
|
||||
|
@ -167,10 +172,12 @@ class WC_Gateway_Paypal_Request {
|
|||
}
|
||||
|
||||
return apply_filters(
|
||||
'woocommerce_paypal_args', array_merge(
|
||||
'woocommerce_paypal_args',
|
||||
array_merge(
|
||||
$this->get_transaction_args( $order ),
|
||||
$this->get_line_item_args( $order, true )
|
||||
), $order
|
||||
),
|
||||
$order
|
||||
);
|
||||
|
||||
}
|
||||
|
@ -184,11 +191,19 @@ class WC_Gateway_Paypal_Request {
|
|||
protected function get_paypal_args( $order ) {
|
||||
WC_Gateway_Paypal::log( 'Generating payment form for order ' . $order->get_order_number() . '. Notify URL: ' . $this->notify_url );
|
||||
|
||||
$force_one_line_item = apply_filters( 'woocommerce_paypal_force_one_line_item', false, $order );
|
||||
|
||||
if ( ( wc_tax_enabled() && wc_prices_include_tax() ) || ! $this->line_items_valid( $order ) ) {
|
||||
$force_one_line_item = true;
|
||||
}
|
||||
|
||||
$paypal_args = apply_filters(
|
||||
'woocommerce_paypal_args', array_merge(
|
||||
'woocommerce_paypal_args',
|
||||
array_merge(
|
||||
$this->get_transaction_args( $order ),
|
||||
$this->get_line_item_args( $order )
|
||||
), $order
|
||||
$this->get_line_item_args( $order, $force_one_line_item )
|
||||
),
|
||||
$order
|
||||
);
|
||||
|
||||
return $this->fix_request_length( $order, $paypal_args );
|
||||
|
@ -300,11 +315,8 @@ class WC_Gateway_Paypal_Request {
|
|||
* @return array
|
||||
*/
|
||||
protected function get_line_item_args( $order, $force_one_line_item = false ) {
|
||||
if ( wc_tax_enabled() && wc_prices_include_tax() || ! $this->line_items_valid( $order ) ) {
|
||||
$force_one_line_item = true;
|
||||
}
|
||||
|
||||
$line_item_args = array();
|
||||
|
||||
if ( $force_one_line_item ) {
|
||||
/**
|
||||
* Send order as a single item.
|
||||
|
@ -342,9 +354,10 @@ class WC_Gateway_Paypal_Request {
|
|||
|
||||
foreach ( $order->get_items() as $item ) {
|
||||
$item_name = $item->get_name();
|
||||
$item_meta = strip_tags(
|
||||
$item_meta = wp_strip_all_tags(
|
||||
wc_display_item_meta(
|
||||
$item, array(
|
||||
$item,
|
||||
array(
|
||||
'before' => '',
|
||||
'separator' => ', ',
|
||||
'after' => '',
|
||||
|
@ -373,9 +386,10 @@ class WC_Gateway_Paypal_Request {
|
|||
*/
|
||||
protected function get_order_item_name( $order, $item ) {
|
||||
$item_name = $item->get_name();
|
||||
$item_meta = strip_tags(
|
||||
$item_meta = wp_strip_all_tags(
|
||||
wc_display_item_meta(
|
||||
$item, array(
|
||||
$item,
|
||||
array(
|
||||
'before' => '',
|
||||
'separator' => ', ',
|
||||
'after' => '',
|
||||
|
@ -447,12 +461,12 @@ class WC_Gateway_Paypal_Request {
|
|||
// Products.
|
||||
foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item ) {
|
||||
if ( 'fee' === $item['type'] ) {
|
||||
$item_line_total = $this->number_format( $item['line_total'], $order );
|
||||
$item_line_total = $this->number_format( $item['line_total'], $order );
|
||||
$this->add_line_item( $item->get_name(), 1, $item_line_total );
|
||||
} else {
|
||||
$product = $item->get_product();
|
||||
$sku = $product ? $product->get_sku() : '';
|
||||
$item_line_total = $this->number_format( $order->get_item_subtotal( $item, false ), $order );
|
||||
$product = $item->get_product();
|
||||
$sku = $product ? $product->get_sku() : '';
|
||||
$item_line_total = $this->number_format( $order->get_item_subtotal( $item, false ), $order );
|
||||
$this->add_line_item( $this->get_order_item_name( $order, $item ), $item->get_quantity(), $item_line_total, $sku );
|
||||
}
|
||||
}
|
||||
|
@ -470,12 +484,17 @@ class WC_Gateway_Paypal_Request {
|
|||
$index = ( count( $this->line_items ) / 4 ) + 1;
|
||||
|
||||
$item = apply_filters(
|
||||
'woocommerce_paypal_line_item', array(
|
||||
'woocommerce_paypal_line_item',
|
||||
array(
|
||||
'item_name' => html_entity_decode( wc_trim_string( $item_name ? $item_name : __( 'Item', 'woocommerce' ), 127 ), ENT_NOQUOTES, 'UTF-8' ),
|
||||
'quantity' => (int) $quantity,
|
||||
'amount' => wc_float_to_string( (float) $amount ),
|
||||
'item_number' => $item_number,
|
||||
), $item_name, $quantity, $amount, $item_number
|
||||
),
|
||||
$item_name,
|
||||
$quantity,
|
||||
$amount,
|
||||
$item_number
|
||||
);
|
||||
|
||||
$this->line_items[ 'item_name_' . $index ] = $this->limit_length( $item['item_name'], 127 );
|
||||
|
|