Skip to content

Commit

Permalink
Merge tag '4.3.0' into develop
Browse files Browse the repository at this point in the history
4.3.0

# gpg: Signature made Wed Sep 13 12:42:29 2023 PDT
# gpg:                using RSA key B6C810CBE206E036FB68F3CD5E86D0CED64C7093
# gpg: Good signature from "Brandon Kelly <[email protected]>" [ultimate]
  • Loading branch information
brandonkelly committed Sep 13, 2023
2 parents d032545 + 65a6166 commit 85ae09a
Show file tree
Hide file tree
Showing 109 changed files with 4,994 additions and 1,245 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- develop
- v3
- '4.3'
pull_request:
permissions:
contents: read
Expand Down
46 changes: 32 additions & 14 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
# Release Notes for Craft Commerce

## Unreleased

- Variant min and max quantity fields now validate together logically. ([#3234](https://github.com/craftcms/commerce/issues/3234))
- Added the “Product Type” product condition rule. ([#3209](https://github.com/craftcms/commerce/issues/3209))
- Fixed a bug where `hasMatchingAddresses()` was incorrectly returning `false`. ([#3183](https://github.com/craftcms/commerce/issues/3183))
- Fixed a bug where changing a user’s email would cause extra user elements to be created. ([#3138](https://github.com/craftcms/commerce/issues/3138))
- Fixed a bug where related sales were showing when creating a new product.
## 4.3.0 - 2023-09-13

- Sales and discounts now support using related entries in their matching item conditions. ([#3134](https://github.com/craftcms/commerce/issues/3134), [#2717](https://github.com/craftcms/commerce/issues/2717))
- It’s now possible to query products by shipping category and tax category. ([#3219](https://github.com/craftcms/commerce/issues/3219))
- Guest customers registering during checkout now have their addresses saved to their account. ([#3203](https://github.com/craftcms/commerce/pull/3203))
- Product conditions can now have “Product Type”, “Variant SKU”, “Variant Has Unlimited Stock”, “Variant Price”, and “Variant Stock” rules. ([#3209](https://github.com/craftcms/commerce/issues/3209))
- Improved the performance of discount recalculation.
- Improved the performance of the `commerce/upgrade` command. ([#3208](https://github.com/craftcms/commerce/pull/3208))
- Added the `commerce/cart/forget-cart` action. ([#3206](https://github.com/craftcms/commerce/issues/3206))
- The `commerce/cart/update-cart` action now accepts `firstName` and `lastName` address parameters. ([#3015](https://github.com/craftcms/commerce/issues/3015))
- Added `craft\commerce\controllers\OrdersController::EVENT_MODIFY_PURCHASABLES_TABLE_QUERY`. ([#3198](https://github.com/craftcms/commerce/pull/3198))
- Added `craft\commerce\elements\Order::$orderCompletedEmail`. ([#3138](https://github.com/craftcms/commerce/issues/3138))
- Added `craft\commerce\elements\db\ProductQuery::$shippingCategoryId`.
- Added `craft\commerce\elements\db\ProductQuery::$taxCategoryId`.
- Added `craft\commerce\elements\db\ProductQuery::shippingCategory()`.
- Added `craft\commerce\elements\db\ProductQuery::shippingCategoryId()`.
- Added `craft\commerce\elements\db\ProductQuery::taxCategory()`.
- Added `craft\commerce\elements\db\ProductQuery::taxCategoryId()`.
- Added `craft\commerce\models\Discount::hasBillingAddressCondition()`.
- Added `craft\commerce\models\Discount::hasCustomerCondition()`.
- Added `craft\commerce\models\Discount::hasOrderCondition()`.
- Added `craft\commerce\models\Discount::hasShippingAddressCondition()`.
- Deprecated payment source creation via the `commerce/subscriptions/subscribe` action.
- Deprecated `craft\commerce\elements\Order::setEmail()`. `Order::setCustomer()` should be used instead.
- Removed the `htmx` option from the`commerce/example-templates` command.
- Removed the `color` option from the`commerce/example-templates` command.
- Added `craft\commerce\events\ModifyPurchasablesTableQueryEvent`. ([#3198](https://github.com/craftcms/commerce/pull/3198))
- Fixed a bug where products/variants could be saved with a minimum quantity that was set higher than the maximum quantity. ([#3234](https://github.com/craftcms/commerce/issues/3234))
- Fixed a bug where `craft\commerce\elements\Order::hasMatchingAddresses()` could incorrectly return `false`. ([#3183](https://github.com/craftcms/commerce/issues/3183))
- Fixed a bug where changing a user’s email could cause additional user elements to be created. ([#3138](https://github.com/craftcms/commerce/issues/3138))
- Fixed a bug where related sales were displaying when creating a new product.
- Fixed a bug where Commerce wasn’t invoking `craft\services\Elements::EVENT_AUTHORIZE_*` event handlers.
- Fixed a bug where discounts’ per user usage counters weren’t getting migrated properly when upgrading to Commerce 4.
- Fixed a bug where address changes weren’t being synced to carts using them as a source. ([#3178](https://github.com/craftcms/commerce/issues/3178))
- Added `craft\commerce\services\Orders::afterSaveAddressHandler()`.
- Added `craft\commerce\elements\Order::$orderCompletedEmail`. ([#3138](https://github.com/craftcms/commerce/issues/3138))
- Added the `commerce/cart/forget-cart` action. ([#3206](https://github.com/craftcms/commerce/issues/3206))
- The `commerce/cart/update` action now accepts `firstName` and `lastName` in address params. ([#3015](https://github.com/craftcms/commerce/issues/3015))
- Removed the htmx option from the`commerce/example-templates` command.
- Removed the color option from the`commerce/example-templates` command.
- Fixed a bug where address changes weren’t being synced to carts that were using them. ([#3178](https://github.com/craftcms/commerce/issues/3178))
- Fixed an XSS vulnerability.

## 4.2.11 - 2023-06-05
Expand Down
104 changes: 47 additions & 57 deletions example-templates/dist/shop/_private/address/list.twig
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,74 @@
{% set selectable = selectable ?? false %}
{% set primaryBillingAddressId = primaryBillingAddressId ?? null %}
{% set primaryShippingAddressId = primaryShippingAddressId ?? null %}
{% set cardWidth = cardWidth ?? 'md:w-1/2' %}
{% set showDelete = showDelete ?? false %}
{% set showAdd = showAdd ?? false %}
{% set addUrl = '/shop/customer/addresses/edit?redirect=' ~ craft.app.request.fullPath %}

{% if currentUser %}
{% if addresses|length %}
<div class="md:flex md:flex-wrap md:-mx-2 pb-4">
{% for address in addresses %}
{% set editUrl = '/shop/customer/addresses/edit?addressId=' ~ address.id ~ '&redirect=' ~ craft.app.request.fullPath %}
<div class="pb-2 my-4 md:px-2 {{ cardWidth }} md:my-0">
{% tag selectable ? 'label' : 'div' with {
class: 'block relative address-select js-address-select border-blue-300 border-b-2 px-6 py-4 rounded-md shadow-md hover:shadow-lg',
data: {
'address-id': address.id,
},
} %}
<span class="js-radio flex py-2">
{% if addresses|length %}
<div class="my-6 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 xl:grid-cols-3 gap-4">
{% for address in addresses %}
{% set editUrl = '/shop/customer/addresses/edit?addressId=' ~ address.id ~ '&redirect=' ~ craft.app.request.fullPath %}
<div class="block border border-gray-200 bg-white rounded-lg shadow-sm hover:shadow-md p-4 w-full">
{% tag selectable ? 'label' : 'div' with {
class: 'block relative address-select js-address-select',
data: {
'address-id': address.id,
},
} %}
<span class="js-radio flex py-2">
{% if selectable %}
{{ input('radio', name ~ 'Id', address.id, {
data: {
'model-name': name,
},
checked: (attribute(cart, sourceIdName) == address.id) or (not attribute(cart, sourceIdName) and address.id == attribute(_context, primaryIdName)),
}) }}
{{ input('radio', name ~ 'Id', address.id, {
data: {
'model-name': name,
},
checked: (attribute(cart, sourceIdName) == address.id) or (not attribute(cart, sourceIdName) and address.id == attribute(_context, primaryIdName)),
}) }}
{% endif %}
<span class="-mt-2 ml-3 mb-2">
<span class="-mt-2 mb-2 {% if selectable %}ml-4{% endif %}">
{{ address|address }}
</span>
</span>
<span class="block mb-1">
<span class="block mb-1">
<a href="{{ url(editUrl) }}" class="cursor-pointer rounded px-2 py-1 text-sm inline-block bg-gray-500 hover:bg-gray-600 text-white hover:text-white">
{{- 'Edit'|t -}}
</a>
{% if showDelete and not selectable %}
<form method="post" action="" class="js-address-delete inline-block">
<form method="post" action="" class="js-address-delete inline-block">
{{ csrfInput() }}
{{ actionInput('users/delete-address') }}
{{ redirectInput('shop/customer/addresses') }}
{{ hiddenInput('addressId', address.id) }}
{{ tag('button', {
type: 'submit',
class: 'cursor-pointer rounded px-2 py-1 text-sm inline-block bg-gray-500 hover:bg-gray-600 text-white hover:text-white',
text: 'Delete'|t
}) }}
{{ actionInput('users/delete-address') }}
{{ redirectInput('shop/customer/addresses') }}
{{ hiddenInput('addressId', address.id) }}
{{ tag('button', {
type: 'submit',
class: 'cursor-pointer rounded px-2 py-1 text-sm inline-block bg-gray-500 hover:bg-gray-600 text-white hover:text-white',
text: 'Delete'|t
}) }}
</form>
{% endif %}
</span>

{% if primaryBillingAddressId == address.id or primaryShippingAddressId == address.id %}
<span class="absolute top-4 right-4">
{% if primaryBillingAddressId == address.id %}
<span title="{{ 'Primary billing address'|t }}">💳</span>
{% endif %}
{% if primaryShippingAddressId == address.id %}
<span title="{{ 'Primary shipping address'|t }}">📦</span>
{% endif %}
</span>
{% endtag %}
</div>
{% endfor %}
{% if showAdd %}
<a href="{{ addUrl }}" class="block rounded-lg hover:shadow-md w-full">
<div class="flex items-center justify-center h-full border border-gray-200 bg-white rounded-lg shadow-sm p-4 w-full group hover:shadow-md">
<span class="group-hover:underline">Add Address</span>
</div>
</a>
{% endif %}
{% endtag %}
</div>
{% endfor %}
</div>
{% endif %}
{% if showAdd %}
<div class="pt-2">
<a href="{{ url(addUrl) }}" class="cursor-pointer rounded px-2 py-1 text-sm inline-block bg-blue-500 hover:bg-blue-600 text-white hover:text-white">{{ 'Add address'|t }}</a>
</div>
{% endif %}
{% endif %}
{% endif %}

{% js %}
const addressDeletes = document.querySelectorAll('.js-address-delete');
for (let i = 0; i < addressDeletes.length; i++) {
addressDeletes[i].addEventListener('submit', ev => {
if (!confirm('{{ 'Are you sure you want to delete this address?'|t }}')) {
ev.preventDefault();
const addressDeletes = document.querySelectorAll('.js-address-delete');
for (let i = 0; i < addressDeletes.length; i++) {
addressDeletes[i].addEventListener('submit', ev => {
if (!confirm('{{ 'Are you sure you want to delete this address?'|t }}')) {
ev.preventDefault();
}
});
}
});
}
{% endjs %}
{% endjs %}
18 changes: 18 additions & 0 deletions example-templates/dist/shop/_private/layouts/includes/header.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div class="bg-gray-900">
<div class="container mx-auto p-6 md:flex justify-content-between align-content-center">
<h1 class="text-3xl">
<a href="{{ siteUrl('/shop') }}" class="text-white">
{{- siteName ~ ' Shop' -}}
</a>
</h1>
{% if craft.app.sites.getAllSites()|length > 1 %}
<div class="ml-auto">
<select name="site" id="js-site-selector" class="mt-1 block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm">
{% for site in craft.app.sites.getAllSites() %}
<option value="{{ siteUrl(craft.app.request.absoluteUrl|replace(currentSite.getBaseUrl(), ''), null, null, site.id) }}" {% if site.handle == currentSite.handle %}selected{% endif %}>{{ site.name }}</option>
{% endfor %}
</select>
</div>
{% endif %}
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Outputs the checkout progress navigation using the request path and included `ch
label: 'Payment Method',
url: 'shop/checkout/payment-method'
},
{
label: 'Options',
url: 'shop/checkout/options'
},
{
label: 'Payment',
url: 'shop/checkout/payment'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!-- Template: {{ _self }}.twig -->
{#
Outputs the site’s global main navigation based on path and included `pages` array.
@var cart \craft\commerce\elements\Order
@var currentUser \craft\elements\User
#}
{% set pages = [
{
label: 'My Orders',
url: 'shop/customer/orders'
},
{
label: 'My Addresses',
url: 'shop/customer/addresses'
},
{
label: 'My Stored Cards',
url: 'shop/customer/cards'
}
] %}
{% set currentPath = craft.app.request.pathInfo %}
{# Show the nav if we in a customers page #}
{% if currentPath in pages|column('url') %}
{% set activeClasses = 'bg-gray-200' %}
<div class="bg-gray-50">
<div class="container mx-auto justify-between items-center p-6 relative">
<nav class="-ml-4"
role="navigation"
aria-label="Customer">
{% for page in pages %}
<a href="{{ url(page.url) }}"
class="mx-2 px-2 py-1 rounded{% if page.url in currentPath %} {{ activeClasses }}{% endif %}">
{{- page.label|t -}}
</a>
{% endfor %}
</nav>
</div>
</div>
{% endif %}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Outputs the site’s global main navigation based on path and included `pages` a
] %}
{% set currentPath = craft.app.request.pathInfo %}
{% set activeClasses = 'bg-white' %}
{# Show the nav if we are not in a checkout page #}
{% if 'checkout' not in currentPath %}
<div class="bg-gray-100">
<div class="container mx-auto justify-between items-center p-6 relative">
Expand Down
32 changes: 13 additions & 19 deletions example-templates/dist/shop/_private/layouts/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,22 @@ Common, top-level layout template.
{% set flashNotice = craft.app.session.getFlash('notice') %}
{% set flashError = craft.app.session.getFlash('error') %}

<header>
<div class="bg-gray-900">
<div class="container mx-auto p-6 md:flex justify-content-between align-content-center">
<h1 class="text-3xl">
<a href="{{ siteUrl('/shop') }}" class="text-white">
{{- siteName ~ ' Shop' -}}
</a>
</h1>
{% if craft.app.sites.getAllSites()|length > 1 %}
<div class="ml-auto">
<select name="site" id="js-site-selector" class="mt-1 block w-full rounded-md border-gray-300 py-2 pl-3 pr-10 text-base focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm">
{% for site in craft.app.sites.getAllSites() %}
<option value="{{ siteUrl(craft.app.request.absoluteUrl|replace(currentSite.getBaseUrl(), ''), null, null, site.id) }}" {% if site.handle == currentSite.handle %}selected{% endif %}>{{ site.name }}</option>
{% endfor %}
</select>
</div>
{% endif %}
</div>
</div>
{% macro docs(text, link) %}
<small class="">
{{ tag('a', {
text: 'ℹ︎ ' ~ text,
href: link,
class: 'text-gray-400 hover:text-gray-600 hover:underline',
target: '_blank',
}) }}
</small>
{% endmacro %}

<header>
{{ include('shop/_private/layouts/includes/header') }}
{{ include('shop/_private/layouts/includes/nav-main') }}
{{ include('shop/_private/layouts/includes/nav-checkout') }}
{{ include('shop/_private/layouts/includes/nav-customer') }}
</header>

<div id="main">
Expand Down
2 changes: 1 addition & 1 deletion example-templates/dist/shop/cart/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Outputs cart.
</label>
{{ input('text', 'lineItems[' ~ item.id ~ '][note]', item.note, {
id: 'lineitem-note-' ~ item.id,
class: 'border border-gray-300 hover:border-gray-500 px-4 py-2 leading-tight rounded',
class: 'border border-gray-300 hover:border-gray-500 px-4 py-2 leading-tight rounded w-full',
size: 20,
placeholder: 'My Note'|t
}) }}
Expand Down
4 changes: 2 additions & 2 deletions example-templates/dist/shop/cart/load.twig
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ Outputs form for collecting a cart number to be loaded.
{{- 'Cart Number'|t -}}
</label>
<div>
{{ input('text', 'number', 'border border-gray-300 hover:border-gray-500 px-4 py-2 leading-tight rounded', {
{{ input('text', 'number', null, {
id: 'number',
class: ['w-full', ''],
class: ['w-full', 'border border-gray-300 hover:border-gray-500 px-4 py-2 leading-tight rounded'],
placeholder: '7e89fh0ew8034…'
}) }}
</div>
Expand Down

This file was deleted.

Loading

0 comments on commit 85ae09a

Please sign in to comment.