Skip to content

Commit c4f5060

Browse files
author
roman
committed
Merge branch 'MAGETWO-92163' of github.com:magento-qwerty/magento2ce into MAGETWO-92163
2 parents 88f99b2 + 44c11ec commit c4f5060

File tree

49 files changed

+359
-1239
lines changed

Some content is hidden

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

49 files changed

+359
-1239
lines changed

app/code/Magento/Catalog/Model/Product/Media/Config.php

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@
1010
use Magento\Store\Model\StoreManagerInterface;
1111

1212
/**
13-
* Catalog product media config
13+
* Catalog product media config.
1414
*
1515
* @api
16-
*
17-
* @author Magento Core Team <core@magentocommerce.com>
1816
* @since 100.0.2
1917
*/
2018
class Config implements ConfigInterface
@@ -31,6 +29,11 @@ class Config implements ConfigInterface
3129
*/
3230
private $attributeHelper;
3331

32+
/**
33+
* @var string[]
34+
*/
35+
private $mediaAttributeCodes;
36+
3437
/**
3538
* @param StoreManagerInterface $storeManager
3639
*/
@@ -40,8 +43,7 @@ public function __construct(StoreManagerInterface $storeManager)
4043
}
4144

4245
/**
43-
* Filesystem directory path of product images
44-
* relatively to media folder
46+
* Get filesystem directory path for product images relative to the media directory.
4547
*
4648
* @return string
4749
*/
@@ -51,8 +53,7 @@ public function getBaseMediaPathAddition()
5153
}
5254

5355
/**
54-
* Web-based directory path of product images
55-
* relatively to media folder
56+
* Get web-based directory path for product images relative to the media directory.
5657
*
5758
* @return string
5859
*/
@@ -62,15 +63,15 @@ public function getBaseMediaUrlAddition()
6263
}
6364

6465
/**
65-
* @return string
66+
* @inheritdoc
6667
*/
6768
public function getBaseMediaPath()
6869
{
6970
return 'catalog/product';
7071
}
7172

7273
/**
73-
* @return string
74+
* @inheritdoc
7475
*/
7576
public function getBaseMediaUrl()
7677
{
@@ -79,8 +80,7 @@ public function getBaseMediaUrl()
7980
}
8081

8182
/**
82-
* Filesystem directory path of temporary product images
83-
* relatively to media folder
83+
* Filesystem directory path of temporary product images relative to the media directory.
8484
*
8585
* @return string
8686
*/
@@ -90,6 +90,8 @@ public function getBaseTmpMediaPath()
9090
}
9191

9292
/**
93+
* Get temporary base media URL.
94+
*
9395
* @return string
9496
*/
9597
public function getBaseTmpMediaUrl()
@@ -100,24 +102,24 @@ public function getBaseTmpMediaUrl()
100102
}
101103

102104
/**
103-
* @param string $file
104-
* @return string
105+
* @inheritdoc
105106
*/
106107
public function getMediaUrl($file)
107108
{
108109
return $this->getBaseMediaUrl() . '/' . $this->_prepareFile($file);
109110
}
110111

111112
/**
112-
* @param string $file
113-
* @return string
113+
* @inheritdoc
114114
*/
115115
public function getMediaPath($file)
116116
{
117117
return $this->getBaseMediaPath() . '/' . $this->_prepareFile($file);
118118
}
119119

120120
/**
121+
* Get temporary media URL.
122+
*
121123
* @param string $file
122124
* @return string
123125
*/
@@ -127,8 +129,7 @@ public function getTmpMediaUrl($file)
127129
}
128130

129131
/**
130-
* Part of URL of temporary product images
131-
* relatively to media folder
132+
* Part of URL of temporary product images relative to the media directory.
132133
*
133134
* @param string $file
134135
* @return string
@@ -139,7 +140,7 @@ public function getTmpMediaShortUrl($file)
139140
}
140141

141142
/**
142-
* Part of URL of product images relatively to media folder
143+
* Part of URL of product images relatively to media folder.
143144
*
144145
* @param string $file
145146
* @return string
@@ -150,6 +151,8 @@ public function getMediaShortUrl($file)
150151
}
151152

152153
/**
154+
* Get path to the temporary media.
155+
*
153156
* @param string $file
154157
* @return string
155158
*/
@@ -159,6 +162,8 @@ public function getTmpMediaPath($file)
159162
}
160163

161164
/**
165+
* Process file path.
166+
*
162167
* @param string $file
163168
* @return string
164169
*/
@@ -168,15 +173,23 @@ protected function _prepareFile($file)
168173
}
169174

