Skip to content

Commit fe841f8

Browse files
committed
Merge branch '2.4-develop' of https://github.com/magento-commerce/magento2ce into ACP2E-2504
2 parents 96e5bb9 + f6d4542 commit fe841f8

File tree

121 files changed

+3650
-458
lines changed

Some content is hidden

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

121 files changed

+3650
-458
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* ADOBE CONFIDENTIAL
5+
* ___________________
6+
*
7+
* Copyright 2014 Adobe
8+
* All Rights Reserved.
9+
*
10+
* NOTICE: All information contained herein is, and remains
11+
* the property of Adobe and its suppliers, if any. The intellectual
12+
* and technical concepts contained herein are proprietary to Adobe
13+
* and its suppliers and are protected by all applicable intellectual
14+
* property laws, including trade secret and copyright laws.
15+
* Dissemination of this information or reproduction of this material
16+
* is strictly forbidden unless prior written permission is obtained
17+
* from Adobe.
18+
* ************************************************************************
19+
*/
20+
declare(strict_types=1);
21+
22+
namespace Magento\Catalog\Api;
23+
24+
/**
25+
* Intended to allow setting 'is_filterable' property for specific attribute as integer value via REST/SOAP API
26+
*
27+
* @api
28+
*/
29+
interface ProductAttributeIsFilterableManagementInterface
30+
{
31+
/**
32+
* Retrieve 'is_filterable' property for specific attribute as integer
33+
*
34+
* @param string $attributeCode
35+
* @return int
36+
* @throws \Magento\Framework\Exception\NoSuchEntityException
37+
*/
38+
public function get(string $attributeCode): int;
39+
40+
/**
41+
* Set 'is_filterable' property for specific attribute as integer
42+
*
43+
* @param string $attributeCode
44+
* @param int $isFilterable
45+
* @return bool
46+
* @throws \Magento\Framework\Exception\NoSuchEntityException
47+
* @throws \Magento\Framework\Exception\InputException
48+
* @throws \Magento\Framework\Exception\StateException
49+
*/
50+
public function set(string $attributeCode, int $isFilterable): bool;
51+
}

app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Catalog\Model\Entity\Attribute;
1414
use Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker;
1515
use Magento\Framework\Data\FormFactory;
16+
use Magento\Framework\Exception\LocalizedException;
1617
use Magento\Framework\Registry;
1718

1819
/**
@@ -58,6 +59,7 @@ public function __construct(
5859
* @inheritDoc
5960
* @return $this
6061
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
62+
* @throws LocalizedException
6163
*/
6264
protected function _prepareForm()
6365
{
@@ -176,28 +178,34 @@ protected function _prepareForm()
176178
['form' => $form, 'attribute' => $attributeObject]
177179
);
178180

181+
$dependencies = $this->getLayout()->createBlock(
182+
\Magento\Backend\Block\Widget\Form\Element\Dependence::class
183+
)->addFieldMap(
184+
"is_html_allowed_on_front",
185+
'html_allowed_on_front'
186+
)->addFieldMap(
187+
"frontend_input",
188+
'frontend_input_type'
189+
)->addFieldMap(
190+
"is_searchable",
191+
'searchable'
192+
)->addFieldMap(
193+
"is_visible_in_advanced_search",
194+
'advanced_search'
195+
)->addFieldDependence(
196+
'advanced_search',
197+
'searchable',
198+
'1'
199+
);
200+
$this->_eventManager->dispatch(
201+
'adminhtml_catalog_product_attribute_edit_frontend_prepare_field_dependencies',
202+
['dependencies' => $dependencies]
203+
);
204+
179205
// define field dependencies
180206
$this->setChild(
181207
'form_after',
182-
$this->getLayout()->createBlock(
183-
\Magento\Backend\Block\Widget\Form\Element\Dependence::class
184-
)->addFieldMap(
185-
"is_html_allowed_on_front",
186-
'html_allowed_on_front'
187-
)->addFieldMap(
188-
"frontend_input",
189-
'frontend_input_type'
190-
)->addFieldMap(
191-
"is_searchable",
192-
'searchable'
193-
)->addFieldMap(
194-
"is_visible_in_advanced_search",
195-
'advanced_search'
196-
)->addFieldDependence(
197-
'advanced_search',
198-
'searchable',
199-
'1'
200-
)
208+
$dependencies
201209
);
202210

