Skip to content

Commit

Permalink
ENGCOM-3071: Fix regexp when filter by root category id #121
Browse files Browse the repository at this point in the history
  • Loading branch information
Valeriy Naida authored Oct 3, 2018
2 parents a6a822b + 413d3c8 commit 0571603
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 41 deletions.
16 changes: 14 additions & 2 deletions app/code/Magento/CatalogGraphQl/Model/Resolver/CategoryTree.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Magento\CatalogGraphQl\Model\Resolver;

use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ExtractDataFromCategoryTree;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
Expand All @@ -27,16 +28,26 @@ class CategoryTree implements ResolverInterface
*/
private $categoryTree;

/**
* @var ExtractDataFromCategoryTree
*/
private $extractDataFromCategoryTree;

/**
* @param \Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\CategoryTree $categoryTree
* @param ExtractDataFromCategoryTree $extractDataFromCategoryTree
*/
public function __construct(
\Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\CategoryTree $categoryTree
\Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\CategoryTree $categoryTree,
ExtractDataFromCategoryTree $extractDataFromCategoryTree
) {
$this->categoryTree = $categoryTree;
$this->extractDataFromCategoryTree = $extractDataFromCategoryTree;
}

/**
* Get category id
*
* @param array $args
* @return int
* @throws GraphQlInputException
Expand All @@ -62,7 +73,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
$rootCategoryId = $this->getCategoryId($args);
$categoriesTree = $this->categoryTree->getTree($info, $rootCategoryId);
if (!empty($categoriesTree)) {
return current($categoriesTree);
$result = $this->extractDataFromCategoryTree->execute($categoriesTree);
return current($result);
} else {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@

use GraphQL\Language\AST\FieldNode;
use Magento\CatalogGraphQl\Model\Category\DepthCalculator;
use Magento\CatalogGraphQl\Model\Category\Hydrator;
use Magento\CatalogGraphQl\Model\Category\LevelCalculator;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Catalog\Api\Data\CategoryInterface;
use Magento\Catalog\Model\ResourceModel\Category\Collection;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
use Magento\CatalogGraphQl\Model\AttributesJoiner;
use Magento\Catalog\Model\Category;

/**
* Category tree data provider
Expand Down Expand Up @@ -53,87 +53,64 @@ class CategoryTree
*/
private $metadata;

/**
* @var Hydrator
*/
private $hydrator;

/**
* @param CollectionFactory $collectionFactory
* @param AttributesJoiner $attributesJoiner
* @param DepthCalculator $depthCalculator
* @param LevelCalculator $levelCalculator
* @param MetadataPool $metadata
* @param Hydrator $hydrator
*/
public function __construct(
CollectionFactory $collectionFactory,
AttributesJoiner $attributesJoiner,
DepthCalculator $depthCalculator,
LevelCalculator $levelCalculator,
MetadataPool $metadata,
Hydrator $hydrator
MetadataPool $metadata
) {
$this->collectionFactory = $collectionFactory;
$this->attributesJoiner = $attributesJoiner;
$this->depthCalculator = $depthCalculator;
$this->levelCalculator = $levelCalculator;
$this->metadata = $metadata;
$this->hydrator = $hydrator;
}

/**
* Returns categories tree starting from parent $rootCategoryId
*
* @param ResolveInfo $resolveInfo
* @param int $rootCategoryId
* @return array
* @return \Iterator
*/
public function getTree(ResolveInfo $resolveInfo, int $rootCategoryId) : array
public function getTree(ResolveInfo $resolveInfo, int $rootCategoryId): \Iterator
{
$categoryQuery = $resolveInfo->fieldNodes[0];
$collection = $this->collectionFactory->create();
$this->joinAttributesRecursively($collection, $categoryQuery);
$depth = $this->depthCalculator->calculate($categoryQuery);
$level = $this->levelCalculator->calculate($rootCategoryId);

// If root category is being filter, we've to remove first slash
if ($rootCategoryId == Category::TREE_ROOT_ID) {
$regExpPathFilter = sprintf('.*%s/[/0-9]*$', $rootCategoryId);
} else {
$regExpPathFilter = sprintf('.*/%s/[/0-9]*$', $rootCategoryId);
}

//Search for desired part of category tree
$collection->addPathFilter(sprintf('.*/%s/[/0-9]*$', $rootCategoryId));
$collection->addPathFilter($regExpPathFilter);

$collection->addFieldToFilter('level', ['gt' => $level]);
$collection->addFieldToFilter('level', ['lteq' => $level + $depth - self::DEPTH_OFFSET]);
$collection->setOrder('level');
$collection->getSelect()->orWhere(
$this->metadata->getMetadata(CategoryInterface::class)->getIdentifierField() . ' = ?',
$rootCategoryId
);
return $this->processTree($collection->getIterator());
}

/**
* Iterates through category tree
*
* @param \Iterator $iterator
* @return array
*/
private function processTree(\Iterator $iterator) : array
{
$tree = [];
while ($iterator->valid()) {
/** @var CategoryInterface $category */
$category = $iterator->current();
$iterator->next();
$nextCategory = $iterator->current();
$tree[$category->getId()] = $this->hydrator->hydrateCategory($category);
$tree[$category->getId()]['model'] = $category;
if ($nextCategory && (int) $nextCategory->getLevel() !== (int) $category->getLevel()) {
$tree[$category->getId()]['children'] = $this->processTree($iterator);
}
}

return $tree;
return $collection->getIterator();
}

/**
* Joins EAV attributes recursively
* Join attributes recursively
*
* @param Collection $collection
* @param FieldNode $fieldNode
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider;

use Magento\CatalogGraphQl\Model\Category\Hydrator;
use Magento\Catalog\Api\Data\CategoryInterface;

/**
* Extract data from category tree
*/
class ExtractDataFromCategoryTree
{
/**
* @var Hydrator
*/
private $categoryHydrator;

/**
* @param Hydrator $categoryHydrator
*/
public function __construct(
Hydrator $categoryHydrator
) {
$this->categoryHydrator = $categoryHydrator;
}

/**
* Extract data from category tree
*
* @param \Iterator $iterator
* @return array
*/
public function execute(\Iterator $iterator): array
{
$tree = [];
while ($iterator->valid()) {
/** @var CategoryInterface $category */
$category = $iterator->current();
$iterator->next();
$nextCategory = $iterator->current();
$tree[$category->getId()] = $this->categoryHydrator->hydrateCategory($category);
$tree[$category->getId()]['model'] = $category;
if ($nextCategory && (int) $nextCategory->getLevel() !== (int) $category->getLevel()) {
$tree[$category->getId()]['children'] = $this->execute($iterator);
}
}

return $tree;
}
}

0 comments on commit 0571603

Please sign in to comment.