Skip to content

Commit 5ace3df

Browse files
committed
Merge branch 'ACP2E-68' of https://github.com/magento-l3/magento2ce into PR-2021-20-08
2 parents da8d65d + 5713c1b commit 5ace3df

File tree

3 files changed

+238
-3
lines changed

3 files changed

+238
-3
lines changed

app/code/Magento/CatalogGraphQl/Model/Resolver/Products/Query/Search.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Magento\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder;
1111
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch;
12+
use Magento\CatalogGraphQl\Model\Resolver\Products\Query\Search\QueryPopularity;
1213
use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResult;
1314
use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResultFactory;
1415
use Magento\Framework\Api\Search\SearchCriteriaInterface;
@@ -22,6 +23,8 @@
2223

2324
/**
2425
* Full text search for catalog using given search criteria.
26+
*
27+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2528
*/
2629
class Search implements ProductQueryInterface
2730
{
@@ -60,6 +63,11 @@ class Search implements ProductQueryInterface
6063
*/
6164
private $searchCriteriaBuilder;
6265

66+
/**
67+
* @var QueryPopularity
68+
*/
69+
private $queryPopularity;
70+
6371
/**
6472
* @param SearchInterface $search
6573
* @param SearchResultFactory $searchResultFactory
@@ -68,6 +76,7 @@ class Search implements ProductQueryInterface
6876
* @param ProductSearch $productsProvider
6977
* @param SearchCriteriaBuilder $searchCriteriaBuilder
7078
* @param ArgumentsProcessorInterface|null $argsSelection
79+
* @param QueryPopularity|null $queryPopularity
7180
*/
7281
public function __construct(
7382
SearchInterface $search,
@@ -76,16 +85,17 @@ public function __construct(
7685
FieldSelection $fieldSelection,
7786
ProductSearch $productsProvider,
7887
SearchCriteriaBuilder $searchCriteriaBuilder,
79-
ArgumentsProcessorInterface $argsSelection = null
88+
ArgumentsProcessorInterface $argsSelection = null,
89+
QueryPopularity $queryPopularity = null
8090
) {
8191
$this->search = $search;
8292
$this->searchResultFactory = $searchResultFactory;
8393
$this->pageSizeProvider = $pageSize;
8494
$this->fieldSelection = $fieldSelection;
8595
$this->productsProvider = $productsProvider;
8696
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
87-
$this->argsSelection = $argsSelection ?: ObjectManager::getInstance()
88-
->get(ArgumentsProcessorInterface::class);
97+
$this->argsSelection = $argsSelection ?: ObjectManager::getInstance()->get(ArgumentsProcessorInterface::class);
98+
$this->queryPopularity = $queryPopularity ?: ObjectManager::getInstance()->get(QueryPopularity::class);
8999
}
90100

91101
/**
@@ -124,6 +134,11 @@ public function getResult(
124134

125135
$totalPages = $realPageSize ? ((int)ceil($searchResults->getTotalCount() / $realPageSize)) : 0;
126136

137+
// add query statistics data
138+
if (!empty($args['search'])) {
139+
$this->queryPopularity->execute($context, $args['search'], (int) $searchResults->getTotalCount());
140+
}
141+
127142
$productArray = [];
128143
/** @var \Magento\Catalog\Model\Product $product */
129144
foreach ($searchResults->getItems() as $product) {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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\Products\Query\Search;
9+
10+
use Magento\Framework\Stdlib\StringUtils as StdlibString;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\GraphQl\Model\Query\ContextInterface;
14+
use Magento\Search\Model\QueryFactory;
15+
16+
/**
17+
* Query statics handler
18+
*/
19+
class QueryPopularity
20+
{
21+
/**
22+
* @var QueryFactory
23+
*/
24+
private $queryFactory;
25+
26+
/**
27+
* @var StdlibString
28+
*/
29+
private $string;
30+
31+
/**
32+
* @param QueryFactory $queryFactory
33+
* @param StdlibString $string
34+
*/
35+
public function __construct(
36+
QueryFactory $queryFactory,
37+
StdlibString $string
38+
) {
39+
$this->queryFactory = $queryFactory;
40+
$this->string = $string;
41+
}
42+
43+
/**
44+
* Fill the query popularity
45+
*
46+
* @param ContextInterface $context
47+
* @param string $queryText
48+
* @param int $numResults
49+
* @return void
50+
* @throws NoSuchEntityException
51+
* @throws LocalizedException
52+
*/
53+
public function execute(ContextInterface $context, string $queryText, int $numResults) : void
54+
{
55+
$query = $this->queryFactory->create();
56+
$maxQueryLength = (int) $query->getMaxQueryLength();
57+
if ($maxQueryLength && $this->string->strlen($queryText) > $maxQueryLength) {
58+
$queryText = $this->string->substr($queryText, 0, $maxQueryLength);
59+
}
60+
$query->setQueryText($queryText);
61+
$store = $context->getExtensionAttributes()->getStore();
62+
$query->setStoreId($store->getId());
63+
$query->saveIncrementalPopularity();
64+
$query->saveNumResults($numResults);
65+
}
66+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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\Test\Unit\Model\Resolver\Products\Query;
9+
10+
use Magento\CatalogGraphQl\DataProvider\Product\SearchCriteriaBuilder;
11+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch;
12+
use Magento\CatalogGraphQl\Model\Resolver\Products\Query\FieldSelection;
13+
use Magento\CatalogGraphQl\Model\Resolver\Products\Query\Search;
14+
use Magento\CatalogGraphQl\Model\Resolver\Products\Query\Search\QueryPopularity;
15+
use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResultFactory;
16+
use Magento\Framework\Api\Search\SearchCriteriaInterface;
17+
use Magento\Framework\Api\Search\SearchResultInterface;
18+
use Magento\Framework\GraphQl\Query\Resolver\ArgumentsProcessorInterface;
19+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
20+
use Magento\GraphQl\Model\Query\ContextExtensionInterface;
21+
use Magento\GraphQl\Model\Query\ContextInterface;
22+
use Magento\Search\Api\SearchInterface;
23+
use Magento\Search\Model\Search\PageSizeProvider;
24+
use Magento\Store\Api\Data\StoreInterface;
25+
use PHPUnit\Framework\MockObject\MockObject;
26+
use PHPUnit\Framework\TestCase;
27+
28+
/**
29+
* Test for fulltext search query
30+
*
31+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
32+
*/
33+
class SearchTest extends TestCase
34+
{
35+
/**
36+
* @var SearchInterface|MockObject
37+
*/
38+
private $search;
39+
40+
/**
41+
* @var SearchResultFactory|MockObject
42+
*/
43+
private $searchResultFactory;
44+
45+
/**
46+
* @var PageSizeProvider|MockObject
47+
*/
48+
private $pageSizeProvider;
49+
50+
/**
51+
* @var FieldSelection|MockObject
52+
*/
53+
private $fieldSelection;
54+
55+
/**
56+
* @var ArgumentsProcessorInterface|MockObject
57+
*/
58+
private $argsSelection;
59+
60+
/**
61+
* @var ProductSearch|MockObject
62+
*/
63+
private $productsProvider;
64+
65+
/**
66+
* @var SearchCriteriaBuilder|MockObject
67+
*/
68+
private $searchCriteriaBuilder;
69+
70+
/**
71+
* @var QueryPopularity|MockObject
72+
*/
73+
private $queryPopularity;
74+
75+
/**
76+
* @var Search
77+
*/
78+
private $model;
79+
80+
/**
81+
* @inheritdoc
82+
*/
83+
protected function setUp(): void
84+
{
85+
parent::setUp();
86+
$this->search = $this->getMockBuilder(SearchInterface::class)
87+
->disableOriginalConstructor()
88+
->getMockForAbstractClass();
89+
$this->searchResultFactory = $this->getMockBuilder(SearchResultFactory::class)
90+
->disableOriginalConstructor()
91+
->getMock();
92+
$this->pageSizeProvider = $this->getMockBuilder(PageSizeProvider::class)
93+
->disableOriginalConstructor()
94+
->getMock();
95+
$this->fieldSelection = $this->getMockBuilder(FieldSelection::class)
96+
->disableOriginalConstructor()
97+
->getMock();
98+
$this->argsSelection = $this->getMockBuilder(ArgumentsProcessorInterface::class)
99+
->disableOriginalConstructor()
100+
->getMockForAbstractClass();
101+
$this->productsProvider = $this->getMockBuilder(ProductSearch::class)
102+
->disableOriginalConstructor()
103+
->getMock();
104+
$this->searchCriteriaBuilder = $this->getMockBuilder(SearchCriteriaBuilder::class)
105+
->disableOriginalConstructor()
106+
->getMock();
107+
$this->queryPopularity = $this->getMockBuilder(QueryPopularity::class)
108+
->disableOriginalConstructor()
109+
->getMock();
110+
$this->model = new Search(
111+
$this->search,
112+
$this->searchResultFactory,
113+
$this->pageSizeProvider,
114+
$this->fieldSelection,
115+
$this->productsProvider,
116+
$this->searchCriteriaBuilder,
117+
$this->argsSelection,
118+
$this->queryPopularity
119+
);
120+
}
121+
122+
public function testPopulateSearchQueryStats(): void
123+
{
124+
$args = ['search' => 'test'];
125+
$context = $this->getMockBuilder(ContextInterface::class)
126+
->disableOriginalConstructor()
127+
->getMockForAbstractClass();
128+
$resolveInfo = $this->getMockBuilder(ResolveInfo::class)
129+
->disableOriginalConstructor()
130+
->getMock();
131+
132+
$searchCriteria = $this->getMockBuilder(SearchCriteriaInterface::class)
133+
->disableOriginalConstructor()
134+
->getMockForAbstractClass();
135+
$this->searchCriteriaBuilder->expects($this->any())
136+
->method('build')
137+
->willReturn($searchCriteria);
138+
$results = $this->getMockBuilder(SearchResultInterface::class)
139+
->disableOriginalConstructor()
140+
->getMockForAbstractClass();
141+
$this->search->expects($this->once())
142+
->method('search')
143+
->with($searchCriteria)
144+
->willReturn($results);
145+
$this->productsProvider->expects($this->any())->method('getList')->willReturn($results);
146+
$results->expects($this->any())->method('getItems')->willReturn([]);
147+
148+
$this->queryPopularity->expects($this->once())
149+
->method('execute')
150+
->with($context, $args['search'], 0);
151+
152+
$this->model->getResult($args, $resolveInfo, $context);
153+
}
154+
}

0 commit comments

Comments
 (0)