203211
$this->setForm($form);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* ADOBE CONFIDENTIAL
5+
* ___________________
6+
*
7+
* Copyright 2014 Adobe
8+
* All Rights Reserved.
9+
*
10+
* NOTICE: All information contained herein is, and remains
11+
* the property of Adobe and its suppliers, if any. The intellectual
12+
* and technical concepts contained herein are proprietary to Adobe
13+
* and its suppliers and are protected by all applicable intellectual
14+
* property laws, including trade secret and copyright laws.
15+
* Dissemination of this information or reproduction of this material
16+
* is strictly forbidden unless prior written permission is obtained
17+
* from Adobe.
18+
* ************************************************************************
19+
*/
20+
declare(strict_types=1);
21+
22+
namespace Magento\Catalog\Model\Product\Attribute;
23+
24+
use Magento\Catalog\Api\ProductAttributeIsFilterableManagementInterface;
25+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
26+
27+
class IsFilterableManagement implements ProductAttributeIsFilterableManagementInterface
28+
{
29+
/**
30+
* @var ProductAttributeRepositoryInterface
31+
*/
32+
private ProductAttributeRepositoryInterface $productAttributeRepository;
33+
34+
/**
35+
* @param ProductAttributeRepositoryInterface $productAttributeRepository
36+
*/
37+
public function __construct(
38+
ProductAttributeRepositoryInterface $productAttributeRepository
39+
) {
40+
$this->productAttributeRepository = $productAttributeRepository;
41+
}
42+
43+
/**
44+
* @inheritdoc
45+
*/
46+
public function get(string $attributeCode): int
47+
{
48+
$attribute = $this->productAttributeRepository->get($attributeCode);
49+
50+
return (int)$attribute->getIsFilterable();
51+
}
52+
53+
/**
54+
* @inheritdoc
55+
*/
56+
public function set(string $attributeCode, int $isFilterable): bool
57+
{
58+
$attribute = $this->productAttributeRepository->get($attributeCode);
59+
$attribute->setIsFilterable($isFilterable);
60+
$this->productAttributeRepository->save($attribute);
61+
62+
return true;
63+
}
64+
}

