Skip to content

Commit

Permalink
#7698: Admin Global Search was build in a hurry
Browse files Browse the repository at this point in the history
  • Loading branch information
RomaKis committed Jan 9, 2018
1 parent 79d8e9a commit bc345f8
Show file tree
Hide file tree
Showing 6 changed files with 291 additions and 12 deletions.
103 changes: 103 additions & 0 deletions app/code/Magento/Backend/Block/GlobalSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,63 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Backend\Block;

use Magento\Backend\Model\GlobalSearch\SearchEntityFactory;
use Magento\Backend\Model\GlobalSearch\SearchEntity;
use Magento\Framework\App\ObjectManager;

/**
* @api
* @since 100.0.2
*/
class GlobalSearch extends \Magento\Backend\Block\Template
{
const ENTITY_TYPE_PRODUCTS = 'Products';
const ENTITY_TYPE_ORDERS = 'Orders';
const ENTITY_TYPE_CUSTOMERS = 'Customers';
const ENTITY_TYPE_PAGES = 'Pages';

/**
* Affiliation between entity types for global search and corresponding admin resources.
*
* @var array
*/
private $entityTypes = [
self::ENTITY_TYPE_PRODUCTS => \Magento\Catalog\Controller\Adminhtml\Product::ADMIN_RESOURCE,
self::ENTITY_TYPE_ORDERS => \Magento\Sales\Controller\Adminhtml\Order::ADMIN_RESOURCE,
self::ENTITY_TYPE_CUSTOMERS => \Magento\Customer\Controller\Adminhtml\Index::ADMIN_RESOURCE,
self::ENTITY_TYPE_PAGES => \Magento\Cms\Controller\Adminhtml\Page\Index::ADMIN_RESOURCE,
];

/**
* @var SearchEntityFactory
*/
private $searchEntityFactory;

/**
* @var string
*/
protected $_template = 'Magento_Backend::system/search.phtml';

/**
* @param Template\Context $context
* @param array $data
* @param SearchEntityFactory|null $searchEntityFactory
*/
public function __construct(
Template\Context $context,
array $data = [],
SearchEntityFactory $searchEntityFactory = null
) {
$this->searchEntityFactory = $searchEntityFactory ?: ObjectManager::getInstance()->get(
SearchEntityFactory::class
);

parent::__construct($context, $data);
}

/**
* Get components configuration
* @return array
Expand All @@ -34,4 +78,63 @@ public function getWidgetInitOptions()
]
];
}

/**
* Get entities which are allowed to show.
*
* @return SearchEntity[]
*/
public function getEntitiesToShow()
{
$allowedEntityTypes = [];
$entitiesToShow = [];

foreach ($this->entityTypes as $entityType => $resource) {
if ($this->getAuthorization()->isAllowed($resource)) {
$allowedEntityTypes[] = $entityType;
}
}

foreach ($allowedEntityTypes as $entityType) {
$url = $this->getUrlEntityType($entityType);

$searchEntity = $this->searchEntityFactory->create();
$searchEntity->setId('searchPreview' . $entityType);
$searchEntity->setTitle('in ' . $entityType);
$searchEntity->setUrl($url);

$entitiesToShow[] = $searchEntity;
}

return $entitiesToShow;
}

/**
* Get url path by entity type.
*
* @param string $entityType
*
* @return string
*/
private function getUrlEntityType(string $entityType)
{
$urlPath = '';

switch ($entityType) {
case self::ENTITY_TYPE_PRODUCTS:
$urlPath = 'catalog/product/index/';
break;
case self::ENTITY_TYPE_ORDERS:
$urlPath = 'sales/order/index/';
break;
case self::ENTITY_TYPE_CUSTOMERS:
$urlPath = 'customer/index/index/';
break;
case self::ENTITY_TYPE_PAGES:
$urlPath = 'cms/page/index/';
break;
}

return $this->getUrl($urlPath);
}
}
73 changes: 73 additions & 0 deletions app/code/Magento/Backend/Model/GlobalSearch/SearchEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Backend\Model\GlobalSearch;

/**
* Entity for global search in backend
*/
class SearchEntity extends \Magento\Framework\DataObject
{
/**
* Get id.
*
* @return string
*/
public function getId()
{
return $this->getData('id');
}

/**
* Get url.
*
* @return string
*/
public function getUrl()
{
return $this->getData('url');
}

/**
* Get title.
*
* @return string
*/
public function getTitle()
{
return $this->getData('title');
}

/**
* Set Id.
*
* @param string $value
*/
public function setId(string $value)
{
$this->setData('id', $value);
}

/**
* Set url.
*
* @param string $value
*/
public function setUrl(string $value)
{
$this->setData('url', $value);
}

/**
* Set title.
*
* @param string $value
*/
public function setTitle(string $value)
{
$this->setData('title', $value);
}
}
101 changes: 101 additions & 0 deletions app/code/Magento/Backend/Test/Unit/Block/GlobalSearchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Backend\Test\Unit\Block;

