Skip to content

Commit 6baf2b2

Browse files
Merge branch '2.4-develop' into fixed-returning-from-method-that-doesnt-return
2 parents 40fcb35 + 9a7352b commit 6baf2b2

File tree

173 files changed

+9768
-2009
lines changed

Some content is hidden

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

173 files changed

+9768
-2009
lines changed

app/code/Magento/Captcha/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"magento/module-store": "*",
1515
"magento/module-authorization": "*",
1616
"laminas/laminas-captcha": "^2.18",
17-
"magento/laminas-db": "^1.0.0"
17+
"magento/magento-zf-db": "^3.21"
1818
},
1919
"type": "magento2-module",
2020
"license": [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Model\Indexer\Category\Flat;
9+
10+
use Magento\Framework\Indexer\AbstractProcessor;
11+
use Magento\Framework\Indexer\IndexerRegistry;
12+
13+
class Processor extends AbstractProcessor
14+
{
15+
public const INDEXER_ID = State::INDEXER_ID;
16+
17+
/**
18+
* @param IndexerRegistry $indexerRegistry
19+
* @param State $state
20+
*/
21+
public function __construct(
22+
IndexerRegistry $indexerRegistry,
23+
private readonly State $state
24+
) {
25+
parent::__construct($indexerRegistry);
26+
}
27+
28+
/**
29+
* @inheritdoc
30+
*/
31+
public function reindexRow($id, $forceReindex = false)
32+
{
33+
if (!$this->state->isFlatEnabled()) {
34+
return;
35+
}
36+
37+
parent::reindexRow($id, $forceReindex);
38+
}
39+
40+
/**
41+
* @inheritdoc
42+
*/
43+
public function reindexList($ids, $forceReindex = false)
44+
{
45+
if (!$this->state->isFlatEnabled()) {
46+
return;
47+
}
48+
49+
parent::reindexList($ids, $forceReindex);
50+
}
51+
52+
/**
53+
* @inheritdoc
54+
*/
55+
public function reindexAll()
56+
{
57+
if (!$this->state->isFlatEnabled()) {
58+
return;
59+
}
60+
61+
parent::reindexAll();
62+
}
63+
64+
/**
65+
* @inheritdoc
66+
*/
67+
public function markIndexerAsInvalid()
68+
{
69+
if (!$this->state->isFlatEnabled()) {
70+
return;
71+
}
72+
73+
parent::markIndexerAsInvalid();
74+
}
75+
}

app/code/Magento/Catalog/Model/Indexer/Category/Product/AbstractAction.php

+54-41
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
namespace Magento\Catalog\Model\Indexer\Category\Product;
88

9+
use Magento\Catalog\Api\Data\CategoryInterface;
910
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Catalog\Model\Category;
1012
use Magento\Catalog\Model\Product;
1113
use Magento\Framework\App\ObjectManager;
1214
use Magento\Framework\App\ResourceConnection;
@@ -312,19 +314,17 @@ protected function getPathFromCategoryId($categoryId)
312314
protected function getNonAnchorCategoriesSelect(Store $store)
313315
{
314316
if (!isset($this->nonAnchorSelects[$store->getId()])) {
315-
$statusAttributeId = $this->config->getAttribute(
316-
Product::ENTITY,
317-
'status'
318-
)->getId();
319-
$visibilityAttributeId = $this->config->getAttribute(
320-
Product::ENTITY,
321-
'visibility'
322-
)->getId();
317+
$statusAttributeId = $this->config->getAttribute(Product::ENTITY, 'status')->getId();
318+
$visibilityAttributeId = $this->config->getAttribute(Product::ENTITY, 'visibility')->getId();
319+
$isActiveAttributeId = $this->config->getAttribute(Category::ENTITY, 'is_active')->getId();
323320

324321
$rootPath = $this->getPathFromCategoryId($store->getRootCategoryId());
325322

326-
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
327-
$linkField = $metadata->getLinkField();
323+
$productMetadata = $this->metadataPool->getMetadata(ProductInterface::class);
324+
$productLinkField = $productMetadata->getLinkField();
325+
$categoryMetadata = $this->metadataPool->getMetadata(CategoryInterface::class);
326+
$categoryLinkField = $categoryMetadata->getLinkField();
327+
328328
$select = $this->connection->select()->from(
329329
['cc' => $this->getTable('catalog_category_entity')],
330330
[]
@@ -342,28 +342,37 @@ protected function getNonAnchorCategoriesSelect(Store $store)
342342
[]
343343
)->joinInner(
344344
['cpsd' => $this->getTable('catalog_product_entity_int')],
345-
'cpsd.' . $linkField . ' = cpe.' . $linkField . ' AND cpsd.store_id = 0' .
346-
' AND cpsd.attribute_id = ' .
347-
$statusAttributeId,
345+
'cpsd.' . $productLinkField . ' = cpe.' . $productLinkField . ' AND cpsd.store_id = 0' .
346+
' AND cpsd.attribute_id = ' . $statusAttributeId,
348347
[]
349348
)->joinLeft(
350349
['cpss' => $this->getTable('catalog_product_entity_int')],
351-
'cpss.' . $linkField . ' = cpe.' . $linkField . ' AND cpss.attribute_id = cpsd.attribute_id' .
352-
' AND cpss.store_id = ' .
353-
$store->getId(),
350+
'cpss.' . $productLinkField . ' = cpe.' . $productLinkField .
351+
' AND cpss.attribute_id = cpsd.attribute_id AND cpss.store_id = ' . $store->getId(),
354352
[]
355353
)->joinInner(
356354
['cpvd' => $this->getTable('catalog_product_entity_int')],
357-
'cpvd.' . $linkField . ' = cpe.' . $linkField . ' AND cpvd.store_id = 0' .
358-
' AND cpvd.attribute_id = ' .
359-
$visibilityAttributeId,
355+
'cpvd.' . $productLinkField . ' = cpe.' . $productLinkField . ' AND cpvd.store_id = 0' .
356+
' AND cpvd.attribute_id = ' . $visibilityAttributeId,
360357
[]
361358
)->joinLeft(
362359
['cpvs' => $this->getTable('catalog_product_entity_int')],
363-
'cpvs.' . $linkField . ' = cpe.' . $linkField . ' AND cpvs.attribute_id = cpvd.attribute_id' .
364-
' AND cpvs.store_id = ' .
365-
$store->getId(),
360+
'cpvs.' . $productLinkField . ' = cpe.' . $productLinkField .
361+
' AND cpvs.attribute_id = cpvd.attribute_id AND cpvs.store_id = ' . $store->getId(),
362+
[]
363+
)->joinInner(
364+
['ccacd' => $this->getTable('catalog_category_entity_int')],
365+
'ccacd.' . $categoryLinkField . ' = cc.' . $categoryLinkField . ' AND ccacd.store_id = 0' .
366+
' AND ccacd.attribute_id = ' . $isActiveAttributeId,
366367
[]
368+
)->joinLeft(
369+
['ccacs' => $this->getTable('catalog_category_entity_int')],
370+
'ccacs.' . $categoryLinkField . ' = cc.' . $categoryLinkField .
371+
' AND ccacs.attribute_id = ccacd.attribute_id AND ccacs.store_id = ' . $store->getId(),
372+
[]
373+
)->where(
374+
$this->connection->getIfNullSql('ccacs.value', 'ccacd.value') . ' = ?',
375+
1
367376
)->where(
368377
'cc.path LIKE ' . $this->connection->quote($rootPath . '/%')
369378
)->where(
@@ -530,10 +539,8 @@ protected function hasAnchorSelect(Store $store)
530539
protected function createAnchorSelect(Store $store)
531540
{
532541
$this->setCurrentStore($store);
533-
$isAnchorAttributeId = $this->config->getAttribute(
534-
\Magento\Catalog\Model\Category::ENTITY,
535-
'is_anchor'
536-
)->getId();
542+
$isAnchorAttributeId = $this->config->getAttribute(Category::ENTITY, 'is_anchor')->getId();
543+
$isActiveAttributeId = $this->config->getAttribute(Category::ENTITY, 'is_active')->getId();
537544
$statusAttributeId = $this->config->getAttribute(Product::ENTITY, 'status')->getId();
538545
$visibilityAttributeId = $this->config->getAttribute(Product::ENTITY, 'visibility')->getId();
539546
$rootCatIds = explode('/', $this->getPathFromCategoryId($store->getRootCategoryId()));
@@ -542,7 +549,7 @@ protected function createAnchorSelect(Store $store)
542549
$temporaryTreeTable = $this->makeTempCategoryTreeIndex();
543550

544551
$productMetadata = $this->metadataPool->getMetadata(ProductInterface::class);
545-
$categoryMetadata = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\CategoryInterface::class);
552+
$categoryMetadata = $this->metadataPool->getMetadata(CategoryInterface::class);
546553
$productLinkField = $productMetadata->getLinkField();
547554
$categoryLinkField = $categoryMetadata->getLinkField();
548555

@@ -580,21 +587,18 @@ protected function createAnchorSelect(Store $store)
580587
[]
581588
)->joinLeft(
582589
['cpss' => $this->getTable('catalog_product_entity_int')],
583-
'cpss.' . $productLinkField . ' = cpe.' . $productLinkField . ' AND cpss.attribute_id = cpsd.attribute_id' .
584-
' AND cpss.store_id = ' .
585-
$store->getId(),
590+
'cpss.' . $productLinkField . ' = cpe.' . $productLinkField .
591+
' AND cpss.attribute_id = cpsd.attribute_id AND cpss.store_id = ' . $store->getId(),
586592
[]
587593
)->joinInner(
588594
['cpvd' => $this->getTable('catalog_product_entity_int')],
589595
'cpvd.' . $productLinkField . ' = cpe. ' . $productLinkField . ' AND cpvd.store_id = 0' .
590-
' AND cpvd.attribute_id = ' .
591-
$visibilityAttributeId,
596+
' AND cpvd.attribute_id = ' . $visibilityAttributeId,
592597
[]
593598
)->joinLeft(
594599
['cpvs' => $this->getTable('catalog_product_entity_int')],
595600
'cpvs.' . $productLinkField . ' = cpe.' . $productLinkField .
596-
' AND cpvs.attribute_id = cpvd.attribute_id ' . 'AND cpvs.store_id = ' .
597-
$store->getId(),
601+
' AND cpvs.attribute_id = cpvd.attribute_id ' . 'AND cpvs.store_id = ' . $store->getId(),
598602
[]
599603
)->joinInner(
600604
['ccad' => $this->getTable('catalog_category_entity_int')],
@@ -604,9 +608,21 @@ protected function createAnchorSelect(Store $store)
604608
)->joinLeft(
605609
['ccas' => $this->getTable('catalog_category_entity_int')],
606610
'ccas.' . $categoryLinkField . ' = cc.' . $categoryLinkField
607-
. ' AND ccas.attribute_id = ccad.attribute_id AND ccas.store_id = ' .
608-
$store->getId(),
611+
. ' AND ccas.attribute_id = ccad.attribute_id AND ccas.store_id = ' . $store->getId(),
609612
[]
613+
)->joinInner(
614+
['ccacd' => $this->getTable('catalog_category_entity_int')],
615+
'ccacd.' . $categoryLinkField . ' = cc.' . $categoryLinkField . ' AND ccacd.store_id = 0' .
616+
' AND ccacd.attribute_id = ' . $isActiveAttributeId,
617+
[]
618+
)->joinLeft(
619+
['ccacs' => $this->getTable('catalog_category_entity_int')],
620+
'ccacs.' . $categoryLinkField . ' = cc.' . $categoryLinkField
621+
. ' AND ccacs.attribute_id = ccacd.attribute_id AND ccacs.store_id = ' . $store->getId(),
622+
[]
623+
)->where(
624+
$this->connection->getIfNullSql('ccacs.value', 'ccacd.value') . ' = ?',
625+
1
610626
)->where(
611627
'cpw.website_id = ?',
612628
$store->getWebsiteId()
@@ -712,11 +728,8 @@ protected function makeTempCategoryTreeIndex()
712728
*/
713729
protected function fillTempCategoryTreeIndex($temporaryName)
714730
{
715-
$isActiveAttributeId = $this->config->getAttribute(
716-
\Magento\Catalog\Model\Category::ENTITY,
717-
'is_active'
718-
)->getId();
719-
$categoryMetadata = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\CategoryInterface::class);
731+
$isActiveAttributeId = $this->config->getAttribute(Category::ENTITY, 'is_active')->getId();
732+
$categoryMetadata = $this->metadataPool->getMetadata(CategoryInterface::class);
720733
$categoryLinkField = $categoryMetadata->getLinkField();
721734
$selects = $this->prepareSelectsByRange(
722735
$this->connection->select()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Model\Product\Attribute;
9+
10+
use Magento\Catalog\Model\Attribute\Config;
11+
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
12+
use Magento\Framework\Exception\LocalizedException;
13+
14+
class AttributeSetUnassignValidator implements AttributeSetUnassignValidatorInterface
15+
{
16+
/**
17+
* @var array
18+
*/
19+
private array $unassignable;
20+
21+
/**
22+
* @param Config $attributeConfig
23+
*/
24+
public function __construct(
25+
private readonly Config $attributeConfig
26+
) {
27+
}
28+
29+
/**
30+
* @inheritDoc
31+
*/
32+
public function validate(AbstractAttribute $attribute, int $attributeSetId): void
33+
{
34+
if (!isset($this->unassignable)) {
35+
$this->unassignable = $this->attributeConfig->getAttributeNames('unassignable');
36+
}
37+
if (in_array($attribute->getAttributeCode(), $this->unassignable)) {
38+
throw new LocalizedException(
39+
__("The system attribute can't be deleted.")
40+
);
41+
}
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Catalog\Model\Product\Attribute;
9+
10+
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\Model\AbstractModel;
13+
14+
/**
15+
* Interface to validate attribute removal from an attribute set
16+
*/
17+
interface AttributeSetUnassignValidatorInterface
18+
{
19+
/**
20+
* Validate attribute
21+
*
22+
* @param AbstractModel $attribute
23+
* @param int $attributeSetId
24+
* @return void
25+
* @throws LocalizedException
26+
*/
27+
public function validate(AbstractAttribute $attribute, int $attributeSetId): void;
28+
}

0 commit comments

Comments
 (0)