Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# WIP Release Notes for Craft Commerce

### Store Management

### Administration

### Development

### Extensibility

### System
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Fixed a bug where catalog pricing rules could generate promotional prices for non-promotable purchasables. ([#4118](https://github.com/craftcms/commerce/issues/4118))
- Fixed a bug where variants weren’t duplicating correctly. ([#4125](https://github.com/craftcms/commerce/issues/4125))
- Fixed a SQL error that could occur when deleting a shipping method.

## 5.4.6 - 2025-09-04
Expand Down
2 changes: 1 addition & 1 deletion src/base/Purchasable.php
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,7 @@ public function getSkuAsText(): string
/**
* @param string|null $sku
*/
public function setSku(string $sku = null): void
public function setSku(?string $sku = null): void
{
$this->_sku = $sku;
}
Expand Down
2 changes: 1 addition & 1 deletion src/base/Stat.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ abstract class Stat implements StatInterface, HasStoreInterface
* @param DateTime|bool|null $endDate
* @throws \Exception
*/
public function __construct(string $dateRange = null, mixed $startDate = null, mixed $endDate = null, ?int $storeId = null)
public function __construct(?string $dateRange = null, mixed $startDate = null, mixed $endDate = null, ?int $storeId = null)
{
$user = Craft::$app->getUser()->getIdentity();
if ($user) {
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/CatalogPricingRulesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @throws HttpException
* @throws InvalidConfigException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, CatalogPricingRule $catalogPricingRule = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?CatalogPricingRule $catalogPricingRule = null): Response
{
if ($id === null) {
$this->requirePermission('commerce-createCatalogPricingRules');
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/DiscountsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function init(): void
/**
* @throws HttpException
*/
public function actionIndex(string $storeHandle = null): Response
public function actionIndex(?string $storeHandle = null): Response
{
if ($storeHandle) {
$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle);
Expand Down Expand Up @@ -178,7 +178,7 @@ public function actionTableData(): Response
* @param Discount|null $discount
* @throws HttpException
*/
public function actionEdit(int $id = null, Discount $discount = null, string $storeHandle = null): Response
public function actionEdit(?int $id = null, ?Discount $discount = null, ?string $storeHandle = null): Response
{
if ($id === null) {
$this->requirePermission('commerce-createDiscounts');
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/EmailsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function actionIndex(): Response
* @param Email|null $email
* @throws HttpException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, Email $email = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?Email $email = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/GatewaysController.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public function actionIndex(): Response
* @throws DeprecationException
* @throws InvalidConfigException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, ?GatewayInterface $gateway = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?GatewayInterface $gateway = null): Response
{
/** @var Gateway|null $gateway */
$variables = compact('id', 'gateway');
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/LineItemStatusesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function actionIndex(): Response
* @param LineItemStatus|null $lineItemStatus
* @throws HttpException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, LineItemStatus $lineItemStatus = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?LineItemStatus $lineItemStatus = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/OrderStatusesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function actionIndex(): Response
* @param OrderStatus|null $orderStatus
* @throws HttpException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, OrderStatus $orderStatus = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?OrderStatus $orderStatus = null): Response
{
$variables = compact('id', 'orderStatus');
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
Expand Down
4 changes: 2 additions & 2 deletions src/controllers/OrdersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public function init(): void
*
* @throws Throwable
*/
public function actionOrderIndex(string $orderStatusHandle = ''): Response
public function actionOrderIndex(?string $orderStatusHandle = ''): Response
{
Craft::$app->getView()->registerAssetBundle(CommerceCpAsset::class);

Expand Down Expand Up @@ -213,7 +213,7 @@ public function actionCreate(string $storeHandle): Response
* @throws RuntimeError
* @throws SyntaxError
*/
public function actionEditOrder(int $orderId, Order $order = null, $paymentForm = null): Response
public function actionEditOrder(int $orderId, ?Order $order = null, $paymentForm = null): Response
{
$plugin = Plugin::getInstance();
$variables = [];
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/PaymentCurrenciesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @throws HttpException
* @throws InvalidConfigException
*/
public function actionEdit(int $id = null, PaymentCurrency $currency = null, string $storeHandle = null): Response
public function actionEdit(?int $id = null, ?PaymentCurrency $currency = null, ?string $storeHandle = null): Response
{
$variables = compact('id', 'currency');

Expand Down
2 changes: 1 addition & 1 deletion src/controllers/PdfsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function actionIndex(): Response
* @throws InvalidConfigException
* @since 3.2
*/
public function actionEdit(?string $storeHandle = null, int $id = null, Pdf $pdf = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?Pdf $pdf = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/PlansController.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function actionPlanIndex(): Response
* @throws DeprecationException
* @throws ForbiddenHttpException
*/
public function actionEditPlan(int $planId = null, Plan $plan = null): Response
public function actionEditPlan(?int $planId = null, ?Plan $plan = null): Response
{
$this->requirePermission('commerce-manageSubscriptions');

Expand Down
2 changes: 1 addition & 1 deletion src/controllers/ProductTypesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function actionProductTypeIndex(): Response
* @param ProductType|null $productType
* @throws HttpException
*/
public function actionEditProductType(int $productTypeId = null, ProductType $productType = null): Response
public function actionEditProductType(?int $productTypeId = null, ?ProductType $productType = null): Response
{
$variables = compact('productTypeId', 'productType');

Expand Down
2 changes: 1 addition & 1 deletion src/controllers/SalesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @throws HttpException
* @throws InvalidConfigException
*/
public function actionEdit(int $id = null, Sale $sale = null, ?string $storeHandle = null): Response
public function actionEdit(?int $id = null, ?Sale $sale = null, ?string $storeHandle = null): Response
{
if ($id === null) {
$this->requirePermission('commerce-createSales');
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/ShippingCategoriesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @param ShippingCategory|null $shippingCategory
* @throws HttpException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, ShippingCategory $shippingCategory = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?ShippingCategory $shippingCategory = null): Response
{
$variables = [
'id' => $id,
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/ShippingMethodsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @throws HttpException
* @throws InvalidConfigException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, ShippingMethod $shippingMethod = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?ShippingMethod $shippingMethod = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/ShippingRulesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ShippingRulesController extends BaseShippingSettingsController
* @throws SyntaxError
* @throws Exception
*/
public function actionEdit(?string $storeHandle = null, int $methodId = null, int $ruleId = null, ShippingRule $shippingRule = null): Response
public function actionEdit(?string $storeHandle = null, ?int $methodId = null, ?int $ruleId = null, ?ShippingRule $shippingRule = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/ShippingZonesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @param ShippingAddressZone|null $shippingZone
* @throws HttpException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, ShippingAddressZone $shippingZone = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?ShippingAddressZone $shippingZone = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/StoreManagementController.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public function actionIndex(): Response
* @throws TemplateLoaderException
* @throws InvalidConfigException
*/
public function actionEdit(StoreSettings $storeSettings = null, ?string $storeHandle = null): Response
public function actionEdit(?StoreSettings $storeSettings = null, ?string $storeHandle = null): Response
{
$this->requirePermission('commerce-manageGeneralStoreSettings');

Expand Down
2 changes: 1 addition & 1 deletion src/controllers/StoresController.php
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public function actionReorderStores(): Response
* @return Response
* @throws InvalidConfigException
*/
public function actionEditSiteStores(Collection $sitesStores = null): Response
public function actionEditSiteStores(?Collection $sitesStores = null): Response
{
// Breadcrumbs
$crumbs = [
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/SubscriptionsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function actionIndex(): Response
* @throws HttpException
* @throws InvalidConfigException
*/
public function actionEdit(int $subscriptionId = null, Subscription $subscription = null): Response
public function actionEdit(?int $subscriptionId = null, ?Subscription $subscription = null): Response
{
$variables = [];

Expand Down
2 changes: 1 addition & 1 deletion src/controllers/TaxCategoriesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @param TaxCategory|null $taxCategory
* @throws HttpException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, TaxCategory $taxCategory = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?TaxCategory $taxCategory = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/TaxRatesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @throws SyntaxError
* @throws Exception
*/
public function actionEdit(?string $storeHandle = null, int $id = null, TaxRate $taxRate = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?TaxRate $taxRate = null): Response
{
if (!Plugin::getInstance()->getTaxes()->viewTaxRates()) {
throw new ForbiddenHttpException('Tax engine does not permit you to perform this action');
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/TaxZonesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function actionIndex(?string $storeHandle = null): Response
* @param TaxAddressZone|null $taxZone
* @throws HttpException
*/
public function actionEdit(?string $storeHandle = null, int $id = null, TaxAddressZone $taxZone = null): Response
public function actionEdit(?string $storeHandle = null, ?int $id = null, ?TaxAddressZone $taxZone = null): Response
{
if ($storeHandle === null || !$store = Plugin::getInstance()->getStores()->getStoreByHandle($storeHandle)) {
$store = Plugin::getInstance()->getStores()->getPrimaryStore();
Expand Down
2 changes: 1 addition & 1 deletion src/elements/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -2422,7 +2422,7 @@ public function getCpEditUrl(): ?string
* @param string|null $pdfHandle The handle of the PDF to use. If none is passed the default PDF is used.
* @return string|null The URL to the order’s PDF invoice, or null if the PDF template doesn’t exist
*/
public function getPdfUrl(string $option = null, string $pdfHandle = null): ?string
public function getPdfUrl(?string $option = null, ?string $pdfHandle = null): ?string
{
$path = "commerce/downloads/pdf";
$params = [];
Expand Down
21 changes: 13 additions & 8 deletions src/elements/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public static function createCondition(): ElementConditionInterface
/**
* @inheritdoc
*/
protected static function defineSources(string $context = null): array
protected static function defineSources(?string $context = null): array
{
if ($context == 'index') {
$productTypes = Plugin::getInstance()->getProductTypes()->getEditableProductTypes();
Expand Down Expand Up @@ -334,7 +334,7 @@ protected static function defineFieldLayouts(?string $source): array
/**
* @inheritdoc
*/
protected static function defineActions(string $source = null): array
protected static function defineActions(?string $source = null): array
{
$elementsService = Craft::$app->getElements();
// Get the selected site
Expand Down Expand Up @@ -1107,7 +1107,15 @@ public function getVariants(bool $includeDisabled = false): VariantCollection
return VariantCollection::make();
}

$variants = self::createVariantQuery($this)->status(null)->collect();
/** @var self|null $duplicatingProduct */
$duplicatingProduct = $this->duplicateOf;
if ($duplicatingProduct) {
$query = self::createVariantQuery($duplicatingProduct)->status(null);
} else {
$query = self::createVariantQuery($this)->status(null);
}

$variants = $query->collect();

// Don't memoize empty collections in favour of a new query next time
if ($variants->isEmpty()) {
Expand Down Expand Up @@ -1885,12 +1893,9 @@ protected static function defineSearchableAttributes(): array
*/
private static function createVariantQuery(Product $product): VariantQuery
{
$productId = $product->duplicateOf?->id ?? $product->id;
$productSiteId = $product->duplicateOf?->siteId ?? $product->siteId;

$query = Variant::find()
->productId($productId)
->siteId($productSiteId)
->productId($product->id)
->siteId($product->siteId)
->orderBy(['sortOrder' => SORT_ASC]);

if ($product->getIsRevision()) {
Expand Down
2 changes: 1 addition & 1 deletion src/elements/Subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ public function getStatus(): ?string
/**
* @inheritdoc
*/
public static function defineSources(string $context = null): array
public static function defineSources(?string $context = null): array
{
$plans = Plugin::getInstance()->getPlans()->getAllPlans();

Expand Down
2 changes: 1 addition & 1 deletion src/elements/Transfer.php
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ public function getUriFormat(): ?string
* @param string|null $context
* @return array
*/
protected static function defineSources(string $context = null): array
protected static function defineSources(?string $context = null): array
{
$transferStatuses = TransferStatusType::cases();
$transferStatusSources = [];
Expand Down
Loading
Loading