use Magento\Backend\Block\GlobalSearch;
use Magento\Backend\Model\GlobalSearch\SearchEntity;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;

/**
* Test for @see GlobalSearch.
*/
class GlobalSearchTest extends \PHPUnit\Framework\TestCase
{
/**
* @var GlobalSearch
*/
private $globalSearch;

/**
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\AuthorizationInterface
*/
private $authorization;

/**
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\UrlInterface
*/
private $urlBuilder;

/**
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Backend\Model\GlobalSearch\SearchEntityFactory
*/
private $searchEntityFactory;

protected function setUp()
{
$objectManager = new ObjectManager($this);

$this->authorization = $this->createMock(\Magento\Framework\AuthorizationInterface::class);
$this->urlBuilder = $this->createMock(\Magento\Framework\UrlInterface::class);
$context = $this->createMock(\Magento\Backend\Block\Template\Context::class);

$context->expects($this->atLeastOnce())->method('getAuthorization')->willReturn($this->authorization);
$context->expects($this->atLeastOnce())->method('getUrlBuilder')->willReturn($this->urlBuilder);

$this->searchEntityFactory = $this->createMock(\Magento\Backend\Model\GlobalSearch\SearchEntityFactory::class);

$this->globalSearch = $objectManager->getObject(
GlobalSearch::class,
[
'context' => $context,
'searchEntityFactory' => $this->searchEntityFactory,
]
);
}

/**
* @param array $results
* @param int $expectedEntitiesQty
*
* @dataProvider getEntitiesToShowDataProvider
*/
public function testGetEntitiesToShow(array $results, int $expectedEntitiesQty)
{
$searchEntity = $this->createMock(SearchEntity::class);

$this->authorization->expects($this->exactly(count($results)))->method('isAllowed')
->willReturnOnConsecutiveCalls($results[0], $results[1], $results[2], $results[3]);
$this->urlBuilder->expects($this->exactly($expectedEntitiesQty))
->method('getUrl')->willReturn('some/url/is/here');
$this->searchEntityFactory->expects($this->exactly($expectedEntitiesQty))
->method('create')->willReturn($searchEntity);

$searchEntity->expects($this->exactly($expectedEntitiesQty))->method('setId');
$searchEntity->expects($this->exactly($expectedEntitiesQty))->method('setTitle');
$searchEntity->expects($this->exactly($expectedEntitiesQty))->method('setUrl');

$this->assertSame($expectedEntitiesQty, count($this->globalSearch->getEntitiesToShow()));
}

public function getEntitiesToShowDataProvider()
{
return [
[
[true, false, true, false],
2,
],
[
[true, true, true, true],
4,
],
[
[false, false, false, false],
0,
],
];
}
}
1 change: 1 addition & 0 deletions app/code/Magento/Backend/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"magento/module-eav": "101.0.*",
"magento/module-reports": "100.2.*",
"magento/module-sales": "101.0.*",
"magento/module-cms": "102.0.*",
"magento/module-quote": "101.0.*",
"magento/module-catalog": "102.0.*",
"magento/module-user": "101.0.*",
Expand Down
4 changes: 4 additions & 0 deletions app/code/Magento/Backend/i18n/en_US.csv
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,7 @@ Pagination,Pagination
"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."
"Anchor Text for Next","Anchor Text for Next"
"Theme Name","Theme Name"
"In Products","In Products"
"In Orders","In Orders"
"In Customers","In Customers"
"In Pages","In Pages"
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,15 @@
</form>
<script data-template="search-suggest" type="text/x-magento-template">
<ul class="search-global-menu">
<li class="item">
<a id="searchPreviewProducts" href="<?= /* @escapeNotVerified */ $block->getUrl('catalog/product/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Products</a>
</li>
<li class="item">
<a id="searchPreviewOrders" href="<?= /* @escapeNotVerified */ $block->getUrl('sales/order/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Orders</a>
</li>
<li class="item">
<a id="searchPreviewCustomers" href="<?= /* @escapeNotVerified */ $block->getUrl('customer/index/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Customers</a>
</li>
<li class="item">
<a id="searchPreviewPages" href="<?= /* @escapeNotVerified */ $block->getUrl('cms/page/index/') ?>?search=<%- data.term%>" class="title">"<%- data.term%>" in Pages</a>
</li>
<?php foreach ($block->getEntitiesToShow() as $entity): ?>
<li class="item">
<a id="<?= /* @escapeNotVerified */ $entity->getId(); ?>"
href="<?= /* @escapeNotVerified */ $entity->getUrl() ?>?search=<%- data.term%>"
class="title">
"<%- data.term%>" <?= /* @escapeNotVerified */ __($entity->getTitle()); ?>
</a>
</li>
<?php endforeach; ?>
<% if (data.items.length) { %>
<% _.each(data.items, function(value){ %>
<li class="item"
Expand Down

0 comments on commit bc345f8

Please sign in to comment.