Skip to content

Commit 308de2f

Browse files
authored
Merge pull request #8592 from magento-l3/PR-10122023
Pr 10122023
2 parents 9e2eb99 + 8e04b14 commit 308de2f

File tree

22 files changed

+728
-50
lines changed

22 files changed

+728
-50
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+
}
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/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+
}

app/code/Magento/CatalogGraphQl/Model/Resolver/Product/Price/Provider.php

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,68 @@
1717
*/
1818
class Provider implements ProviderInterface
1919
{
20+
/**
21+
* @var array
22+
*/
23+
private $minimalPrice = [
24+
FinalPrice::PRICE_CODE => [],
25+
RegularPrice::PRICE_CODE => []
26+
];
27+
28+
/**
29+
* @var array
30+
*/
31+
private $maximalPrice = [
32+
FinalPrice::PRICE_CODE => [],
33+
RegularPrice::PRICE_CODE => []
34+
];
35+
2036
/**
2137
* @inheritdoc
2238
*/
2339
public function getMinimalFinalPrice(SaleableInterface $product): AmountInterface
2440
{
25-
/** @var FinalPrice $finalPrice */
26-
$finalPrice = $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE);
27-
return $finalPrice->getMinimalPrice();
41+
if (!isset($this->minimalPrice[FinalPrice::PRICE_CODE][$product->getId()])) {
42+
/** @var FinalPrice $finalPrice */
43+
$finalPrice = $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE);
44+
$this->minimalPrice[FinalPrice::PRICE_CODE][$product->getId()] = $finalPrice->getMinimalPrice();
45+
}
46+
return $this->minimalPrice[FinalPrice::PRICE_CODE][$product->getId()];
2847
}
2948

3049
/**
3150
* @inheritdoc
3251
*/
3352
public function getMinimalRegularPrice(SaleableInterface $product): AmountInterface
3453
{
35-
return $this->getRegularPrice($product);
54+
if (!isset($this->minimalPrice[RegularPrice::PRICE_CODE][$product->getId()])) {
55+
$this->minimalPrice[RegularPrice::PRICE_CODE][$product->getId()] = $this->getRegularPrice($product);
56+
}
57+
return $this->minimalPrice[RegularPrice::PRICE_CODE][$product->getId()];
3658
}
3759

3860
/**
3961
* @inheritdoc
4062
*/
4163
public function getMaximalFinalPrice(SaleableInterface $product): AmountInterface
4264
{
43-
/** @var FinalPrice $finalPrice */
44-
$finalPrice = $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE);
45-
return $finalPrice->getMaximalPrice();
65+
if (!isset($this->maximalPrice[FinalPrice::PRICE_CODE][$product->getId()])) {
66+
/** @var FinalPrice $finalPrice */
67+
$finalPrice = $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE);
68+
$this->maximalPrice[FinalPrice::PRICE_CODE][$product->getId()] = $finalPrice->getMaximalPrice();
69+
}
70+
return $this->maximalPrice[FinalPrice::PRICE_CODE][$product->getId()];
4671
}
4772

4873
/**
4974
* @inheritdoc
5075
*/
5176
public function getMaximalRegularPrice(SaleableInterface $product): AmountInterface
5277
{
53-
return $this->getRegularPrice($product);
78+
if (!isset($this->maximalPrice[RegularPrice::PRICE_CODE][$product->getId()])) {
79+
$this->maximalPrice[RegularPrice::PRICE_CODE][$product->getId()] = $this->getRegularPrice($product);
80+
}
81+
return $this->maximalPrice[RegularPrice::PRICE_CODE][$product->getId()];
5482
}
5583

5684
/**

app/code/Magento/ConfigurableProduct/Test/Fixture/Attribute.php

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,12 @@
77

88
namespace Magento\ConfigurableProduct\Test\Fixture;
99

10+
use Magento\Catalog\Test\Fixture\SelectAttribute;
1011
use Magento\Framework\DataObject;
1112

12-
class Attribute extends \Magento\Catalog\Test\Fixture\Attribute
13+
class Attribute extends SelectAttribute
1314
{
1415
private const DEFAULT_DATA = [
15-
'frontend_input' => 'select',
16-
'options' => [
17-
[
18-
'label' => 'option1%uniqid%',
19-
'sort_order' => 0,
20-
],
21-
[
22-
'label' => 'option2%uniqid%',
23-
'sort_order' => 1,
24-
]
25-
],
2616
'scope' => 'global',
2717
];
2818

app/code/Magento/ConfigurableProduct/Test/Fixture/Product.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,15 @@ static function (array $value) {
197197
);
198198
$variationIndex = 0;
199199
foreach ($variations as $variation) {
200-
foreach ($variation as $attributeId => $valueInfo) {
201-
if (isset($links[$variationIndex]) && $links[$variationIndex] !== 0) {
200+
if (isset($links[$variationIndex]) && $links[$variationIndex] !== 0) {
201+
foreach ($variation as $attributeId => $valueInfo) {
202202
$attribute = $this->eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $attributeId);
203203
$product = $this->productRepository->getById($links[$variationIndex]);
204204
$product->setCustomAttribute($attribute->getAttributeCode(), $valueInfo['value']);
205205
$this->productRepository->save($product);
206206
}
207-
$variationIndex++;
208207
}
208+
$variationIndex++;
209209
}
210210
}
211211
}

0 commit comments

Comments
 (0)