Skip to content

Commit ce971ce

Browse files
authored
Merge pull request #3740 from craftcms/5.3
5.3
2 parents d3a69de + 33a4ecd commit ce971ce

File tree

160 files changed

+3495
-905
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

160 files changed

+3495
-905
lines changed

CHANGELOG.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,61 @@
11
# Release Notes for Craft Commerce
22

3+
## Unreleased
4+
5+
### Store Management
6+
- Archived gateways are now listed on the Gateways index page. ([#3839](https://github.com/craftcms/commerce/issues/3839))
7+
- Added card view designers for products and variants. ([#3809](https://github.com/craftcms/commerce/pull/3809))
8+
- Order conditions can now have “Coupon Code” and “Payment Gateway” rules. ([#3776](https://github.com/craftcms/commerce/discussions/3776), [#3722](https://github.com/craftcms/commerce/discussions/3722))
9+
- Product variant conditions can now have a “Product” rule.
10+
- Tax rates now have statuses. ([#3790](https://github.com/craftcms/commerce/discussions/3790))
11+
- It’s now possible to restore soft-deleted product variants.
12+
- Improved Craft Commerce navigation and breadcrumb labels.
13+
14+
### Administration
15+
- The “Recipient”, “BCC’d Recipient”, and “CC’d Recipient” email settings now support being set to environment variables. ([#3738](https://github.com/craftcms/commerce/issues/3738))
16+
- It’s now possible to view (but not edit) system and plugin settings on environments where `allowAdminChanges` is disabled.
17+
18+
### Development
19+
- Added the `couponCode` order query param.
20+
- Orders’ `makePrimaryShippingAddress` and `makePrimaryBillingAddress` property values now persist during checkout.
21+
- The `commerce/update-cart` action now includes an `originalCart` key in JSON responses. ([#430](https://github.com/craftcms/commerce/issues/430))
22+
23+
### Extensibility
24+
- Added support for registering custom tax ID validators.
25+
- Added `craft\commerce\base\InventoryItemTrait`.
26+
- Added `craft\commerce\base\InventoryItemTrait`.
27+
- Added `craft\commerce\base\InventoryLocationTrait`.
28+
- Added `craft\commerce\base\InventoryLocationTrait`.
29+
- Added `craft\commerce\base\Purchasable::hasInventory()`.
30+
- Added `craft\commerce\base\Purchasable::loadSales()`.
31+
- Added `craft\commerce\base\TaxIdValidatorInterface`.
32+
- Added `craft\commerce\controllers\BaseStoreManagementController::getStoreSwitch()`.
33+
- Added `craft\commerce\elements\Purchasable::$allowOutOfStockPurchases`.
34+
- Added `craft\commerce\elements\Purchasable::getIsOutOfStockPurchasingAllowed()`.
35+
- Added `craft\commerce\elements\conditions\orders\CouponCodeConditionRule`.
36+
- Added `craft\commerce\elements\conditions\variants\ProductConditionRule`.
37+
- Added `craft\commerce\elements\db\OrderQuery::$couponCode`.
38+
- Added `craft\commerce\elements\db\OrderQuery::couponCode()`.
39+
- Added `craft\commerce\events\CartPurgeEvent`.
40+
- Added `craft\commerce\events\PurchasableOutOfStockPurchasesAllowedEvent`.
41+
- Added `craft\commerce\services\Gateways\getAllArchivedGateways()`.
42+
- Added `craft\commerce\services\Inventory::updateInventoryLevel()`.
43+
- Added `craft\commerce\services\Inventory::updateInventoryLevel()`.
44+
- Added `craft\commerce\services\Inventory::updatePurchasableInventoryLevel()`.
45+
- Added `craft\commerce\services\Inventory::updatePurchasableInventoryLevel()`.
46+
- Added `craft\commerce\services\Purchasables::EVENT_PURCHASABLE_OUT_OF_STOCK_PURCHASES_ALLOWED`.
47+
- Added `craft\commerce\services\Purchasables::isPurchasableOutOfStockPurchasingAllowed()`.
48+
- Added `craft\commerce\services\Taxes::EVENT_REGISTER_TAX_ID_VALIDATORS`.
49+
- Added `craft\commerce\services\Taxes::getEnabledTaxIdValidators()`.
50+
- Added `craft\commerce\services\Taxes::getTaxIdValidators()`.
51+
- Added `craft\commerce\taxidvalidators\EuVatIdValidator`.
52+
53+
### System
54+
- Craft Commerce now requires Craft CMS 5.6.0 or later.
55+
- Fixed a bug where orders’ promotional prices could be calculated incorrectly when using sales.
56+
- Fixed a bug where the `commerce/cart/update-cart` action wasn’t respecting `makePrimaryShippingAddress` and `makePrimaryBillingAddress` params for newly-created addresses. ([#3864](https://github.com/craftcms/commerce/pull/3864))
57+
- Fixed a PHP error that could occur when viewing discounts. ([#3844](https://github.com/craftcms/commerce/issues/3844))
58+
359
## 5.2.12.1 - 2025-01-23
460

561
- Fixed a JavaScript error that occurred when updating an order’s status for a non-primary store on order indexes.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"prefer-stable": true,
2323
"require": {
2424
"php": "^8.2",
25-
"craftcms/cms": "^5.2.0",
25+
"craftcms/cms": "^5.6.0",
2626
"dompdf/dompdf": "^2.0.2",
2727
"ibericode/vat": "^1.2.2",
2828
"iio/libmergepdf": "^4.0",

composer.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example-templates/dist/shop/_private/address/fields.twig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,11 @@ Outputs address form fields for editing an address.
199199
<hr class="my-2">
200200
<div class="my-2">
201201
{{ hiddenInput('isPrimaryBilling', 0) }}
202-
<label>{{ input('checkbox', 'isPrimaryBilling', 1, { checked: address.isPrimaryBilling }) }} {{ 'Use as the primary billing address'|t('commerce') }}</label>
202+
<label>{{ input('checkbox', 'isPrimaryBilling', 1, { checked: address.isPrimaryBilling }) }} {{ 'Use as the primary billing address'|t }}</label>
203203
</div>
204204
<div class="my-2">
205205
{{ hiddenInput('isPrimaryShipping', 0) }}
206-
<label>{{ input('checkbox', 'isPrimaryShipping', 1, { checked: address.isPrimaryShipping }) }} {{ 'Use as the primary shipping address'|t('commerce') }}</label>
206+
<label>{{ input('checkbox', 'isPrimaryShipping', 1, { checked: address.isPrimaryShipping }) }} {{ 'Use as the primary shipping address'|t }}</label>
207207
</div>
208208
{% endif %}
209209
</div>
@@ -251,4 +251,4 @@ document.querySelector('select#{{ 'countryCode'|namespaceInputId(addressName) }}
251251
});
252252

253253
document.querySelector('select#{{ 'countryCode'|namespaceInputId(addressName) }}').dispatchEvent(new Event('change'));
254-
{% endjs %}
254+
{% endjs %}

example-templates/dist/shop/checkout/_paymentLegacyStripeExample.twig

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@
8888

8989
<button id="submit-button" type="submit">Submit Payment</button>
9090

91-
92-
93-
94-
{# Force in some basic styling for the gateway-provided form markup (better to build your own form markup!) #}
95-
{% include 'shop/checkout/_includes/base-payment-form-styles' %}
96-
9791
{% if cart.gateway.supportsPaymentSources() and currentUser %}
9892
<div class="checkbox">
9993
<label>

example-templates/dist/shop/checkout/addresses.twig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ Outputs a form for collecting an order’s shipping and billing address.
4444
}) }}
4545

4646
{% if currentUser and addresses|length %}
47+
{{ hiddenInput('makePrimaryShippingAddress', 0) }}
4748
<div class="mt-3">
4849
<label>
4950
{{ input('checkbox', 'makePrimaryShippingAddress', 1, {
5051
id: 'makePrimaryShippingAddress',
52+
checked: cart.makePrimaryShippingAddress
5153
}) }}
5254
{{ 'Make this my default shipping address'|t }}
5355
</label>
@@ -79,10 +81,12 @@ Outputs a form for collecting an order’s shipping and billing address.
7981
</div>
8082

8183
{% if currentUser and addresses|length %}
84+
{{ hiddenInput('makePrimaryBillingAddress', 0) }}
8285
<div class="mt-3">
8386
<label>
8487
{{ input('checkbox', 'makePrimaryBillingAddress', 1, {
8588
id: 'makePrimaryBillingAddress',
89+
checked: cart.makePrimaryBillingAddress,
8690
}) }}
8791
{{ 'Make this my default billing address'|t }}
8892
</label>

example-templates/dist/shop/products/_includes/grid.twig

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,16 @@
5050
checked: loop.first,
5151
class: not variant.getIsAvailable() ? 'opacity-10' : '',
5252
disabled: not variant.availableForPurchase,
53-
}) }}<span class="pl-1">{{ variant.sku }} {% if variant.inventoryTracked %}({{ variant.stock ? variant.stock ~ ' available' : 'out of stock'}}){% endif %}</span><span class="ml-auto">{% if variant.onPromotion %} <del class="text-gray-400 text-xs">{{ variant.price|currency(cart.currency) }}</del>{% endif %} {{ variant.salePrice|currency(cart.currency) }}</span>
53+
}) }}
54+
<span class="pl-1">{{ variant.sku }}
55+
{% if variant.hasInventory and variant.inventoryTracked %}
56+
({{ variant.stock ? variant.stock ~ ' available' : 'out of stock'}})
57+
{% if variant.allowOutOfStockPurchases %}
58+
<span class="text-xs text-gray-400">{{ "Continue selling when out of stock."|t }}</span>
59+
{% endif %}
60+
{% endif %}
61+
</span>
62+
<span class="ml-auto">{% if variant.onPromotion %} <del class="text-gray-400 text-xs">{{ variant.price|currency(cart.currency) }}</del>{% endif %} {{ variant.salePrice|currency(cart.currency) }}</span>
5463
</label>
5564
{% endfor %}
5665
</div>

example-templates/src/shop/_private/address/fields.twig

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,11 +199,11 @@ Outputs address form fields for editing an address.
199199
<hr class="my-2">
200200
<div class="my-2">
201201
{{ hiddenInput('isPrimaryBilling', 0) }}
202-
<label>{{ input('checkbox', 'isPrimaryBilling', 1, { checked: address.isPrimaryBilling }) }} {{ 'Use as the primary billing address'|t('commerce') }}</label>
202+
<label>{{ input('checkbox', 'isPrimaryBilling', 1, { checked: address.isPrimaryBilling }) }} {{ 'Use as the primary billing address'|t }}</label>
203203
</div>
204204
<div class="my-2">
205205
{{ hiddenInput('isPrimaryShipping', 0) }}
206-
<label>{{ input('checkbox', 'isPrimaryShipping', 1, { checked: address.isPrimaryShipping }) }} {{ 'Use as the primary shipping address'|t('commerce') }}</label>
206+
<label>{{ input('checkbox', 'isPrimaryShipping', 1, { checked: address.isPrimaryShipping }) }} {{ 'Use as the primary shipping address'|t }}</label>
207207
</div>
208208
{% endif %}
209209
</div>
@@ -251,4 +251,4 @@ document.querySelector('select#{{ 'countryCode'|namespaceInputId(addressName) }}
251251
});
252252

253253
document.querySelector('select#{{ 'countryCode'|namespaceInputId(addressName) }}').dispatchEvent(new Event('change'));
254-
{% endjs %}
254+
{% endjs %}

example-templates/src/shop/checkout/_paymentLegacyStripeExample.twig

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,6 @@
8888

8989
<button id="submit-button" type="submit">Submit Payment</button>
9090

91-
92-
93-
94-
{# Force in some basic styling for the gateway-provided form markup (better to build your own form markup!) #}
95-
{% include '[[folderName]]/checkout/_includes/base-payment-form-styles' %}
96-
9791
{% if cart.gateway.supportsPaymentSources() and currentUser %}
9892
<div class="checkbox">
9993
<label>

example-templates/src/shop/checkout/addresses.twig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,12 @@ Outputs a form for collecting an order’s shipping and billing address.
4444
}) }}
4545

4646
{% if currentUser and addresses|length %}
47+
{{ hiddenInput('makePrimaryShippingAddress', 0) }}
4748
<div class="mt-3">
4849
<label>
4950
{{ input('checkbox', 'makePrimaryShippingAddress', 1, {
5051
id: 'makePrimaryShippingAddress',
52+
checked: cart.makePrimaryShippingAddress
5153
}) }}
5254
{{ 'Make this my default shipping address'|t }}
5355
</label>
@@ -79,10 +81,12 @@ Outputs a form for collecting an order’s shipping and billing address.
7981
</div>
8082

8183
{% if currentUser and addresses|length %}
84+
{{ hiddenInput('makePrimaryBillingAddress', 0) }}
8285
<div class="mt-3">
8386
<label>
8487
{{ input('checkbox', 'makePrimaryBillingAddress', 1, {
8588
id: 'makePrimaryBillingAddress',
89+
checked: cart.makePrimaryBillingAddress,
8690
}) }}
8791
{{ 'Make this my default billing address'|t }}
8892
</label>

example-templates/src/shop/checkout/pay-static.twig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@
190190
}) }}" class="[[classes.a]]">&larr; {{ 'Back'|t }}</a>
191191

