Skip to content

Commit 8fcee06

Browse files
author
Valeriy Nayda
committed
Merge remote-tracking branch 'origin/MAGETWO-50882' into PR-8
2 parents 1032911 + df5f762 commit 8fcee06

File tree

8 files changed

+395
-31
lines changed

8 files changed

+395
-31
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
namespace Magento\Catalog\Api;
8+
9+
/**
10+
* @api
11+
*/
12+
interface CategoryListInterface
13+
{
14+
/**
15+
* Get category list
16+
*
17+
* @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
18+
* @return \Magento\Catalog\Api\Data\CategorySearchResultsInterface
19+
*/
20+
public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria);
21+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
namespace Magento\Catalog\Api\Data;
8+
9+
use Magento\Framework\Api\SearchResultsInterface;
10+
11+
/**
12+
* @api
13+
*/
14+
interface CategorySearchResultsInterface extends SearchResultsInterface
15+
{
16+
/**
17+
* Get categories
18+
*
19+
* @return \Magento\Catalog\Api\Data\CategoryInterface[]
20+
*/
21+
public function getItems();
22+
23+
/**
24+
* Set categories
25+
*
26+
* @param \Magento\Catalog\Api\Data\CategoryInterface[] $items
27+
* @return $this
28+
*/
29+
public function setItems(array $items);
30+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
8+
namespace Magento\Catalog\Model;
9+
10+
use Magento\Catalog\Api\CategoryListInterface;
11+
use Magento\Catalog\Api\CategoryRepositoryInterface;
12+
use Magento\Catalog\Api\Data\CategorySearchResultsInterface;
13+
use Magento\Catalog\Api\Data\CategorySearchResultsInterfaceFactory;
14+
use Magento\Catalog\Model\ResourceModel\Category\Collection;
15+
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
16+
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
17+
use Magento\Framework\Api\Search\FilterGroup;
18+
use Magento\Framework\Api\SearchCriteriaInterface;
19+
use Magento\Framework\Api\SortOrder;
20+
use Magento\Framework\App\ObjectManager;
21+
22+
class CategoryList implements CategoryListInterface
23+
{
24+
/**
25+
* @var CollectionFactory
26+
*/
27+
protected $categoryCollectionFactory;
28+
29+
/**
30+
* @var JoinProcessorInterface
31+
*/
32+
protected $extensionAttributesJoinProcessor;
33+
34+
/**
35+
* @var CategorySearchResultsInterfaceFactory
36+
*/
37+
protected $categorySearchResultsFactory;
38+
39+
/**
40+
* @var CategoryRepositoryInterface
41+
*/
42+
protected $categoryRepository;
43+
44+
/**
45+
* @param CollectionFactory $categoryCollectionFactory
46+
* @param JoinProcessorInterface $extensionAttributesJoinProcessor
47+
* @param CategorySearchResultsInterfaceFactory $categorySearchResultsFactory
48+
* @param CategoryRepositoryInterface $categoryRepository
49+
*/
50+
public function __construct(
51+
CollectionFactory $categoryCollectionFactory,
52+
JoinProcessorInterface $extensionAttributesJoinProcessor,
53+
CategorySearchResultsInterfaceFactory $categorySearchResultsFactory,
54+
CategoryRepositoryInterface $categoryRepository
55+
) {
56+
$this->categoryCollectionFactory = $categoryCollectionFactory;
57+
$this->extensionAttributesJoinProcessor = $extensionAttributesJoinProcessor;
58+
$this->categorySearchResultsFactory = $categorySearchResultsFactory;
59+
$this->categoryRepository = $categoryRepository;
60+
}
61+
62+
/**
63+
* {@inheritdoc}
64+
*/
65+
public function getList(SearchCriteriaInterface $searchCriteria)
66+
{
67+
/** @var Collection $collection */
68+
$collection = $this->categoryCollectionFactory->create();
69+
$this->extensionAttributesJoinProcessor->process($collection);
70+
71+
foreach ($searchCriteria->getFilterGroups() as $group) {
72+
$this->addFilterGroupToCollection($group, $collection);
73+
}
74+
75+
/** @var SortOrder $sortOrder */
76+
$sortOrders = $searchCriteria->getSortOrders();
77+
if ($sortOrders) {
78+
foreach ($sortOrders as $sortOrder) {
79+
$collection->addOrder(
80+
$sortOrder->getField(),
81+
($sortOrder->getDirection() === SortOrder::SORT_ASC) ? SortOrder::SORT_ASC : SortOrder::SORT_DESC
82+
);
83+
}
84+
}
85+
86+
$collection->setCurPage($searchCriteria->getCurrentPage());
87+
$collection->setPageSize($searchCriteria->getPageSize());
88+
89+
$items = [];
90+
foreach ($collection->getAllIds() as $id) {
91+
$items[] = $this->categoryRepository->get($id);
92+
}
93+
94+
/** @var CategorySearchResultsInterface $searchResult */
95+
$searchResult = $this->categorySearchResultsFactory->create();
96+
$searchResult->setSearchCriteria($searchCriteria);
97+
$searchResult->setItems($items);
98+
$searchResult->setTotalCount($collection->getSize());
99+
return $searchResult;
100+
}
101+
102+
/**
103+
* @param FilterGroup $filterGroup
104+
* @param Collection $collection
105+
* @return void
106+
*/
107+
protected function addFilterGroupToCollection(FilterGroup $filterGroup, Collection $collection)
108+
{
109+
$filters = $filterGroup->getFilters();
110+
if ($filters) {
111+
$fields = [];
112+
foreach ($filters as $filter) {
113+
$conditionType = $filter->getConditionType() ? $filter->getConditionType() : 'eq';
114+
$fields[] = ['attribute' => $filter->getField(), $conditionType => $filter->getValue()];
115+
}
116+
$collection->addFieldToFilter($fields);
117+
}
118+
}
119+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Test\Unit\Model;
7+
8+
use Magento\Catalog\Api\CategoryRepositoryInterface;
9+
use Magento\Catalog\Api\Data\CategorySearchResultsInterface;
10+
use Magento\Catalog\Model\Category;
11+
use Magento\Catalog\Model\CategoryList;
12+
use Magento\Catalog\Model\ResourceModel\Category\Collection;
13+
use Magento\Framework\Api\ExtensionAttribute\JoinProcessorInterface;
14+
use Magento\Framework\Api\Filter;
15+
use Magento\Framework\Api\Search\FilterGroup;
16+
use Magento\Framework\Api\SearchCriteriaInterface;
17+
use Magento\Framework\Api\SortOrder;
18+
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
19+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
20+
use Magento\Catalog\Api\Data\CategorySearchResultsInterfaceFactory;
21+
22+
/**
23+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
24+
*/
25+
class CategoryListTest extends \PHPUnit_Framework_TestCase
26+
{
27+
/**
28+
* @var CategoryList
29+
*/
30+
protected $model;
31+
32+
/**
33+
* @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject
34+
*/
35+
private $categoryCollectionFactory;
36+
37+
/**
38+
* @var JoinProcessorInterface|\PHPUnit_Framework_MockObject_MockObject
39+
*/
40+
private $extensionAttributesJoinProcessor;
41+
42+
/**
43+
* @var CategorySearchResultsInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject
44+
*/
45+
private $categorySearchResultsFactory;
46+
47+
/**
48+
* @var CategoryRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
49+
*/
50+
private $categoryRepository;
51+
52+
protected function setUp()
53+
{
54+
$this->categoryCollectionFactory = $this->getMockBuilder(CollectionFactory::class)
55+
->disableOriginalConstructor()
56+
->setMethods(['create'])
57+
->getMock();
58+
$this->extensionAttributesJoinProcessor = $this->getMock(JoinProcessorInterface::class);
59+
$this->categorySearchResultsFactory = $this->getMockBuilder(CategorySearchResultsInterfaceFactory::class)
60+
->disableOriginalConstructor()
61+
->setMethods(['create'])
62+
->getMock();
63+
$this->categoryRepository = $this->getMock(CategoryRepositoryInterface::class);
64+
65+
$this->model = (new ObjectManager($this))->getObject(
66+
CategoryList::class,
67+
[
68+
'categoryCollectionFactory' => $this->categoryCollectionFactory,
69+
'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessor,
70+
'categorySearchResultsFactory' => $this->categorySearchResultsFactory,
71+
'categoryRepository' => $this->categoryRepository,
72+
]
73+
);
74+
}
75+
76+
public function testGetList()
77+
{
78+
$fieldName = 'field_1';
79+
$value = 'value_1';
80+
$conditionType = 'eq';
81+
$currentPage = 2;
82+
$pageSize = 1;
83+
$totalCount = 2;
84+
$categoryIdFirst = 1;
85+
$categoryIdSecond = 2;
86+
87+
$categoryFirst = $this->getMockBuilder(Category::class)->disableOriginalConstructor()->getMock();
88+
$categorySecond = $this->getMockBuilder(Category::class)->disableOriginalConstructor()->getMock();
89+
90+
$filter = $this->getMockBuilder(Filter::class)->disableOriginalConstructor()->getMock();
91+
$filter->expects($this->atLeastOnce())->method('getConditionType')->willReturn($conditionType);
92+
$filter->expects($this->atLeastOnce())->method('getField')->willReturn($fieldName);
93+
$filter->expects($this->once())->method('getValue')->willReturn($value);
94+
95+
$filterGroup = $this->getMockBuilder(FilterGroup::class)->disableOriginalConstructor()->getMock();
96+
$filterGroup->expects($this->once())->method('getFilters')->willReturn([$filter]);
97+
98+
$sortOrder = $this->getMockBuilder(SortOrder::class)->disableOriginalConstructor()->getMock();
99+
$sortOrder->expects($this->once())->method('getField')->willReturn($fieldName);
100+
$sortOrder->expects($this->once())->method('getDirection')->willReturn(SortOrder::SORT_ASC);
101+
102+
/** @var SearchCriteriaInterface|\PHPUnit_Framework_MockObject_MockObject $searchCriteria */
103+
$searchCriteria = $this->getMock(SearchCriteriaInterface::class);
104+
$searchCriteria->expects($this->once())->method('getFilterGroups')->willReturn([$filterGroup]);
105+
$searchCriteria->expects($this->once())->method('getCurrentPage')->willReturn($currentPage);
106+
$searchCriteria->expects($this->once())->method('getPageSize')->willReturn($pageSize);
107+
$searchCriteria->expects($this->once())->method('getSortOrders')->willReturn([$sortOrder]);
108+
109+
$collection = $this->getMockBuilder(Collection::class)->disableOriginalConstructor()->getMock();
110+
$collection->expects($this->once())
111+
->method('addFieldToFilter')
112+
->with([['attribute' => $fieldName, $conditionType => $value]]);
113+
$collection->expects($this->once())->method('addOrder')->with($fieldName, SortOrder::SORT_ASC);
114+
$collection->expects($this->once())->method('setCurPage')->with($currentPage);
115+
$collection->expects($this->once())->method('setPageSize')->with($pageSize);
116+
$collection->expects($this->once())->method('getSize')->willReturn($totalCount);
117+
$collection->expects($this->once())->method('getAllIds')->willReturn([$categoryIdFirst, $categoryIdSecond]);
118+
119+
$searchResult = $this->getMock(CategorySearchResultsInterface::class);
120+
$searchResult->expects($this->once())->method('setSearchCriteria')->with($searchCriteria);
121+
$searchResult->expects($this->once())->method('setItems')->with([$categoryFirst, $categorySecond]);
122+
$searchResult->expects($this->once())->method('setTotalCount')->with($totalCount);
123+
124+
$this->categoryRepository->expects($this->exactly(2))
125+
->method('get')
126+
->willReturnMap([
127+
[$categoryIdFirst, $categoryFirst],
128+
[$categoryIdSecond, $categorySecond],
129+
])
130+
->willReturn($categoryFirst);
131+
132+
$this->categorySearchResultsFactory->expects($this->once())->method('create')->willReturn($searchResult);
133+
$this->categoryCollectionFactory->expects($this->once())->method('create')->willReturn($collection);
134+
$this->extensionAttributesJoinProcessor->expects($this->once())->method('process')->with($collection);
135+
136+
$this->assertEquals($searchResult, $this->model->getList($searchCriteria));
137+
}
138+
}

app/code/Magento/Catalog/Test/Unit/Model/CategoryRepositoryTest.php

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@
55
*/
66
namespace Magento\Catalog\Test\Unit\Model;
77

8+
use Magento\Catalog\Model\Category;
9+
use Magento\Catalog\Model\CategoryRepository;
10+
use Magento\Catalog\Model\ResourceModel\Category\Collection;
11+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
12+
813
class CategoryRepositoryTest extends \PHPUnit_Framework_TestCase
914
{
1015
/**
11-
* @var \Magento\Catalog\Model\CategoryRepository
16+
* @var CategoryRepository
1217
*/
1318
protected $model;
1419

@@ -88,21 +93,16 @@ protected function setUp()
8893
->with(\Magento\Catalog\Api\Data\CategoryInterface::class)
8994
->willReturn($metadataMock);
9095

91-
$this->model = new \Magento\Catalog\Model\CategoryRepository(
92-
$this->categoryFactoryMock,
93-
$this->categoryResourceMock,
94-
$this->storeManagerMock
96+
$this->model = (new ObjectManager($this))->getObject(
97+
CategoryRepository::class,
98+
[
99+
'categoryFactory' => $this->categoryFactoryMock,
100+
'categoryResource' => $this->categoryResourceMock,
101+
'storeManager' => $this->storeManagerMock,
102+
'metadataPool' => $this->metadataPoolMock,
103+
'extensibleDataObjectConverter' => $this->extensibleDataObjectConverterMock,
104+
]
95105
);
96-
97-
$this->setProperties($this->model, [
98-
'metadataPool' => $this->metadataPoolMock
99-
]);
100-
101-
// Todo: \Magento\Framework\TestFramework\Unit\Helper\ObjectManager to do this automatically (MAGETWO-49793)
102-
$reflection = new \ReflectionClass(get_class($this->model));
103-
$reflectionProperty = $reflection->getProperty('extensibleDataObjectConverter');
104-
$reflectionProperty->setAccessible(true);
105-
$reflectionProperty->setValue($this->model, $this->extensibleDataObjectConverterMock);
106106
}
107107

108108
public function testGet()
@@ -370,20 +370,4 @@ public function testDeleteByIdentifierWithException()
370370
);
371371
$this->model->deleteByIdentifier($categoryId);
372372
}
373-
374-
/**
375-
* @param $object
376-
* @param array $properties
377-
*/
378-
private function setProperties($object, $properties = [])
379-
{
380-
$reflectionClass = new \ReflectionClass(get_class($object));
381-
foreach ($properties as $key => $value) {
382-
if ($reflectionClass->hasProperty($key)) {
383-
$reflectionProperty = $reflectionClass->getProperty($key);
384-
$reflectionProperty->setAccessible(true);
385-
$reflectionProperty->setValue($object, $value);
386-
}
387-
}
388-
}
389373
}

app/code/Magento/Catalog/etc/di.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
<preference for="Magento\Catalog\Api\AttributeSetRepositoryInterface" type="Magento\Catalog\Model\Product\Attribute\SetRepository" />
4545
<preference for="Magento\Catalog\Api\ProductManagementInterface" type="Magento\Catalog\Model\ProductManagement" />
4646
<preference for="Magento\Catalog\Api\AttributeSetFinderInterface" type="Magento\Catalog\Model\Product\Attribute\AttributeSetFinder" />
47+
<preference for="Magento\Catalog\Api\CategoryListInterface" type="Magento\Catalog\Model\CategoryList" />
48+
<preference for="Magento\Catalog\Api\Data\CategorySearchResultsInterface" type="Magento\Framework\Api\SearchResults" />
4749
<type name="Magento\Customer\Model\ResourceModel\Visitor">
4850
<plugin name="catalogLog" type="Magento\Catalog\Model\Plugin\Log" />
4951
</type>

0 commit comments

Comments
 (0)