Skip to content

Commit f3e52e5

Browse files
committed
Merge branch 'MAGETWO-97830' of https://github.com/magento-tango/magento2ce into pr_2019_03_20
2 parents 20d1ff7 + fa7a749 commit f3e52e5

File tree

18 files changed

+462
-79
lines changed

18 files changed

+462
-79
lines changed

app/code/Magento/Elasticsearch/SearchAdapter/Aggregation/Builder/Term.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ public function build(
2222
array $queryResult,
2323
DataProviderInterface $dataProvider
2424
) {
25+
$buckets = $queryResult['aggregations'][$bucket->getName()]['buckets'] ?? [];
2526
$values = [];
26-
foreach ($queryResult['aggregations'][$bucket->getName()]['buckets'] as $resultBucket) {
27+
foreach ($buckets as $resultBucket) {
2728
$values[$resultBucket['key']] = [
2829
'value' => $resultBucket['key'],
2930
'count' => $resultBucket['doc_count'],
3031
];
3132
}
33+
3234
return $values;
3335
}
3436
}

app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Match.php

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
*/
66
namespace Magento\Elasticsearch\SearchAdapter\Query\Builder;
77

8+
use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\AttributeProvider;
9+
use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\FieldType\ResolverInterface as TypeResolver;
10+
use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerPool;
11+
use Magento\Framework\App\ObjectManager;
812
use Magento\Framework\Search\Request\Query\BoolExpression;
913
use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface;
1014
use Magento\Elasticsearch\Model\Adapter\FieldMapperInterface;
@@ -26,20 +30,49 @@ class Match implements QueryInterface
2630
private $fieldMapper;
2731

2832
/**
33+
* @deprecated
34+
* @see \Magento\Elasticsearch\SearchAdapter\Query\ValueTransformer\TextTransformer
2935
* @var PreprocessorInterface[]
3036
*/
3137
protected $preprocessorContainer;
3238

39+
/**
40+
* @var AttributeProvider
41+
*/
42+
private $attributeProvider;
43+
44+
/**
45+
* @var TypeResolver
46+
*/
47+
private $fieldTypeResolver;
48+
49+
/**
50+
* @var ValueTransformerPool
51+
*/
52+
private $valueTransformerPool;
53+
3354
/**
3455
* @param FieldMapperInterface $fieldMapper
3556
* @param PreprocessorInterface[] $preprocessorContainer
57+
* @param AttributeProvider|null $attributeProvider
58+
* @param TypeResolver|null $fieldTypeResolver
59+
* @param ValueTransformerPool|null $valueTransformerPool
3660
*/
3761
public function __construct(
3862
FieldMapperInterface $fieldMapper,
39-
array $preprocessorContainer
63+
array $preprocessorContainer,
64+
AttributeProvider $attributeProvider = null,
65+
TypeResolver $fieldTypeResolver = null,
66+
ValueTransformerPool $valueTransformerPool = null
4067
) {
4168
$this->fieldMapper = $fieldMapper;
4269
$this->preprocessorContainer = $preprocessorContainer;
70+
$this->attributeProvider = $attributeProvider ?? ObjectManager::getInstance()
71+
->get(AttributeProvider::class);
72+
$this->fieldTypeResolver = $fieldTypeResolver ?? ObjectManager::getInstance()
73+
->get(TypeResolver::class);
74+
$this->valueTransformerPool = $valueTransformerPool ?? ObjectManager::getInstance()
75+
->get(ValueTransformerPool::class);
4376
}
4477

