Skip to content

Commit

Permalink
Stop loading products all over again each time we request attributes. (
Browse files Browse the repository at this point in the history
…#24)

* Reworked attribbutes and rating fields as they were hyper ineeficent each loading data on its own.

* Fixed PHPDOC

* Fixed entries getting lost in schema

* Reworked to use countinue

* Fied CR
  • Loading branch information
alfredsgenkins authored Oct 23, 2019
1 parent 3750a6f commit 9d298d4
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 24 deletions.
43 changes: 23 additions & 20 deletions src/Model/Resolver/AttributesWithValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,22 @@ public function __construct(
$this->productRepository = $productRepository;
}

protected function getAttributeOptions($attr, $rawOptions) {
if (!$this->swatchHelper->isSwatchAttribute($attr)) return [];

$optionIds = array_map(function ($option) { return $option['value']; }, $rawOptions);
$swatchOptions = $this->swatchHelper->getSwatchesByOptionsId($optionIds);

return array_map(function ($option) use ($swatchOptions) {
$option['swatch_data'] = $swatchOptions[$option['value']] ?? [];
return $option;
}, $rawOptions);
}

/**
* Fetches the data from persistence models and format it according to the GraphQL schema.
*
* @param \Magento\Framework\GraphQl\Config\Element\Field $field
* @param Field $field
* @param ContextInterface $context
* @param ResolveInfo $info
* @param array|null $value
Expand All @@ -65,30 +77,21 @@ public function resolve(
array $value = null,
array $args = null
) {
$product = $this->productRepository->getById($value['entity_id']);
$attributes = $product->getAttributes();
$product = $value['model'];
$attributesToReturn = [];

foreach ($attributes as $attribute) {
if ($attribute->getIsVisibleOnFront()) {
$productAttribute = $product->getCustomAttribute($attribute->getAttributeCode());

$rawOptions = $attribute->getSource()->getAllOptions(true, true);
foreach ($product->getAttributes() as $attr) {
if ($attr->getIsVisibleOnFront()) {
$rawOptions = $attr->getSource()->getAllOptions(true, true);
array_shift($rawOptions);

$optionIds = array_map(function ($option) { return $option['value']; }, $rawOptions);
$swatchOptions = $this->swatchHelper->getSwatchesByOptionsId($optionIds);

$attributesToReturn[] = [
'attribute_value' => $productAttribute ? $productAttribute->getValue() : null,
'attribute_code' => $attribute->getAttributeCode(),
'attribute_type' => $attribute->getFrontendInput(),
'attribute_label' => $attribute->getFrontendLabel(),
'attribute_id' => $attribute->getAttributeId(),
'attribute_options' => array_map(function ($option) use ($swatchOptions) {
$option['swatch_data'] = $swatchOptions[$option['value']] ?? [];
return $option;
}, $rawOptions)
'attribute_value' => $attr ? $attr->getValue() : null,
'attribute_code' => $attr->getAttributeCode(),
'attribute_type' => $attr->getFrontendInput(),
'attribute_label' => $attr->getFrontendLabel(),
'attribute_id' => $attr->getAttributeId(),
'attribute_options' => $this->getAttributeOptions($attr, $rawOptions)
];
}
}
Expand Down
26 changes: 23 additions & 3 deletions src/Model/Resolver/Products/DataProvider/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@
namespace ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider;

use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory;
use Magento\Framework\Api\SearchResultsInterface;
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessorInterface;
use Magento\Framework\Exception\LocalizedException;
use ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CriteriaCheck;
use Magento\Review\Model\Review;
use Magento\Review\Model\ResourceModel\Review\Product\Collection as ProductCollection;

/**
* Product field data provider, used for GraphQL resolver processing.
Expand Down Expand Up @@ -56,17 +60,26 @@ class Product extends \Magento\CatalogGraphQl\Model\Resolver\Products\DataProvid
private $maxPrice;

/**
* @var Review
*/
protected $review;

/**
* Product constructor.
* @param CollectionFactory $collectionFactory
* @param ProductSearchResultsInterfaceFactory $searchResultsFactory
* @param Visibility $visibility
* @param CollectionProcessorInterface $collectionProcessor
* @param Review $review
*/
public function __construct(
CollectionFactory $collectionFactory,
ProductSearchResultsInterfaceFactory $searchResultsFactory,
Visibility $visibility,
CollectionProcessorInterface $collectionProcessor
CollectionProcessorInterface $collectionProcessor,
Review $review
) {
$this->review = $review;
$this->collectionFactory = $collectionFactory;
$this->searchResultsFactory = $searchResultsFactory;
$this->visibility = $visibility;
Expand All @@ -81,14 +94,15 @@ public function __construct(
* @param bool $isSearch
* @param bool $isChildSearch
* @return SearchResultsInterface
* @throws LocalizedException
*/
public function getList(
SearchCriteriaInterface $searchCriteria,
array $attributes = [],
bool $isSearch = false,
bool $isChildSearch = false
): SearchResultsInterface {
/** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
/** @var Collection $collection */
$collection = $this->collectionFactory->create();

$this->collectionProcessor->process($collection, $searchCriteria, $attributes);
Expand All @@ -115,6 +129,12 @@ public function getList(
$collection->addOptionsToResult();
}

if (in_array('review_summary', $attributes)) {
/** @var ProductCollection $collection */
// Only getItems is used inside
$this->review->appendSummary($collection);
}

$searchResult = $this->searchResultsFactory->create();
$searchResult->setSearchCriteria($searchCriteria);
$searchResult->setItems($collection->getItems());
Expand All @@ -126,7 +146,7 @@ public function getList(


/**
* @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
* @param Collection $collection
* @return array
*/
public function getCollectionMinMaxPrice($collection)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor;

use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessorInterface;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Store\Model\StoreManagerInterface;

/**
* Adds passed in attributes to product collection results
*
* {@inheritdoc}
*/
class AttributeProcessor implements CollectionProcessorInterface
{
const ATTRIBUTES_FIELD = 'attributes';

/**
* @var CollectionFactory
*/
protected $collectionFactory;

/**
* @var StoreManagerInterface
*/
protected $storeManager;

/**
* FilterableAttributeList constructor
*
* @param CollectionFactory $collectionFactory
* @param StoreManagerInterface $storeManager
*/
public function __construct(
CollectionFactory $collectionFactory,
StoreManagerInterface $storeManager
) {
$this->collectionFactory = $collectionFactory;
$this->storeManager = $storeManager;
}

protected function getAttributesVisibleOnFrontend() {
$collection = $this->collectionFactory->create();
$collection->setItemObjectClass(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class)
->addStoreLabel($this->storeManager->getStore()->getId())
->setOrder('position', 'ASC');

// Add filter by storefront visibility
$collection->addFieldToFilter('additional_table.is_visible_on_front', ['gt' => 0]);
return $collection->load();
}

/**
* {@inheritdoc}
*/
public function process(
Collection $collection,
SearchCriteriaInterface $searchCriteria,
array $attributeNames
): Collection {
foreach ($attributeNames as $name) {
if ($name !== self::ATTRIBUTES_FIELD) {
$collection->addAttributeToSelect($name);
continue;
}

$attributesVisibleOnFront = $this->getAttributesVisibleOnFrontend();

$attributeCodes = array_map(function($attr) {
return $attr->getAttributeCode();
}, $attributesVisibleOnFront->getItems());

$collection->addAttributeToSelect($attributeCodes);
}

return $collection;
}
}
6 changes: 5 additions & 1 deletion src/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
</type>

<preference for="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\StockProcessor"
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\StockProcessor"/>
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\StockProcessor" />

<preference for="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\AttributeProcessor"
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\AttributeProcessor" />


<virtualType name="ScandiPWA\CatalogGraphQl\Model\Search\PageSizeProvider" type="Magento\Search\Model\Search\PageSizeProvider">
<arguments>
Expand Down

0 comments on commit 9d298d4

Please sign in to comment.