Skip to content

Commit

Permalink
Merge pull request magento#1577 from magento-panda/PANDA-FIXES-2.2
Browse files Browse the repository at this point in the history
Fixed issue:
MAGETWO-77777 [2.2.x] - [Magento Cloud] Using search synonyms from the same group gives different results

array bug fix

Category_ids display no

Refactoring

continue condition

Condition rewrite
  • Loading branch information
igrybkov authored and manuelson committed Oct 13, 2017
2 parents ba4b975 + a4f4d8d commit c33d9d7
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 32 deletions.
6 changes: 3 additions & 3 deletions app/code/Magento/Catalog/Block/Product/View/Attributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ public function getAdditionalData(array $excludeAttr = [])
$attributes = $product->getAttributes();
foreach ($attributes as $attribute) {
if ($attribute->getIsVisibleOnFront() && !in_array($attribute->getAttributeCode(), $excludeAttr)) {
$value = $attribute->getFrontend()->getValue($product);

if (is_array($value = $attribute->getFrontend()->getValue($product))) {
continue;
}
if (!$product->hasData($attribute->getAttributeCode())) {
$value = __('N/A');
} elseif ((string)$value == '') {
$value = __('No');
} elseif ($attribute->getFrontendInput() == 'price' && is_string($value)) {
$value = $this->priceCurrency->convertAndFormat($value);
}

if ($value instanceof Phrase || (is_string($value) && strlen($value))) {
$data[$attribute->getAttributeCode()] = [
'label' => __($attribute->getStoreLabel()),
Expand Down
127 changes: 98 additions & 29 deletions app/code/Magento/Search/Model/SynonymAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);
namespace Magento\Search\Model;

use Magento\Search\Api\SynonymAnalyzerInterface;

/**
* SynonymAnalyzer responsible for search of synonyms matching a word or a phrase.
*/
class SynonymAnalyzer implements SynonymAnalyzerInterface
{
/**
Expand Down Expand Up @@ -42,55 +47,119 @@ public function __construct(SynonymReader $synReader)
*/
public function getSynonymsForPhrase($phrase)
{
$synGroups = [];
$result = [];

if (empty($phrase)) {
return $synGroups;
if (empty(trim($phrase))) {
return $result;
}

$rows = $this->synReaderModel->loadByPhrase($phrase)->getData();
$synonyms = [];
foreach ($rows as $row) {
$synonyms [] = $row['synonyms'];
}
$synonymGroups = $this->getSynonymGroupsByPhrase($phrase);

// Replace multiple spaces in a row with the only one space
$phrase = preg_replace("/ {2,}/", " ", $phrase);

// Go through every returned record looking for presence of the actual phrase. If there were no matching
// records found in DB then create a new entry for it in the returned array
$words = explode(' ', $phrase);
foreach ($words as $w) {
$position = $this->findInArray($w, $synonyms);
if ($position !== false) {
$synGroups[] = explode(',', $synonyms[$position]);
} else {
// No synonyms were found. Return the original word in this position
$synGroups[] = [$w];

foreach ($words as $offset => $word) {
$synonyms = [$word];

if ($synonymGroups) {
$pattern = $this->getSearchPattern(array_slice($words, $offset));
$position = $this->findInArray($pattern, $synonymGroups);
if ($position !== null) {
$synonyms = explode(',', $synonymGroups[$position]);
}
}

$result[] = $synonyms;
}
return $synGroups;

return $result;
}

/**
* Helper method to find the presence of $word in $wordsArray. If found, the particular array index is returned.
* Helper method to find the matching of $pattern to $synonymGroupsToExamine.
* If matches, the particular array index is returned.
* Otherwise false will be returned.
*
* @param string $word
* @param $array $wordsArray
* @return boolean | int
* @param string $pattern
* @param array $synonymGroupsToExamine
* @return int|null
*/
private function findInArray($word, $wordsArray)
private function findInArray(string $pattern, array $synonymGroupsToExamine)
{
if (empty($wordsArray)) {
return false;
}
$position = 0;
foreach ($wordsArray as $wordsLine) {
$pattern = '/^' . $word . ',|,' . $word . ',|,' . $word . '$/';
$rv = preg_match($pattern, $wordsLine);
if ($rv != 0) {
foreach ($synonymGroupsToExamine as $synonymGroup) {
$matchingResultCode = preg_match($pattern, $synonymGroup);
if ($matchingResultCode === 1) {
return $position;
}
$position++;
}
return false;
return null;
}

/**
* Returns a regular expression to search for synonyms of the phrase represented as the list of words.
*
* Returned pattern contains expression to search for a part of the phrase from the beginning.
*
* For example, in the phrase "Elizabeth is the English queen" with subset from the very first word,
* the method will build an expression which looking for synonyms for all these patterns:
* - Elizabeth is the English queen
* - Elizabeth is the English
* - Elizabeth is the
* - Elizabeth is
* - Elizabeth
*
* For the same phrase on the second iteration with the first word "is" it will match for these synonyms:
* - is the English queen
* - is the English
* - is the
* - is
*
* The pattern looking for exact match and will not find these phrases as synonyms:
* - Is there anybody in the room?
* - Is the English is most popular language?
* - Is the English queen Elizabeth?
*
* Take into account that returned pattern expects that data will be represented as comma-separated value.
*
* @param array $words
* @return string
*/
private function getSearchPattern(array $words): string
{
$patterns = [];
for ($lastItem = count($words); $lastItem > 0; $lastItem--) {
$phrase = implode("\s+", array_slice($words, 0, $lastItem));
$patterns[] = '^' . $phrase . ',';
$patterns[] = ',' . $phrase . ',';
$patterns[] = ',' . $phrase . '$';
}

$pattern = '/' . implode('|', $patterns) . '/i';
return $pattern;
}

/**
* Get all synonym groups for the phrase
*
* Returns an array of synonyms which are represented as comma-separated value for each item in the list
*
* @param string $phrase
* @return string[]
*/
private function getSynonymGroupsByPhrase(string $phrase): array
{
$result = [];

$synonymGroups = $this->synReaderModel->loadByPhrase($phrase)->getData();
foreach ($synonymGroups as $row) {
$result[] = $row['synonyms'];
}
return $result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,38 @@ public static function loadGetSynonymsForPhraseDataProvider()
'phrase' => 'universe is enormous',
'expectedResult' => [['universe', 'cosmos'], ['is'], ['big', 'huge', 'large', 'enormous']]
],
'WithCaseMismatch' => [
'phrase' => 'GNU\'s Not Unix',
'expectedResult' => [['GNU\'s'], ['Not'], ['unix', 'linux'],]
],
'WithMultiWordPhrase' => [
'phrase' => 'Coastline of Great Britain stretches for 11,073 miles',
'expectedResult' => [
['Coastline'],
['of'],
['Great Britain', 'United Kingdom'],
['Britain'],
['stretches'],
['for'],
['11,073'],
['miles']
]
],
'PartialSynonymMatching' => [
'phrase' => 'Magento Engineering',
'expectedResult' => [
['orange', 'magento'],
['Engineering', 'Technical Staff']
]
],
'noSynonyms' => [
'phrase' => 'this sentence has no synonyms',
'expectedResult' => [['this'], ['sentence'], ['has'], ['no'], ['synonyms']]
],
'multipleSpaces' => [
'phrase' => 'GNU\'s Not Unix',
'expectedResult' => [['GNU\'s'], ['Not'], ['unix', 'linux'],]
],
'oneMoreTest' => [
'phrase' => 'schlicht',
'expectedResult' => [['schlicht', 'natürlich']]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,22 @@
$synonymsModel = $objectManager->create(\Magento\Search\Model\SynonymReader::class);
$synonymsModel->setSynonyms('hill,mountain,peak')->setWebsiteId(1)->save();

$synonymsModel = $objectManager->create(\Magento\Search\Model\SynonymReader::class);
$synonymsModel->setSynonyms('Community Engineering,Contributors,Magento Community Engineering')->setWebsiteId(1)
->save();

$synonymsModel = $objectManager->create(\Magento\Search\Model\SynonymReader::class);
$synonymsModel->setSynonyms('Engineering,Technical Staff')->setWebsiteId(1)->save();

// Synonym groups for "All Store Views"
$synonymsModel = $objectManager->create(\Magento\Search\Model\SynonymReader::class);
$synonymsModel->setSynonyms('universe,cosmos')->setWebsiteId(0)->save();

$synonymsModel = $objectManager->create(\Magento\Search\Model\SynonymReader::class);
$synonymsModel->setSynonyms('unix,linux')->setWebsiteId(0)->save();

$synonymsModel = $objectManager->create(\Magento\Search\Model\SynonymReader::class);
$synonymsModel->setSynonyms('Great Britain,United Kingdom')->setWebsiteId(0)->save();

$synonymsModel = $objectManager->create(\Magento\Search\Model\SynonymReader::class);
$synonymsModel->setSynonyms('big,huge,large,enormous')->setWebsiteId(0)->save();

0 comments on commit c33d9d7

Please sign in to comment.