4578
/**
@@ -72,10 +105,6 @@ public function build(array $selectQuery, RequestQueryInterface $requestQuery, $
72105
*/
73106
protected function prepareQuery($queryValue, $conditionType)
74107
{
75-
$queryValue = $this->escape($queryValue);
76-
foreach ($this->preprocessorContainer as $preprocessor) {
77-
$queryValue = $preprocessor->process($queryValue);
78-
}
79108
$condition = $conditionType === BoolExpression::QUERY_CONDITION_NOT ?
80109
self::QUERY_CONDITION_MUST_NOT : $conditionType;
81110
return [
@@ -104,10 +133,24 @@ protected function buildQueries(array $matches, array $queryValue)
104133

105134
// Checking for quoted phrase \"phrase test\", trim escaped surrounding quotes if found
106135
$count = 0;
107-
$value = preg_replace('#^\\\\"(.*)\\\\"$#m', '$1', $queryValue['value'], -1, $count);
136+
$value = preg_replace('#^"(.*)"$#m', '$1', $queryValue['value'], -1, $count);
108137
$condition = ($count) ? 'match_phrase' : 'match';
109138

139+
$transformedTypes = [];
110140
foreach ($matches as $match) {
141+
$attributeAdapter = $this->attributeProvider->getByAttributeCode($match['field']);
142+
$fieldType = $this->fieldTypeResolver->getFieldType($attributeAdapter);
143+
$valueTransformer = $this->valueTransformerPool->get($fieldType ?? 'text');
144+
$valueTransformerHash = \spl_object_hash($valueTransformer);
145+
if (!isset($transformedTypes[$valueTransformerHash])) {
146+
$transformedTypes[$valueTransformerHash] = $valueTransformer->transform($value);
147+
}
148+
$transformedValue = $transformedTypes[$valueTransformerHash];
149+
if (null === $transformedValue) {
150+
//Value is incompatible with this field type.
151+
continue;
152+
}
153+
111154
$resolvedField = $this->fieldMapper->getFieldName(
112155
$match['field'],
113156
['type' => FieldMapperInterface::TYPE_QUERY]
@@ -117,8 +160,8 @@ protected function buildQueries(array $matches, array $queryValue)
117160
'body' => [
118161
$condition => [
119162
$resolvedField => [
120-
'query' => $value,
121-
'boost' => isset($match['boost']) ? $match['boost'] : 1,
163+
'query' => $transformedValue,
164+
'boost' => $match['boost'] ?? 1,
122165
],
123166
],
124167
],
@@ -131,16 +174,13 @@ protected function buildQueries(array $matches, array $queryValue)
131174
/**
132175
* Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
133176
*
134-
* Cut trailing plus or minus sign, and @ symbol, using of which causes InnoDB to report a syntax error.
135-
* https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html Fulltext-boolean search docs.
136-
*
177+
* @deprecated
178+
* @see \Magento\Elasticsearch\SearchAdapter\Query\ValueTransformer\TextTransformer
137179
* @param string $value
138180
* @return string
139181
*/
140182
protected function escape($value)
141183
{
142-
$value = preg_replace('/@+|[@+-]+$/', '', $value);
143-
144184
$pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
145185
$replace = '\\\$1';
146186

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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\Elasticsearch\SearchAdapter\Query\ValueTransformer;
9+
10+
use Magento\Elasticsearch\Model\Adapter\FieldType\Date;
11+
use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerInterface;
12+
13+
/**
14+
* Value transformer for date type fields.
15+
*/
16+
class DateTransformer implements ValueTransformerInterface
17+
{
18+
/**
19+
* @var Date
20+
*/
21+
private $dateFieldType;
22+
23+
/**
24+
* @param Date $dateFieldType
25+
*/
26+
public function __construct(Date $dateFieldType)
27+
{
28+
$this->dateFieldType = $dateFieldType;
29+
}
30+
31+
/**
32+
* @inheritdoc
33+
*/
34+
public function transform(string $value): ?string
35+
{
36+
try {
37+
$formattedDate = $this->dateFieldType->formatDate(null, $value);
38+
} catch (\Exception $e) {
39+
$formattedDate = null;
40+
}
41+
42+
return $formattedDate;
43+
}
44+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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\Elasticsearch\SearchAdapter\Query\ValueTransformer;
9+
10+
use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerInterface;
11+
12+
/**
13+
* Value transformer for float type fields.
14+
*/
15+
class FloatTransformer implements ValueTransformerInterface
16+
{
17+
/**
18+
* @inheritdoc
19+
*/
20+
public function transform(string $value): ?float
21+
{
22+
return \is_numeric($value) ? (float) $value : null;
23+
}
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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\Elasticsearch\SearchAdapter\Query\ValueTransformer;
9+
10+
use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerInterface;
11+
12+
/**
13+
* Value transformer for integer type fields.
14+
*/
15+
class IntegerTransformer implements ValueTransformerInterface
16+
{
17+
/**
18+
* @inheritdoc
19+
*/
20+
public function transform(string $value): ?int
21+
{
22+
return \is_numeric($value) ? (int) $value : null;
23+
}
24+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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\Elasticsearch\SearchAdapter\Query\ValueTransformer;
9+
10+
use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerInterface;
11+
use Magento\Framework\Search\Adapter\Preprocessor\PreprocessorInterface;
12+
13+
/**
14+
* Value transformer for fields with text types.
15+
*/
16+
class TextTransformer implements ValueTransformerInterface
17+
{
18+
/**
19+
* @var PreprocessorInterface[]
20+
*/
21+
private $preprocessors;
22+
23+
/**
24+
* @param PreprocessorInterface[] $preprocessors
25+
*/
26+
public function __construct(array $preprocessors = [])
27+
{
28+
foreach ($preprocessors as $preprocessor) {
29+
if (!$preprocessor instanceof PreprocessorInterface) {
30+
throw new \InvalidArgumentException(
31+
\sprintf('"%s" is not a instance of ValueTransformerInterface.', get_class($preprocessor))
32+
);
33+
}
34+
}
35+
36+
$this->preprocessors = $preprocessors;
37+
}
38+
39+
/**
40+
* @inheritdoc
41+
*/
42+
public function transform(string $value): string
43+
{
44+
$value = $this->escape($value);
45+
foreach ($this->preprocessors as $preprocessor) {
46+
$value = $preprocessor->process($value);
47+
}
48+
49+
return $value;
50+
}
51+
52+
/**
53+
* Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
54+
*
55+
* @param string $value
56+
* @return string
57+
*/
58+
private function escape(string $value): string
59+
{
60+
$pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
61+
$replace = '\\\$1';
62+
63+
return preg_replace($pattern, $replace, $value);
64+
}
65+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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\Elasticsearch\SearchAdapter\Query;
9+
10+
/**
11+
* Value transformer of search term for matching with ES field types.
12+
*/
13+
interface ValueTransformerInterface
14+
{
15+
/**
16+
* Transform value according to field type.
17+
*
18+
* @param string $value
19+
* @return mixed
20+
*/
21+
public function transform(string $value);
22+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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\Elasticsearch\SearchAdapter\Query;
9+
10+
/**
11+
* Pool of value transformers.
12+
*/
13+
class ValueTransformerPool
14+
{
15+
/**
16+
* @var ValueTransformerInterface[]
17+
*/
18+
private $transformers;
19+
20+
/**
21+
* @param ValueTransformerInterface[] $valueTransformers
22+
*/
23+
public function __construct(array $valueTransformers = [])
24+
{
25+
foreach ($valueTransformers as $valueTransformer) {
26+
if (!$valueTransformer instanceof ValueTransformerInterface) {
27+
throw new \InvalidArgumentException(
28+
\sprintf('"%s" is not a instance of ValueTransformerInterface.', get_class($valueTransformer))
29+
);
30+
}
31+
}
32+
33+
$this->transformers = $valueTransformers;
34+
}
35+
36+
/**
37+
* Get value transformer related to field type.
38+
*
39+
* @param string $fieldType
40+
* @return ValueTransformerInterface
41+
*/
42+
public function get(string $fieldType): ValueTransformerInterface
43+
{
44+
return $this->transformers[$fieldType] ?? $this->transformers['default'];
45+
}
46+
}

0 commit comments

Comments
 (0)