Skip to content

Commit bc345f8

Browse files
committed
magento#7698: Admin Global Search was build in a hurry
1 parent 79d8e9a commit bc345f8

File tree

6 files changed

+291
-12
lines changed

6 files changed

+291
-12
lines changed

app/code/Magento/Backend/Block/GlobalSearch.php

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,63 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
67
namespace Magento\Backend\Block;
78

9+
use Magento\Backend\Model\GlobalSearch\SearchEntityFactory;
10+
use Magento\Backend\Model\GlobalSearch\SearchEntity;
11+
use Magento\Framework\App\ObjectManager;
12+
813
/**
914
* @api
1015
* @since 100.0.2
1116
*/
1217
class GlobalSearch extends \Magento\Backend\Block\Template
1318
{
19+
const ENTITY_TYPE_PRODUCTS = 'Products';
20+
const ENTITY_TYPE_ORDERS = 'Orders';
21+
const ENTITY_TYPE_CUSTOMERS = 'Customers';
22+
const ENTITY_TYPE_PAGES = 'Pages';
23+
24+
/**
25+
* Affiliation between entity types for global search and corresponding admin resources.
26+
*
27+
* @var array
28+
*/
29+
private $entityTypes = [
30+
self::ENTITY_TYPE_PRODUCTS => \Magento\Catalog\Controller\Adminhtml\Product::ADMIN_RESOURCE,
31+
self::ENTITY_TYPE_ORDERS => \Magento\Sales\Controller\Adminhtml\Order::ADMIN_RESOURCE,
32+
self::ENTITY_TYPE_CUSTOMERS => \Magento\Customer\Controller\Adminhtml\Index::ADMIN_RESOURCE,
33+
self::ENTITY_TYPE_PAGES => \Magento\Cms\Controller\Adminhtml\Page\Index::ADMIN_RESOURCE,
34+
];
35+
36+
/**
37+
* @var SearchEntityFactory
38+
*/
39+
private $searchEntityFactory;
40+
1441
/**
1542
* @var string
1643
*/
1744
protected $_template = 'Magento_Backend::system/search.phtml';
1845

46+
/**
47+
* @param Template\Context $context
48+
* @param array $data
49+
* @param SearchEntityFactory|null $searchEntityFactory
50+
*/
51+
public function __construct(
52+
Template\Context $context,
53+
array $data = [],
54+
SearchEntityFactory $searchEntityFactory = null
55+
) {
56+
$this->searchEntityFactory = $searchEntityFactory ?: ObjectManager::getInstance()->get(
57+
SearchEntityFactory::class
58+
);
59+
60+
parent::__construct($context, $data);
61+
}
62+
1963
/**
2064
* Get components configuration
2165
* @return array
@@ -34,4 +78,63 @@ public function getWidgetInitOptions()
3478
]
3579
];
3680
}
81+
82+
/**
83+
* Get entities which are allowed to show.
84+
*
85+
* @return SearchEntity[]
86+
*/
87+
public function getEntitiesToShow()
88+
{
89+
$allowedEntityTypes = [];
90+
$entitiesToShow = [];
91+
92+
foreach ($this->entityTypes as $entityType => $resource) {
93+
if ($this->getAuthorization()->isAllowed($resource)) {
94+
$allowedEntityTypes[] = $entityType;
95+
}
96+
}
97+
98+
foreach ($allowedEntityTypes as $entityType) {
99+
$url = $this->getUrlEntityType($entityType);
100+
101+
$searchEntity = $this->searchEntityFactory->create();
102+
$searchEntity->setId('searchPreview' . $entityType);
103+
$searchEntity->setTitle('in ' . $entityType);
104+
$searchEntity->setUrl($url);
105+
106+
$entitiesToShow[] = $searchEntity;
107+
}
108+
109+
return $entitiesToShow;
110+
}
111+
112+
/**
113+
* Get url path by entity type.
114+
*
115+
* @param string $entityType
116+
*
117+
* @return string
118+
*/
119+
private function getUrlEntityType(string $entityType)
120+
{
121+
$urlPath = '';
122+
123+
switch ($entityType) {
124+
case self::ENTITY_TYPE_PRODUCTS:
125+
$urlPath = 'catalog/product/index/';
126+
break;
127+
case self::ENTITY_TYPE_ORDERS:
128+
$urlPath = 'sales/order/index/';
129+
break;
130+
case self::ENTITY_TYPE_CUSTOMERS:
131+
$urlPath = 'customer/index/index/';
132+
break;
133+
case self::ENTITY_TYPE_PAGES:
134+
$urlPath = 'cms/page/index/';
135+
break;
136+
}
137+
138+
return $this->getUrl($urlPath);
139+
}
37140
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Backend\Model\GlobalSearch;
8+
9+
/**
10+
* Entity for global search in backend
11+
*/
12+
class SearchEntity extends \Magento\Framework\DataObject
13+
{
14+
/**
15+
* Get id.
16+
*
17+
* @return string
18+
*/
19+
public function getId()
20+
{
21+
return $this->getData('id');
22+
}
23+
24+
/**
25+
* Get url.
26+
*
27+
* @return string
28+
*/
29+
public function getUrl()
30+
{
31+
return $this->getData('url');
32+
}
33+
34+
/**
35+
* Get title.
36+
*
37+
* @return string
38+
*/
39+
public function getTitle()
40+
{
41+
return $this->getData('title');
42+
}
43+
44+
/**
45+
* Set Id.
46+
*
47+
* @param string $value
48+
*/
49+
public function setId(string $value)
50+
{
51+
$this->setData('id', $value);
52+
}
53+
54+
/**
55+
* Set url.
56+
*
57+
* @param string $value
58+
*/
59+
public function setUrl(string $value)
60+
{
61+
$this->setData('url', $value);
62+
}
63+
64+
/**
65+
* Set title.
66+
*
67+
* @param string $value
68+
*/
69+
public function setTitle(string $value)
70+
{
71+
$this->setData('title', $value);
72+
}
73+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Backend\Test\Unit\Block;
8+
9+
use Magento\Backend\Block\GlobalSearch;
10+
use Magento\Backend\Model\GlobalSearch\SearchEntity;
11+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
12+
13+
/**
14+
* Test for @see GlobalSearch.
15+
*/
16+
class GlobalSearchTest extends \PHPUnit\Framework\TestCase
17+
{
18+
/**
19+
* @var GlobalSearch
20+
*/
21+
private $globalSearch;
22+
23+
/**
24+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\AuthorizationInterface
25+
*/
26+
private $authorization;
27+
28+
/**
29+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\UrlInterface
30+
*/
31+
private $urlBuilder;
32+
33+
/**
34+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\Model\GlobalSearch\SearchEntityFactory
35+
*/
36+
private $searchEntityFactory;
37+
38+
protected function setUp()
39+
{
40+
$objectManager = new ObjectManager($this);
41+
42+
$this->authorization = $this->createMock(\Magento\Framework\AuthorizationInterface::class);
43+
$this->urlBuilder = $this->createMock(\Magento\Framework\UrlInterface::class);
44+
$context = $this->createMock(\Magento\Backend\Block\Template\Context::class);
45+
46+
$context->expects($this->atLeastOnce())->method('getAuthorization')->willReturn($this->authorization);
47+
$context->expects($this->atLeastOnce())->method('getUrlBuilder')->willReturn($this->urlBuilder);
48+
49+
$this->searchEntityFactory = $this->createMock(\Magento\Backend\Model\GlobalSearch\SearchEntityFactory::class);
50+
51+
$this->globalSearch = $objectManager->getObject(
52+
GlobalSearch::class,
53+
[
54+
'context' => $context,
55+
'searchEntityFactory' => $this->searchEntityFactory,
56+
]
57+
);
58+
}
59+
60+
/**
61+
* @param array $results
62+
* @param int $expectedEntitiesQty
63+
*
64+
* @dataProvider getEntitiesToShowDataProvider
65+
*/
66+
public function testGetEntitiesToShow(array $results, int $expectedEntitiesQty)
67+
{
68+
$searchEntity = $this->createMock(SearchEntity::class);
69+
70+
$this->authorization->expects($this->exactly(count($results)))->method('isAllowed')
71+
->willReturnOnConsecutiveCalls($results[0], $results[1], $results[2], $results[3]);
72+
$this->urlBuilder->expects($this->exactly($expectedEntitiesQty))
73+
->method('getUrl')->willReturn('some/url/is/here');
74+
$this->searchEntityFactory->expects($this->exactly($expectedEntitiesQty))
75+
->method('create')->willReturn($searchEntity);
76+
77+
$searchEntity->expects($this->exactly($expectedEntitiesQty))->method('setId');
78+
$searchEntity->expects($this->exactly($expectedEntitiesQty))->method('setTitle');
79+
$searchEntity->expects($this->exactly($expectedEntitiesQty))->method('setUrl');
80+
81+
$this->assertSame($expectedEntitiesQty, count($this->globalSearch->getEntitiesToShow()));
82+
}
83+
84+
public function getEntitiesToShowDataProvider()
85+
{
86+
return [
87+
[
88+
[true, false, true, false],
89+
2,
90+
],
91+
[
92+
[true, true, true, true],
93+
4,
94+
],
95+
[
96+
[false, false, false, false],
97+
0,
98+
],
99+
];
100+
}
101+
}

app/code/Magento/Backend/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"magento/module-eav": "101.0.*",
1010
"magento/module-reports": "100.2.*",
1111
"magento/module-sales": "101.0.*",
12+
"magento/module-cms": "102.0.*",
1213
"magento/module-quote": "101.0.*",
1314
"magento/module-catalog": "102.0.*",
1415
"magento/module-user": "101.0.*",

app/code/Magento/Backend/i18n/en_US.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,3 +461,7 @@ Pagination,Pagination
461461
"Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used.","Alternative text for the next pages link in the pagination menu. If empty, default arrow image is used."
462462
"Anchor Text for Next","Anchor Text for Next"
463463
"Theme Name","Theme Name"
464+
"In Products","In Products"
465+
"In Orders","In Orders"
466+
"In Customers","In Customers"
467+
"In Pages","In Pages"

app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,15 @@
2727
</form>
2828
<script data-template="search-suggest" type="text/x-magento-template">
2929
<ul class="search-global-menu">
30-
<li class="item">
31-
<a id="searchPreviewProducts" href="<?= /* @escapeNotVerified */ $block->getUrl('catalog/product/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Products</a>
32-
</li>
33-
<li class="item">
34-
<a id="searchPreviewOrders" href="<?= /* @escapeNotVerified */ $block->getUrl('sales/order/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Orders</a>
35-
</li>
36-
<li class="item">
37-
<a id="searchPreviewCustomers" href="<?= /* @escapeNotVerified */ $block->getUrl('customer/index/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Customers</a>
38-
</li>
39-
<li class="item">
40-
<a id="searchPreviewPages" href="<?= /* @escapeNotVerified */ $block->getUrl('cms/page/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Pages</a>
41-
</li>
30+
<?php foreach ($block->getEntitiesToShow() as $entity): ?>
31+
<li class="item">
32+
<a id="<?= /* @escapeNotVerified */ $entity->getId(); ?>"
33+
href="<?= /* @escapeNotVerified */ $entity->getUrl() ?>?search=<%- data.term%>"
34+
class="title">
35+
"<%- data.term%>" <?= /* @escapeNotVerified */ __($entity->getTitle()); ?>
36+
</a>
37+
</li>
38+
<?php endforeach; ?>
4239
<% if (data.items.length) { %>
4340
<% _.each(data.items, function(value){ %>
4441
<li class="item"

0 commit comments

Comments
 (0)