Skip to content

Commit 310fc0c

Browse files
author
Joan He
committed
Merge remote-tracking branch 'tango/PR-0204' into pr
2 parents 92118f5 + 39b1662 commit 310fc0c

File tree

22 files changed

+536
-138
lines changed

22 files changed

+536
-138
lines changed

app/code/Magento/Developer/Model/Setup/Declaration/Schema/WhitelistGenerator.php

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -206,20 +206,25 @@ private function getElementsWithAutogeneratedName(Schema $schema, string $tableN
206206
foreach ($tableData[$elementType] as $tableElementData) {
207207
if ($tableElementData['type'] === 'foreign') {
208208
$referenceTable = $schema->getTableByName($tableElementData['referenceTable']);
209-
$constraintName = $this->elementNameResolver->getFullFKName(
210-
$table,
211-
$table->getColumnByName($tableElementData['column']),
212-
$referenceTable,
213-
$referenceTable->getColumnByName($tableElementData['referenceColumn'])
214-
);
209+
$column = $table->getColumnByName($tableElementData['column']);
210+
$referenceColumn = $referenceTable->getColumnByName($tableElementData['referenceColumn']);
211+
$constraintName = ($column !== false && $referenceColumn !== false) ?
212+
$this->elementNameResolver->getFullFKName(
213+
$table,
214+
$column,
215+
$referenceTable,
216+
$referenceColumn
217+
) : null;
215218
} else {
216219
$constraintName = $this->elementNameResolver->getFullIndexName(
217220
$table,
218221
$tableElementData['column'],
219222
$tableElementData['type']
220223
);
221224
}
222-
$declaredStructure[$elementType][$constraintName] = true;
225+
if ($constraintName) {
226+
$declaredStructure[$elementType][$constraintName] = true;
227+
}
223228
}
224229
}
225230

app/code/Magento/Elasticsearch/Model/Adapter/BatchDataMapper/ProductDataMapper.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@
1212
use Magento\Elasticsearch\Model\Adapter\BatchDataMapperInterface;
1313
use Magento\Elasticsearch\Model\Adapter\FieldType\Date as DateFieldType;
1414
use Magento\AdvancedSearch\Model\Adapter\DataMapper\AdditionalFieldsProviderInterface;
15+
use Magento\Eav\Api\Data\AttributeOptionInterface;
1516

