Skip to content

Commit ec7fff8

Browse files
committed
Merge branch 'develop' of github.corp.magento.com:magento2/magento2ce into TrollS51Bugfixes
2 parents 752af5b + 032a667 commit ec7fff8

File tree

18 files changed

+502
-167
lines changed

18 files changed

+502
-167
lines changed

app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Longtext.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function render(\Magento\Framework\DataObject $row)
3030
$truncateLength = $this->getColumn()->getTruncate();
3131
}
3232
$text = $this->filterManager->truncate(parent::_getValue($row), ['length' => $truncateLength]);
33-
if ($this->getColumn()->getEscape()) {
33+
if (!$this->getColumn()->hasEscape() || $this->getColumn()->getEscape()) {
3434
$text = $this->escapeHtml($text);
3535
}
3636
if ($this->getColumn()->getNl2br()) {

app/code/Magento/Catalog/Model/ResourceModel/Attribute.php

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,27 +113,20 @@ protected function _clearUselessAttributeValues(\Magento\Framework\Model\Abstrac
113113
/**
114114
* Delete entity
115115
*
116-
* @param \Magento\Framework\Model\AbstractModel $object
116+
* @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $object
117117
* @return $this
118118
* @throws \Magento\Framework\Exception\LocalizedException
119119
*/
120-
public function deleteEntity(\Magento\Framework\Model\AbstractModel $object)
120+
public function deleteEntity(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute $object)
121121
{
122122
if (!$object->getEntityAttributeId()) {
123123
return $this;
124124
}
125125

126-
$select = $this->getConnection()->select()->from(
127-
$this->getTable('eav_entity_attribute')
128-
)->where(
129-
'entity_attribute_id = ?',
130-
(int)$object->getEntityAttributeId()
131-
);
132-
$result = $this->getConnection()->fetchRow($select);
133-
126+
$result = $this->getEntityAttribute($object->getEntityAttributeId());
134127
if ($result) {
135128
$attribute = $this->_eavConfig->getAttribute(
136-
\Magento\Catalog\Model\Product::ENTITY,
129+
$object->getEntityTypeId(),
137130
$result['attribute_id']
138131
);
139132

app/code/Magento/Catalog/Model/ResourceModel/Category/Tree.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
*/
66
namespace Magento\Catalog\Model\ResourceModel\Category;
77

8+
use Magento\Framework\Data\Tree\Dbp;
89
use Magento\Catalog\Api\Data\CategoryInterface;
910
use Magento\Framework\Model\Entity\MetadataPool;
1011

1112
/**
1213
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1314
*/
14-
class Tree extends \Magento\Framework\Data\Tree\Dbp
15+
class Tree extends Dbp
1516
{
1617
const ID_FIELD = 'id';
1718

@@ -124,10 +125,10 @@ public function __construct(
124125
$resource->getConnection('catalog'),
125126
$resource->getTableName('catalog_category_entity'),
126127
[
127-
\Magento\Framework\Data\Tree\Dbp::ID_FIELD => 'entity_id',
128-
\Magento\Framework\Data\Tree\Dbp::PATH_FIELD => 'path',
129-
\Magento\Framework\Data\Tree\Dbp::ORDER_FIELD => 'position',
130-
\Magento\Framework\Data\Tree\Dbp::LEVEL_FIELD => 'level'
128+
Dbp::ID_FIELD => 'entity_id',
129+
Dbp::PATH_FIELD => 'path',
130+
Dbp::ORDER_FIELD => 'position',
131+
Dbp::LEVEL_FIELD => 'level'
131132
]
132133
);
133134
$this->_eventManager = $eventManager;

app/code/Magento/Catalog/Observer/AddCatalogToTopmenuItemsObserver.php

Lines changed: 107 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
*/
66
namespace Magento\Catalog\Observer;
77

8+
use Magento\Catalog\Model\Category;
9+
use Magento\Framework\Data\Collection;
10+
use Magento\Framework\Data\Tree\Node;
811
use Magento\Framework\Event\ObserverInterface;
912

13+
/**
14+
* Observer that add Categories Tree to Topmenu
15+
*/
1016
class AddCatalogToTopmenuItemsObserver implements ObserverInterface
1117
{
1218
/**
@@ -17,28 +23,38 @@ class AddCatalogToTopmenuItemsObserver implements ObserverInterface
1723
protected $catalogCategory;
1824

1925
/**
20-
* @var \Magento\Catalog\Model\Indexer\Category\Flat\State
26+
* @var \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory
27+
*/
28+
private $collectionFactory;
29+
30+
/**
31+
* @var \Magento\Store\Model\StoreManagerInterface
2132
*/
22-
protected $categoryFlatState;
33+
private $storeManager;
2334

2435
/**
25-
* @var MenuCategoryData
36+
* @var \Magento\Catalog\Model\Layer\Resolver
2637
*/
27-
protected $menuCategoryData;
38+
private $layerResolver;
2839

2940
/**
3041
* @param \Magento\Catalog\Helper\Category $catalogCategory
3142
* @param \Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState
32-
* @param \Magento\Catalog\Observer\MenuCategoryData $menuCategoryData
43+
* @param \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory
44+
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
45+
* @param \Magento\Catalog\Helper\Category $catalogCategory
46+
* @param \Magento\Catalog\Model\Layer\Resolver $layerResolver
3347
*/
3448
public function __construct(
3549
\Magento\Catalog\Helper\Category $catalogCategory,
36-
\Magento\Catalog\Model\Indexer\Category\Flat\State $categoryFlatState,
37-
\Magento\Catalog\Observer\MenuCategoryData $menuCategoryData
50+
\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
51+
\Magento\Store\Model\StoreManagerInterface $storeManager,
52+
\Magento\Catalog\Model\Layer\Resolver $layerResolver
3853
) {
3954
$this->catalogCategory = $catalogCategory;
40-
$this->categoryFlatState = $categoryFlatState;
41-
$this->menuCategoryData = $menuCategoryData;
55+
$this->collectionFactory = $categoryCollectionFactory;
56+
$this->storeManager = $storeManager;
57+
$this->layerResolver = $layerResolver;
4258
}
4359

4460
/**
@@ -50,38 +66,96 @@ public function __construct(
5066
public function execute(\Magento\Framework\Event\Observer $observer)
5167
{
5268
$block = $observer->getEvent()->getBlock();
53-
$block->addIdentity(\Magento\Catalog\Model\Category::CACHE_TAG);
54-
$this->_addCategoriesToMenu($this->catalogCategory->getStoreCategories(), $observer->getMenu(), $block);
69+
$menuRootNode = $observer->getEvent()->getMenu();
70+
$block->addIdentity(Category::CACHE_TAG);
71+
72+
$rootId = $this->storeManager->getStore()->getRootCategoryId();
73+
$storeId = $this->storeManager->getStore()->getId();
74+
75+
/** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
76+
$collection = $this->getCategoryTree($storeId, $rootId);
77+
78+
$currentCategory = $this->getCurrentCategory();
79+
80+
$mapping = [$rootId => $menuRootNode]; // use nodes stack to avoid recursion
81+
foreach ($collection as $category) {
82+
if (!isset($mapping[$category->getParentId()])) {
83+
continue;
84+
}
85+
/** @var Node $parentCategoryNode */
86+
$parentCategoryNode = $mapping[$category->getParentId()];
87+
88+
$categoryNode = new Node(
89+
$this->getCategoryAsArray($category, $currentCategory),
90+
'id',
91+
$parentCategoryNode->getTree(),
92+
$parentCategoryNode
93+
);
94+
$parentCategoryNode->addChild($categoryNode);
95+
96+
$mapping[$category->getId()] = $categoryNode; //add node in stack
97+
98+
$block->addIdentity(Category::CACHE_TAG . '_' . $category->getId());
99+
}
55100
}
56101

57102
/**
58-
* Recursively adds categories to top menu
103+
* Get current Category from catalog layer
59104
*
60-
* @param \Magento\Framework\Data\Tree\Node\Collection|array $categories
61-
* @param \Magento\Framework\Data\Tree\Node $parentCategoryNode
62-
* @param \Magento\Theme\Block\Html\Topmenu $block
63-
* @return void
105+
* @return \Magento\Catalog\Model\Category
64106
*/
65-
protected function _addCategoriesToMenu($categories, $parentCategoryNode, $block)
107+
private function getCurrentCategory()
66108
{
67-
foreach ($categories as $category) {
68-
if (!$category->getIsActive()) {
69-
continue;
70-
}
71-
$block->addIdentity(\Magento\Catalog\Model\Category::CACHE_TAG . '_' . $category->getId());
109+
$catalogLayer = $this->layerResolver->get();
72110

73-
$tree = $parentCategoryNode->getTree();
74-
$categoryData = $this->menuCategoryData->getMenuCategoryData($category);
75-
$categoryNode = new \Magento\Framework\Data\Tree\Node($categoryData, 'id', $tree, $parentCategoryNode);
76-
$parentCategoryNode->addChild($categoryNode);
111+
if (!$catalogLayer) {
112+
return null;
113+
}
77114

78-
if ($this->categoryFlatState->isFlatEnabled() && $category->getUseFlatResource()) {
79-
$subcategories = (array)$category->getChildrenNodes();
80-
} else {
81-
$subcategories = $category->getChildren();
82-
}
115+
return $catalogLayer->getCurrentCategory();
116+
}
83117

84-
$this->_addCategoriesToMenu($subcategories, $categoryNode, $block);
85-
}
118+
/**
119+
* Convert category to array
120+
*
121+
* @param \Magento\Catalog\Model\Category $category
122+
* @param \Magento\Catalog\Model\Category $currentCategory
123+
* @return array
124+
*/
125+
private function getCategoryAsArray($category, $currentCategory)
126+
{
127+
return [
128+
'name' => $category->getName(),
129+
'id' => 'category-node-' . $category->getId(),
130+
'url' => $this->catalogCategory->getCategoryUrl($category),
131+
'has_active' => in_array((string)$category->getId(), explode('/', $currentCategory->getPath()), true),
132+
'is_active' => $category->getId() == $currentCategory->getId()
133+
];
134+
}
135+
136+
/**
137+
* Get Category Tree
138+
*
139+
* @param int $storeId
140+
* @param int $rootId
141+
* @return \Magento\Catalog\Model\ResourceModel\Category\Collection
142+
* @throws \Magento\Framework\Exception\LocalizedException
143+
*/
144+
protected function getCategoryTree($storeId, $rootId)
145+
{
146+
/** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
147+
$collection = $this->collectionFactory->create();
148+
$collection->setStoreId($storeId);
149+
$collection->addAttributeToSelect('name');
150+
$collection->addFieldToFilter('path', ['like' => '1/' . $rootId . '/%']); //load only from store root
151+
$collection->addAttributeToFilter('include_in_menu', 1);
152+
$collection->addAttributeToFilter('is_active', 1);
153+
$collection->addUrlRewriteToResult();
154+
$collection->addOrder('level', Collection::SORT_ORDER_ASC);
155+
$collection->addOrder('position', Collection::SORT_ORDER_ASC);
156+
$collection->addOrder('parent_id', Collection::SORT_ORDER_ASC);
157+
$collection->addOrder('entity_id', Collection::SORT_ORDER_ASC);
158+
159+
return $collection;
86160
}
87161
}

app/code/Magento/Catalog/Test/Unit/Observer/AddCatalogToTopmenuItemsObserverTest.php

Lines changed: 36 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,51 @@ public function setUp()
5252
false
5353
);
5454

55-
$this->_categoryFlatState = $this->getMock(
56-
'\Magento\Catalog\Model\Indexer\Category\Flat\State',
57-
['isFlatEnabled'],
58-
[],
59-
'',
60-
false
61-
);
62-
6355
$this->menuCategoryData = $this->getMock(
6456
'Magento\Catalog\Observer\MenuCategoryData',
6557
['getMenuCategoryData'],
6658
[],
6759
'',
6860
false
6961
);
62+
63+
$this->store = $this->getMockBuilder('Magento\Store\Model\Store')
64+
->setMethods(['getRootCategoryId', 'getFilters', '__wakeup'])
65+
->disableOriginalConstructor()
66+
->getMockForAbstractClass();
67+
68+
$this->storeManager = $this->getMockBuilder('Magento\Store\Model\StoreManagerInterface')
69+
->setMethods(['getStore'])
70+
->disableOriginalConstructor()
71+
->getMockForAbstractClass();
72+
$this->storeManager->expects($this->any())->method('getStore')
73+
->will($this->returnValue($this->store));
74+
75+
$this->store->expects($this->any())->method('getRootCategoryId')
76+
->will($this->returnValue(1));
77+
78+
$collectionFactory = $this->getMockBuilder('\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory')
79+
->setMethods(['create'])
80+
->disableOriginalConstructor()
81+
->getMock();
82+
83+
$collection = $this->getMockBuilder('\Magento\Catalog\Model\ResourceModel\Category\Collection')
84+
->disableOriginalConstructor()
85+
->getMock();
86+
87+
$collectionFactory->expects($this->once())->method('create')
88+
->willReturn($collection);
89+
90+
$collection->expects($this->once())->method('getIterator')
91+
->willReturn(new \ArrayIterator([]));
92+
7093
$this->_observer = (new ObjectManager($this))->getObject(
7194
'Magento\Catalog\Observer\AddCatalogToTopmenuItemsObserver',
7295
[
7396
'catalogCategory' => $this->_catalogCategory,
7497
'menuCategoryData' => $this->menuCategoryData,
75-
'categoryFlatState' => $this->_categoryFlatState,
98+
'storeManager' => $this->storeManager,
99+
'categoryCollectionFactory' => $collectionFactory,
76100
]
77101
);
78102
}
@@ -97,9 +121,7 @@ protected function _preparationData()
97121
'',
98122
false
99123
);
100-
$this->_childrenCategory->expects($this->once())
101-
->method('getIsActive')
102-
->will($this->returnValue(false));
124+
103125

104126
$this->_category = $this->getMock(
105127
'\Magento\Catalog\Model\Category',
@@ -108,69 +130,27 @@ protected function _preparationData()
108130
'',
109131
false
110132
);
111-
$this->_category->expects($this->once())
112-
->method('getIsActive')
113-
->will($this->returnValue(true));
114-
115-
$this->_catalogCategory->expects($this->once())
116-
->method('getStoreCategories')
117-
->will($this->returnValue([$this->_category]));
118-
$this->menuCategoryData->expects($this->once())
119-
->method('getMenuCategoryData')
120-
->with($this->_category);
121133

122134
$blockMock = $this->_getCleanMock('\Magento\Theme\Block\Html\Topmenu');
123135

124-
$treeMock = $this->_getCleanMock('\Magento\Framework\Data\Tree');
125-
126-
$menuMock = $this->getMock('\Magento\Framework\Data\Tree\Node', ['getTree', 'addChild'], [], '', false);
127-
$menuMock->expects($this->once())
128-
->method('getTree')
129-
->will($this->returnValue($treeMock));
130-
131136
$eventMock = $this->getMock('\Magento\Framework\Event', ['getBlock'], [], '', false);
132137
$eventMock->expects($this->once())
133138
->method('getBlock')
134139
->will($this->returnValue($blockMock));
135140

136141
$observerMock = $this->getMock('\Magento\Framework\Event\Observer', ['getEvent', 'getMenu'], [], '', false);
137-
$observerMock->expects($this->once())
142+
$observerMock->expects($this->any())
138143
->method('getEvent')
139144
->will($this->returnValue($eventMock));
140-
$observerMock->expects($this->once())
141-
->method('getMenu')
142-
->will($this->returnValue($menuMock));
143145

144146
return $observerMock;
145147
}
146148

147-
public function testAddCatalogToTopMenuItemsWithoutFlat()
149+
public function testAddCatalogToTopMenuItems()
148150
{
149151
$observer = $this->_preparationData();
150-
151-
$this->_category->expects($this->once())
152-
->method('getChildren')
153-
->will($this->returnValue([$this->_childrenCategory]));
154-
155152
$this->_observer->execute($observer);
156153
}
157154

158-
public function testAddCatalogToTopMenuItemsWithFlat()
159-
{
160-
$observer = $this->_preparationData();
161-
162-
$this->_category->expects($this->once())
163-
->method('getChildrenNodes')
164-
->will($this->returnValue([$this->_childrenCategory]));
165-
166-
$this->_category->expects($this->once())
167-
->method('getUseFlatResource')
168-
->will($this->returnValue(true));
169155

170-
$this->_categoryFlatState->expects($this->once())
171-
->method('isFlatEnabled')
172-
->will($this->returnValue(true));
173-
174-
$this->_observer->execute($observer);
175-
}
176156
}

0 commit comments

Comments
 (0)