192192
<div class="gateway-payment-form max-w-3/4">
193-
{% namespace cart.gateway.handle|commercePaymentFormNamespace %}
194-
{{ cart.gateway.getPaymentFormHtml(params)|raw }}
193+
{% namespace gateway.handle|commercePaymentFormNamespace %}
194+
{{ gateway.getPaymentFormHtml(params)|raw }}
195195
{% endnamespace %}
196196
</div>
197197

example-templates/src/shop/products/_includes/grid.twig

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,16 @@
5050
checked: loop.first,
5151
class: not variant.getIsAvailable() ? 'opacity-10' : '',
5252
disabled: not variant.availableForPurchase,
53-
}) }}<span class="pl-1">{{ variant.sku }} {% if variant.inventoryTracked %}({{ variant.stock ? variant.stock ~ ' available' : 'out of stock'}}){% endif %}</span><span class="ml-auto">{% if variant.onPromotion %} <del class="text-gray-400 text-xs">{{ variant.price|currency(cart.currency) }}</del>{% endif %} {{ variant.salePrice|currency(cart.currency) }}</span>
53+
}) }}
54+
<span class="pl-1">{{ variant.sku }}
55+
{% if variant.hasInventory and variant.inventoryTracked %}
56+
({{ variant.stock ? variant.stock ~ ' available' : 'out of stock'}})
57+
{% if variant.allowOutOfStockPurchases %}
58+
<span class="text-xs text-gray-400">{{ "Continue selling when out of stock."|t }}</span>
59+
{% endif %}
60+
{% endif %}
61+
</span>
62+
<span class="ml-auto">{% if variant.onPromotion %} <del class="text-gray-400 text-xs">{{ variant.price|currency(cart.currency) }}</del>{% endif %} {{ variant.salePrice|currency(cart.currency) }}</span>
5463
</label>
5564
{% endfor %}
5665
</div>