1617
/**
1718
* Map product index data to search engine metadata
1819
*/
1920
class ProductDataMapper implements BatchDataMapperInterface
2021
{
22+
/**
23+
* @var AttributeOptionInterface[]
24+
*/
25+
private $attributeOptionsCache;
26+
2127
/**
2228
* @var Builder
2329
*/
@@ -95,6 +101,7 @@ public function __construct(
95101
$this->excludedAttributes = array_merge($this->defaultExcludedAttributes, $excludedAttributes);
96102
$this->additionalFieldsProvider = $additionalFieldsProvider;
97103
$this->dataProvider = $dataProvider;
104+
$this->attributeOptionsCache = [];
98105
}
99106

100107
/**
@@ -272,7 +279,13 @@ private function isAttributeDate(Attribute $attribute): bool
272279
private function getValuesLabels(Attribute $attribute, array $attributeValues): array
273280
{
274281
$attributeLabels = [];
275-
foreach ($attribute->getOptions() as $option) {
282+
283+
$options = $this->getAttributeOptions($attribute);
284+
if (empty($options)) {
285+
return $attributeLabels;
286+
}
287+
288+
foreach ($options as $option) {
276289
if (\in_array($option->getValue(), $attributeValues)) {
277290
$attributeLabels[] = $option->getLabel();
278291
}
@@ -281,6 +294,22 @@ private function getValuesLabels(Attribute $attribute, array $attributeValues):
281294
return $attributeLabels;
282295
}
283296

297+
/**
298+
* Retrieve options for attribute
299+
*
300+
* @param Attribute $attribute
301+
* @return array
302+
*/
303+
private function getAttributeOptions(Attribute $attribute): array
304+
{
305+
if (!isset($this->attributeOptionsCache[$attribute->getId()])) {
306+
$options = $attribute->getOptions() ?? [];
307+
$this->attributeOptionsCache[$attribute->getId()] = $options;
308+
}
309+
310+
return $this->attributeOptionsCache[$attribute->getId()];
311+
}
312+
284313
/**
285314
* Retrieve value for field. If field have only one value this method return it.
286315
* Otherwise will be returned array of these values.

app/code/Magento/Elasticsearch/Model/Adapter/FieldMapper/Product/FieldProvider/DynamicField.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public function getFields(array $context = []): array
126126
foreach ($groups as $group) {
127127
$groupPriceKey = $this->fieldNameResolver->getFieldName(
128128
$priceAttribute,
129-
['customerGroupId' => $group->getId(), 'websiteId' => $context['websiteId']]
129+
array_merge($context, ['customerGroupId' => $group->getId()])
130130
);
131131
$allAttributes[$groupPriceKey] = [
132132
'type' => $this->fieldTypeConverter->convert(FieldTypeConverterInterface::INTERNAL_DATA_TYPE_FLOAT),

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,29 @@
88
use Magento\Framework\Search\Request\BucketInterface as RequestBucketInterface;
99
use Magento\Framework\Search\Dynamic\DataProviderInterface;
1010

11+
/**
12+
* Builder for term buckets.
13+
*/
1114
class Term implements BucketBuilderInterface
1215
{
1316
/**
14-
* {@inheritdoc}
17+
* @inheritdoc
1518
*/
1619
public function build(
1720
RequestBucketInterface $bucket,
1821
array $dimensions,
1922
array $queryResult,
2023
DataProviderInterface $dataProvider
2124
) {
25+
$buckets = $queryResult['aggregations'][$bucket->getName()]['buckets'] ?? [];
2226
$values = [];
23-
foreach ($queryResult['aggregations'][$bucket->getName()]['buckets'] as $resultBucket) {
27+
foreach ($buckets as $resultBucket) {
2428
$values[$resultBucket['key']] = [
2529
'value' => $resultBucket['key'],
2630
'count' => $resultBucket['doc_count'],
2731
];
2832
}
33+
2934
return $values;
3035
}
3136
}

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

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@
55
*/
66
namespace Magento\Elasticsearch\SearchAdapter\Query\Builder;
77

8+
use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerPool;
9+
use Magento\Framework\App\ObjectManager;
810
use Magento\Framework\Search\Request\Query\BoolExpression;
911
use Magento\Framework\Search\Request\QueryInterface as RequestQueryInterface;
1012
use Magento\Elasticsearch\Model\Adapter\FieldMapperInterface;
1113
use Magento\Framework\Search\Adapter\Preprocessor\PreprocessorInterface;
1214

15+
/**
16+
* Builder for match query.
17+
*/
1318
class Match implements QueryInterface
1419
{
1520
/**
@@ -23,24 +28,35 @@ class Match implements QueryInterface
2328
private $fieldMapper;
2429

2530
/**
31+
* @deprecated
32+
* @see \Magento\Elasticsearch\SearchAdapter\Query\ValueTransformer\TextTransformer
2633
* @var PreprocessorInterface[]
2734
*/
2835
protected $preprocessorContainer;
2936

37+
/**
38+
* @var ValueTransformerPool
39+
*/
40+
private $valueTransformerPool;
41+
3042
/**
3143
* @param FieldMapperInterface $fieldMapper
3244
* @param PreprocessorInterface[] $preprocessorContainer
45+
* @param ValueTransformerPool|null $valueTransformerPool
3346
*/
3447
public function __construct(
3548
FieldMapperInterface $fieldMapper,
36-
array $preprocessorContainer
49+
array $preprocessorContainer,
50+
ValueTransformerPool $valueTransformerPool = null
3751
) {
3852
$this->fieldMapper = $fieldMapper;
3953
$this->preprocessorContainer = $preprocessorContainer;
54+
$this->valueTransformerPool = $valueTransformerPool ?? ObjectManager::getInstance()
55+
->get(ValueTransformerPool::class);
4056
}
4157

4258
/**
43-
* {@inheritdoc}
59+
* @inheritdoc
4460
*/
4561
public function build(array $selectQuery, RequestQueryInterface $requestQuery, $conditionType)
4662
{
@@ -61,16 +77,14 @@ public function build(array $selectQuery, RequestQueryInterface $requestQuery, $
6177
}
6278

6379
/**
80+
* Prepare query.
81+
*
6482
* @param string $queryValue
6583
* @param string $conditionType
6684
* @return array
6785
*/
6886
protected function prepareQuery($queryValue, $conditionType)
6987
{
70-
$queryValue = $this->escape($queryValue);
71-
foreach ($this->preprocessorContainer as $preprocessor) {
72-
$queryValue = $preprocessor->process($queryValue);
73-
}
7488
$condition = $conditionType === BoolExpression::QUERY_CONDITION_NOT ?
7589
self::QUERY_CONDITION_MUST_NOT : $conditionType;
7690
return [
@@ -99,21 +113,34 @@ protected function buildQueries(array $matches, array $queryValue)
99113

100114
// Checking for quoted phrase \"phrase test\", trim escaped surrounding quotes if found
101115
$count = 0;
102-
$value = preg_replace('#^\\\\"(.*)\\\\"$#m', '$1', $queryValue['value'], -1, $count);
116+
$value = preg_replace('#^"(.*)"$#m', '$1', $queryValue['value'], -1, $count);
103117
$condition = ($count) ? 'match_phrase' : 'match';
104118

119+
$attributesTypes = $this->fieldMapper->getAllAttributesTypes();
120+
$transformedTypes = [];
105121
foreach ($matches as $match) {
106122
$resolvedField = $this->fieldMapper->getFieldName(
107123
$match['field'],
108124
['type' => FieldMapperInterface::TYPE_QUERY]
109125
);
126+
$valueTransformer = $this->valueTransformerPool->get($attributesTypes[$resolvedField]['type'] ?? 'text');
127+
$valueTransformerHash = \spl_object_hash($valueTransformer);
128+
if (!isset($transformedTypes[$valueTransformerHash])) {
129+
$transformedTypes[$valueTransformerHash] = $valueTransformer->transform($value);
130+
}
131+
$transformedValue = $transformedTypes[$valueTransformerHash];
132+
if (null === $transformedValue) {
133+
//Value is incompatible with this field type.
134+
continue;
135+
}
136+
110137
$conditions[] = [
111138
'condition' => $queryValue['condition'],
112139
'body' => [
113140
$condition => [
114141
$resolvedField => [
115-
'query' => $value,
116-
'boost' => isset($match['boost']) ? $match['boost'] : 1,
142+
'query' => $transformedValue,
143+
'boost' => $match['boost'] ?? 1,
117144
],
118145
],
119146
],
@@ -124,18 +151,15 @@ protected function buildQueries(array $matches, array $queryValue)
124151
}
125152

126153
/**
127-
* Cut trailing plus or minus sign, and @ symbol, using of which causes InnoDB to report a syntax error.
128-
* @link https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html Fulltext-boolean search docs.
129-
*
130154
* Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
131155
*
156+
* @deprecated
157+
* @see \Magento\Elasticsearch\SearchAdapter\Query\ValueTransformer\TextTransformer
132158
* @param string $value
133159
* @return string
134160
*/
135161
protected function escape($value)
136162
{
137-
$value = preg_replace('/@+|[@+-]+$/', '', $value);
138-
139163
$pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
140164
$replace = '\\\$1';
141165

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+
}

0 commit comments

Comments
 (0)