app/code/Magento/Catalog/Model/ResourceModel/Category/Collection.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
* Category resource collection
1717
*
1818
* @api
19-
* @author Magento Core Team <core@magentocommerce.com>
2019
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2120
* @since 100.0.2
2221
*/
@@ -568,8 +567,7 @@ private function getProductsCountFromCategoryTable(Category $item, string $websi
568567
*/
569568
private function getProductsCountQuery(array $categoryIds, $addVisibilityFilter = true): Select
570569
{
571-
$connections = $this->_resource->getConnection();
572-
$categoryTable = $connections->getTableName('catalog_category_product_index');
570+
$categoryTable = $this->_resource->getTableName('catalog_category_product_index');
573571
$select = $this->_conn->select()
574572
->from(
575573
['cat_index' => $categoryTable],

app/code/Magento/Catalog/Test/Mftf/Test/SavingCustomAttributeValuesUsingUITest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
<actionGroup ref="AdminSetProductAttributeUseInLayeredNavigationOptionActionGroup" stepKey="setDropdownUseInLayeredNavigationNoResults">
5656
<argument name="useInLayeredNavigationValue" value="Filterable (with results)"/>
5757
</actionGroup>
58+
<selectOption selector="{{AdvancedAttributePropertiesSection.UseInSearch}}" userInput="Yes" stepKey="selectIsSearchAble"/>
5859
<selectOption selector="{{AttributePropertiesSection.useInSearchResultsLayeredNavigation}}" userInput="Yes" stepKey="selectUseInLayeredNavigationOption"/>
5960
<click stepKey="saveAttribute" selector="{{AttributePropertiesSection.Save}}"/>
6061

app/code/Magento/Catalog/etc/di.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
<preference for="Magento\Catalog\Model\ProductLink\Data\ListCriteriaInterface" type="Magento\Catalog\Model\ProductLink\Data\ListCriteria" />
7878
<preference for="Magento\Catalog\Api\CategoryListDeleteBySkuInterface" type="Magento\Catalog\Model\CategoryLinkRepository"/>
7979
<preference for="Magento\Theme\CustomerData\MessagesProviderInterface" type="Magento\Catalog\Model\Theme\CustomerData\MessagesProvider"/>
80+
<preference for="Magento\Catalog\Api\ProductAttributeIsFilterableManagementInterface" type="Magento\Catalog\Model\Product\Attribute\IsFilterableManagement" />
8081
<type name="Magento\Customer\Model\ResourceModel\Visitor">
8182
<plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" />
8283
</type>

app/code/Magento/Catalog/etc/webapi.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@
5151
<resource ref="Magento_Catalog::attributes_attributes" />
5252
</resources>
5353
</route>
54+
<route url="/V1/products/attributes/:attributeCode/is-filterable" method="GET">
55+
<service class="Magento\Catalog\Api\ProductAttributeIsFilterableManagementInterface" method="get"/>
56+
<resources>
57+
<resource ref="Magento_Catalog::attributes_attributes" />
58+
</resources>
59+
</route>
5460
<route url="/V1/products/attributes" method="GET">
5561
<service class="Magento\Catalog\Api\ProductAttributeRepositoryInterface" method="getList" />
5662
<resources>
@@ -87,6 +93,12 @@
8793
<resource ref="Magento_Catalog::attributes_attributes" />
8894
</resources>
8995
</route>
96+
<route url="/V1/products/attributes/:attributeCode/is-filterable/:isFilterable" method="PUT">
97+
<service class="Magento\Catalog\Api\ProductAttributeIsFilterableManagementInterface" method="set"/>
98+
<resources>
99+
<resource ref="Magento_Catalog::attributes_attributes" />
100+
</resources>
101+
</route>
90102
<route url="/V1/products/attributes/:attributeCode" method="DELETE">
91103
<service class="Magento\Catalog\Api\ProductAttributeRepositoryInterface" method="deleteById"/>
92104
<resources>

app/code/Magento/CatalogCustomerGraphQl/Model/Resolver/PriceTiers.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,6 @@ public function resolve(
125125
return [];
126126
}
127127

128-
if (!$product->getTierPrices()) {
129-
return [];
130-
}
131-
132128
$productId = (int)$product->getId();
133129
$this->tiers->addProductFilter($productId);
134130

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
/************************************************************************
3+
*
4+
* Copyright 2023 Adobe
5+
* All Rights Reserved.
6+
*
7+
* NOTICE: All information contained herein is, and remains
8+
* the property of Adobe and its suppliers, if any. The intellectual
9+
* and technical concepts contained herein are proprietary to Adobe
10+
* and its suppliers and are protected by all applicable intellectual
11+
* property laws, including trade secret and copyright laws.
12+
* Dissemination of this information or reproduction of this material
13+
* is strictly forbidden unless prior written permission is obtained
14+
* from Adobe.
15+
* ************************************************************************
16+
*/
17+
declare(strict_types=1);
18+
19+
namespace Magento\CatalogCustomerGraphQl\Test\Unit\Model\Resolver;
20+
21+
use Magento\CatalogCustomerGraphQl\Model\Resolver\Customer\GetCustomerGroup;
22+
use Magento\CatalogCustomerGraphQl\Model\Resolver\PriceTiers;
23+
use Magento\CatalogCustomerGraphQl\Model\Resolver\Product\Price\Tiers;
24+
use Magento\CatalogCustomerGraphQl\Model\Resolver\Product\Price\TiersFactory;
25+
use Magento\CatalogGraphQl\Model\Resolver\Product\Price\Discount;
26+
use Magento\CatalogGraphQl\Model\Resolver\Product\Price\ProviderPool;
27+
use Magento\Directory\Model\PriceCurrency;
28+
use Magento\Framework\GraphQl\Config\Element\Field;
29+
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory;
30+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
31+
use Magento\GraphQl\Model\Query\Context;
32+
use PHPUnit\Framework\TestCase;
33+
use PHPUnit\Framework\MockObject\MockObject;
34+
35+
/**
36+
* Test Resolver for PriceTiers
37+
*/
38+
class PriceTiersTest extends TestCase
39+
{
40+
/**
41+
* @var Field|MockObject
42+
*/
43+
private $fieldMock;
44+
45+
/**
46+
* @var ResolveInfo|MockObject
47+
*/
48+
private $resolveInfoMock;
49+
50+
/**
51+
* @var Context|MockObject
52+
*/
53+
private $contextMock;
54+
55+
/**
56+
* @var TiersFactory|MockObject
57+
*/
58+
private $tiersFactory;
59+
60+
/**
61+
* @var PriceTiers
62+
*/
63+
private $priceTiers;
64+
65+
protected function setUp(): void
66+
{
67+
$valueFactory = $this->createMock(ValueFactory::class);
68+
$this->tiersFactory = $this->createMock(TiersFactory::class);
69+
$customerGroup = $this->createMock(GetCustomerGroup::class);
70+
$priceDiscount = $this->createMock(Discount::class);
71+
$providerPool = $this->createMock(ProviderPool::class);
72+
$priceCurrency = $this->createMock(PriceCurrency::class);
73+
$this->priceTiers = new PriceTiers(
74+
$valueFactory,
75+
$this->tiersFactory,
76+
$customerGroup,
77+
$priceDiscount,
78+
$providerPool,
79+
$priceCurrency
80+
);
81+
82+
$this->fieldMock = $this->createMock(Field::class);
83+
$this->resolveInfoMock = $this->createMock(ResolveInfo::class);
84+
$this->contextMock = $this->createMock(Context::class);
85+
}
86+
87+
public function testResolve()
88+
{
89+
$tiers = $this->createMock(Tiers::class);
90+
$tiers->expects($this->once())
91+
->method('addProductFilter')
92+
->willReturnSelf();
93+
94+
$this->tiersFactory->expects($this->once())
95+
->method('create')
96+
->willReturn($tiers);
97+
98+
$productMock = $this->createMock(\Magento\Catalog\Model\Product::class);
99+
$productMock->expects($this->never())
100+
->method('getTierPrices');
101+
102+
$productMock->expects($this->once())
103+
->method('getId')
104+
->willReturn(1);
105+
106+
$valueMock = ['model' => $productMock];
107+
108+
$this->priceTiers->resolve($this->fieldMock, $this->contextMock, $this->resolveInfoMock, $valueMock);
109+
}
110+
}

0 commit comments

Comments
 (0)