src/Plugin.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ public static function editions(): array
257257
/**
258258
* @inheritDoc
259259
*/
260-
public string $schemaVersion = '5.2.9.1';
260+
public string $schemaVersion = '5.3.0.4';
261261

262262
/**
263263
* @inheritdoc
@@ -279,6 +279,11 @@ public static function editions(): array
279279
*/
280280
public CmsEdition $minCmsEdition = CmsEdition::Pro;
281281

282+
/**
283+
* @inheritdoc
284+
*/
285+
public bool $hasReadOnlyCpSettings = true;
286+
282287
use CommerceServices;
283288
use Variables;
284289
use Routes;
@@ -304,7 +309,6 @@ public function init(): void
304309
$this->_registerGqlQueries();
305310
$this->_registerGqlComponents();
306311
$this->_registerGqlEagerLoadableFields();
307-
$this->_registerLinkTypes();
308312
$this->_registerCacheTypes();
309313
$this->_registerGarbageCollection();
310314

@@ -315,6 +319,7 @@ public function init(): void
315319
$this->_registerWidgets();
316320
$this->_registerElementExports();
317321
$this->_defineFieldLayoutElements();
322+
$this->_registerLinkTypes();
318323
$this->_registerRedactorLinkOptions();
319324
$this->_registerCKEditorLinkOptions();
320325
} else {
@@ -351,6 +356,14 @@ public function getSettingsResponse(): mixed
351356
return Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('commerce/settings/general'));
352357
}
353358

359+
/**
360+
* @inheritdoc
361+
*/
362+
public function getReadOnlySettingsResponse(): mixed
363+
{
364+
return Craft::$app->getResponse()->redirect(UrlHelper::cpUrl('commerce/settings/general'));
365+
}
366+
354367
/**
355368
* @inheritdoc
356369
*/
@@ -428,9 +441,10 @@ public function getCpNavItem(): ?array
428441
];
429442
}
430443

431-
if (Craft::$app->getUser()->getIsAdmin() && Craft::$app->getConfig()->getGeneral()->allowAdminChanges) {
444+
if (Craft::$app->getUser()->getIsAdmin()) {
432445
$ret['subnav']['settings'] = [
433-
'label' => Craft::t('commerce', 'System Settings'),
446+
'ariaLabel' => Craft::t('commerce', 'Commerce Settings'),
447+
'label' => Craft::t('app', 'Settings'),
434448
'url' => 'commerce/settings/general',
435449
];
436450
}

0 commit comments

Comments
 (0)