170175
/**
176+
* Get codes of media attribute.
177+
*
171178
* @return array
172179
* @since 100.0.4
173180
*/
174181
public function getMediaAttributeCodes()
175182
{
176-
return $this->getAttributeHelper()->getAttributeCodesByFrontendType('media_image');
183+
if (!isset($this->mediaAttributeCodes)) {
184+
// the in-memory object-level caching allows to prevent unnecessary calls to the DB
185+
$this->mediaAttributeCodes = $this->getAttributeHelper()->getAttributeCodesByFrontendType('media_image');
186+
}
187+
return $this->mediaAttributeCodes;
177188
}
178189

179190
/**
191+
* Get attribute helper.
192+
*
180193
* @return Attribute
181194
*/
182195
private function getAttributeHelper()

app/code/Magento/CatalogGraphQl/Model/AttributesJoiner.php

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
*/
1616
class AttributesJoiner
1717
{
18+
/**
19+
* @var array
20+
*/
21+
private $queryFields = [];
22+
1823
/**
1924
* Join fields attached to field node to collection's select.
2025
*
@@ -24,17 +29,33 @@ class AttributesJoiner
2429
*/
2530
public function join(FieldNode $fieldNode, AbstractCollection $collection) : void
2631
{
27-
$query = $fieldNode->selectionSet->selections;
28-
29-
/** @var FieldNode $field */
30-
foreach ($query as $field) {
31-
if ($field->kind === 'InlineFragment') {
32-
continue;
32+
foreach ($this->getQueryFields($fieldNode) as $field) {
33+
if (!$collection->isAttributeAdded($field)) {
34+
$collection->addAttributeToSelect($field);
3335
}
36+
}
37+
}
3438

35-
if (!$collection->isAttributeAdded($field->name->value)) {
36-
$collection->addAttributeToSelect($field->name->value);
39+
/**
40+
* Get an array of queried fields.
41+
*
42+
* @param FieldNode $fieldNode
43+
* @return string[]
44+
*/
45+
public function getQueryFields(FieldNode $fieldNode)
46+
{
47+
if (!isset($this->queryFields[$fieldNode->name->value])) {
48+
$this->queryFields[$fieldNode->name->value] = [];
49+
$query = $fieldNode->selectionSet->selections;
50+
/** @var FieldNode $field */
51+
foreach ($query as $field) {
52+
if ($field->kind === 'InlineFragment') {
53+
continue;
54+
}
55+
$this->queryFields[$fieldNode->name->value][] = $field->name->value;
3756
}
3857
}
58+
59+
return $this->queryFields[$fieldNode->name->value];
3960
}
4061
}

app/code/Magento/CatalogGraphQl/Model/Category/Hydrator.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\CatalogGraphQl\Model\Category;
99

1010
use Magento\Catalog\Api\Data\CategoryInterface;
11+
use Magento\Catalog\Model\Category;
1112
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\CustomAttributesFlattener;
1213
use Magento\Framework\Reflection\DataObjectProcessor;
1314

@@ -41,14 +42,19 @@ public function __construct(
4142
/**
4243
* Hydrate and flatten category object to flat array
4344
*
44-
* @param CategoryInterface $category
45+
* @param Category $category
46+
* @param bool $basicFieldsOnly Set to false to avoid expensive hydration, used for performance optimization
4547
* @return array
4648
*/
47-
public function hydrateCategory(CategoryInterface $category) : array
49+
public function hydrateCategory(Category $category, $basicFieldsOnly = false) : array
4850
{
49-
$categoryData = $this->dataObjectProcessor->buildOutputDataArray($category, CategoryInterface::class);
51+
if ($basicFieldsOnly) {
52+
$categoryData = $category->getData();
53+
} else {
54+
$categoryData = $this->dataObjectProcessor->buildOutputDataArray($category, CategoryInterface::class);
55+
$categoryData['product_count'] = $category->getProductCount();
56+
}
5057
$categoryData['id'] = $category->getId();
51-
$categoryData['product_count'] = $category->getProductCount();
5258
$categoryData['children'] = [];
5359
$categoryData['available_sort_by'] = $category->getAvailableSortBy();
5460
return $this->flattener->flatten($categoryData);

app/code/Magento/CatalogGraphQl/Model/Resolver/Categories.php

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use Magento\Framework\GraphQl\Config\Element\Field;
1818
use Magento\Framework\GraphQl\Query\ResolverInterface;
1919
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory;
20-
use Magento\Framework\Reflection\DataObjectProcessor;
20+
use Magento\CatalogGraphQl\Model\Category\Hydrator as CategoryHydrator;
2121

2222
/**
2323
* Resolver for category objects the product is assigned to.
@@ -36,11 +36,6 @@ class Categories implements ResolverInterface
3636
*/
3737
private $categoryIds = [];
3838

39-
/**
40-
* @var DataObjectProcessor
41-
*/
42-
private $dataObjectProcessor;
43-
4439
/**
4540
* @var AttributesJoiner
4641
*/
@@ -57,29 +52,34 @@ class Categories implements ResolverInterface
5752
private $valueFactory;
5853

5954
/**
60-
* Category constructor.
55+
* @var CategoryHydrator
56+
*/
57+
private $categoryHydrator;
58+
59+
/**
6160
* @param CollectionFactory $collectionFactory
62-
* @param DataObjectProcessor $dataObjectProcessor
6361
* @param AttributesJoiner $attributesJoiner
6462
* @param CustomAttributesFlattener $customAttributesFlattener
6563
* @param ValueFactory $valueFactory
64+
* @param CategoryHydrator $categoryHydrator
6665
*/
6766
public function __construct(
6867
CollectionFactory $collectionFactory,
69-
DataObjectProcessor $dataObjectProcessor,
7068
AttributesJoiner $attributesJoiner,
7169
CustomAttributesFlattener $customAttributesFlattener,
72-
ValueFactory $valueFactory
70+
ValueFactory $valueFactory,
71+
CategoryHydrator $categoryHydrator
7372
) {
7473
$this->collection = $collectionFactory->create();
75-
$this->dataObjectProcessor = $dataObjectProcessor;
7674
$this->attributesJoiner = $attributesJoiner;
7775
$this->customAttributesFlattener = $customAttributesFlattener;
7876
$this->valueFactory = $valueFactory;
77+
$this->categoryHydrator = $categoryHydrator;
7978
}
8079

8180
/**
82-
* {@inheritdoc}
81+
* @inheritdoc
82+
*
8383
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
8484
*/
8585
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
@@ -107,13 +107,17 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
107107
/** @var CategoryInterface | \Magento\Catalog\Model\Category $item */
108108
foreach ($this->collection as $item) {
109109
if (in_array($item->getId(), $categoryIds)) {
110-
$categories[$item->getId()] = $this->dataObjectProcessor->buildOutputDataArray(
111-
$item,
112-
CategoryInterface::class
113-
);
114-
$categories[$item->getId()] = $this->customAttributesFlattener
115-
->flatten($categories[$item->getId()]);
116-
$categories[$item->getId()]['product_count'] = $item->getProductCount();
110+
// Try to extract all requested fields from the loaded collection data
111+
$categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item, true);
112+
$requestedFields = $that->attributesJoiner->getQueryFields($info->fieldNodes[0]);
113+
$extractedFields = array_keys($categories[$item->getId()]);
114+
$foundFields = array_intersect($requestedFields, $extractedFields);
115+
if (count($requestedFields) === count($foundFields)) {
116+
continue;
117+
}
118+
119+
// If not all requested fields were extracted from the collection, start more complex extraction
120+
$categories[$item->getId()] = $this->categoryHydrator->hydrateCategory($item);
117121
}
118122
}
119123

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Query\ResolverInterface;
12+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
13+
14+
/**
15+
* Layered navigation filters resolver, used for GraphQL request processing.
16+
*/
17+
class LayerFilters implements ResolverInterface
18+
{
19+
/**
20+
* @var Layer\DataProvider\Filters
21+
*/
22+
private $filtersDataProvider;
23+
24+
/**
25+
* @param \Magento\CatalogGraphQl\Model\Resolver\Layer\DataProvider\Filters $filtersDataProvider
26+
*/
27+
public function __construct(
28+
\Magento\CatalogGraphQl\Model\Resolver\Layer\DataProvider\Filters $filtersDataProvider
29+
) {
30+
$this->filtersDataProvider = $filtersDataProvider;
31+
}
32+
33+
/**
34+
* @inheritdoc
35+
*/
36+
public function resolve(
37+
Field $field,
38+
$context,
39+
ResolveInfo $info,
40+
array $value = null,
41+
array $args = null
42+
) {
43+
if (!isset($value['layer_type'])) {
44+
return null;
45+
}
46+
47+
return $this->filtersDataProvider->getData($value['layer_type']);
48+
}
49+
}

0 commit comments

Comments
 (0)