Skip to content

Commit b8e5a3f

Browse files
ENGCOM-3493: Added a separate resolver for returning category products count #243
- Merge Pull Request magento/graphql-ce#243 from magento/graphql-ce:category-products-count-fix - Merged commits: 1. f9acb65 2. 9aacf0e 3. 19c1f87 4. 3694c65
2 parents 9845b2b + 3694c65 commit b8e5a3f

File tree

4 files changed

+215
-2
lines changed

4 files changed

+215
-2
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ public function hydrateCategory(Category $category, $basicFieldsOnly = false) :
5252
$categoryData = $category->getData();
5353
} else {
5454
$categoryData = $this->dataObjectProcessor->buildOutputDataArray($category, CategoryInterface::class);
55-
$categoryData['product_count'] = $category->getProductCount();
5655
}
5756
$categoryData['id'] = $category->getId();
5857
$categoryData['children'] = [];
5958
$categoryData['available_sort_by'] = $category->getAvailableSortBy();
59+
$categoryData['model'] = $category;
6060
return $this->flattener->flatten($categoryData);
6161
}
6262
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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\Category;
9+
10+
use Magento\Catalog\Model\Category;
11+
use Magento\Catalog\Model\Product\Visibility;
12+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\StockProcessor;
13+
use Magento\Framework\Api\SearchCriteriaInterface;
14+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
16+
use Magento\Framework\GraphQl\Config\Element\Field;
17+
use Magento\Framework\GraphQl\Query\ResolverInterface;
18+
19+
/**
20+
* Retrieves products count for a category
21+
*/
22+
class ProductsCount implements ResolverInterface
23+
{
24+
/**
25+
* @var Visibility
26+
*/
27+
private $catalogProductVisibility;
28+
29+
/**
30+
* @var StockProcessor
31+
*/
32+
private $stockProcessor;
33+
34+
/**
35+
* @var SearchCriteriaInterface
36+
*/
37+
private $searchCriteria;
38+
39+
/**
40+
* @param Visibility $catalogProductVisibility
41+
* @param SearchCriteriaInterface $searchCriteria
42+
* @param StockProcessor $stockProcessor
43+
*/
44+
public function __construct(
45+
Visibility $catalogProductVisibility,
46+
SearchCriteriaInterface $searchCriteria,
47+
StockProcessor $stockProcessor
48+
) {
49+
$this->catalogProductVisibility = $catalogProductVisibility;
50+
$this->searchCriteria = $searchCriteria;
51+
$this->stockProcessor = $stockProcessor;
52+
}
53+
54+
/**
55+
* @inheritdoc
56+
*/
57+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
58+
{
59+
if (!isset($value['model'])) {
60+
throw new GraphQlInputException(__('"model" value should be specified'));
61+
}
62+
/** @var Category $category */
63+
$category = $value['model'];
64+
$productsCollection = $category->getProductCollection();
65+
$productsCollection->setVisibility($this->catalogProductVisibility->getVisibleInSiteIds());
66+
$productsCollection = $this->stockProcessor->process($productsCollection, $this->searchCriteria, []);
67+
68+
return $productsCollection->getSize();
69+
}
70+
}

app/code/Magento/CatalogGraphQl/etc/schema.graphqls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ interface CategoryInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model
377377
level: Int @doc(description: "Indicates the depth of the category within the tree")
378378
created_at: String @doc(description: "Timestamp indicating when the category was created")
379379
updated_at: String @doc(description: "Timestamp indicating when the category was updated")
380-
product_count: Int @doc(description: "The number of products in the category")
380+
product_count: Int @doc(description: "The number of products in the category") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Category\\ProductsCount")
381381
default_sort_by: String @doc(description: "The attribute to use for sorting")
382382
products(
383383
pageSize: Int = 20 @doc(description: "Specifies the maximum number of results to return at once. This attribute is optional."),
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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\GraphQl\Catalog;
9+
10+
use Magento\TestFramework\TestCase\GraphQlAbstract;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
12+
use Magento\TestFramework\Helper\Bootstrap;
13+
use Magento\Catalog\Model\Product\Visibility;
14+
use Magento\Catalog\Model\Product\Attribute\Source\Status as productStatus;
15+
16+
/**
17+
* Class CategoryProductsCountTest
18+
*
19+
* Test for Magento\CatalogGraphQl\Model\Resolver\Category\ProductsCount resolver
20+
*/
21+
class CategoryProductsCountTest extends GraphQlAbstract
22+
{
23+
/**
24+
* @var ProductRepositoryInterface
25+
*/
26+
private $productRepository;
27+
28+
protected function setUp()
29+
{
30+
$objectManager = Bootstrap::getObjectManager();
31+
$this->productRepository = $objectManager->create(ProductRepositoryInterface::class);
32+
}
33+
34+
/**
35+
* @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
36+
*/
37+
public function testCategoryWithSaleableProduct()
38+
{
39+
$categoryId = 2;
40+
41+
$query = <<<QUERY
42+
{
43+
category(id: {$categoryId}) {
44+
id
45+
product_count
46+
}
47+
}
48+
QUERY;
49+
$response = $this->graphQlQuery($query);
50+
51+
self::assertEquals(1, $response['category']['product_count']);
52+
}
53+
54+
/**
55+
* @magentoApiDataFixture Magento/Catalog/_files/category_product.php
56+
*/
57+
public function testCategoryWithInvisibleProduct()
58+
{
59+
$categoryId = 333;
60+
$sku = 'simple333';
61+
62+
$product = $this->productRepository->get($sku);
63+
$product->setVisibility(Visibility::VISIBILITY_NOT_VISIBLE);
64+
$this->productRepository->save($product);
65+
66+
$query = <<<QUERY
67+
{
68+
category(id: {$categoryId}) {
69+
id
70+
product_count
71+
}
72+
}
73+
QUERY;
74+
$response = $this->graphQlQuery($query);
75+
76+
self::assertEquals(0, $response['category']['product_count']);
77+
}
78+
79+
/**
80+
* @magentoApiDataFixture Magento/Catalog/_files/product_simple_out_of_stock.php
81+
*/
82+
public function testCategoryWithOutOfStockProductManageStockEnabled()
83+
{
84+
$categoryId = 2;
85+
86+
$query = <<<QUERY
87+
{
88+
category(id: {$categoryId}) {
89+
id
90+
product_count
91+
}
92+
}
93+
QUERY;
94+
$response = $this->graphQlQuery($query);
95+
96+
self::assertEquals(0, $response['category']['product_count']);
97+
}
98+
99+
/**
100+
* @magentoApiDataFixture Magento/Catalog/_files/category_product.php
101+
*/
102+
public function testCategoryWithOutOfStockProductManageStockDisabled()
103+
{
104+
$categoryId = 333;
105+
106+
$query = <<<QUERY
107+
{
108+
category(id: {$categoryId}) {
109+
id
110+
product_count
111+
}
112+
}
113+
QUERY;
114+
$response = $this->graphQlQuery($query);
115+
116+
self::assertEquals(1, $response['category']['product_count']);
117+
}
118+
119+
/**
120+
* @magentoApiDataFixture Magento/Catalog/_files/category_product.php
121+
*/
122+
public function testCategoryWithDisabledProduct()
123+
{
124+
$categoryId = 333;
125+
$sku = 'simple333';
126+
127+
$product = $this->productRepository->get($sku);
128+
$product->setStatus(ProductStatus::STATUS_DISABLED);
129+
$this->productRepository->save($product);
130+
131+
$query = <<<QUERY
132+
{
133+
category(id: {$categoryId}) {
134+
id
135+
product_count
136+
}
137+
}
138+
QUERY;
139+
$response = $this->graphQlQuery($query);
140+
141+
self::assertEquals(0, $response['category']['product_count']);
142+
}
143+
}

0 commit comments

Comments
 (0)