SynonymReader.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Search\Model\ResourceModel;
  7. use Magento\Framework\DB\Helper\Mysql\Fulltext;
  8. use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
  9. use Magento\Store\Model\StoreManagerInterface;
  10. /**
  11. * Synonym Reader resource model
  12. */
  13. class SynonymReader extends AbstractDb
  14. {
  15. /**
  16. * @var \Magento\Framework\DB\Helper\Mysql\Fulltext $fullTextSelect
  17. */
  18. private $fullTextSelect;
  19. /**
  20. * Store manager
  21. *
  22. * @var StoreManagerInterface
  23. */
  24. protected $storeManager;
  25. /**
  26. * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
  27. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  28. * @param \Magento\Framework\DB\Helper\Mysql\Fulltext $fulltext
  29. * @param string $connectionName
  30. */
  31. public function __construct(
  32. \Magento\Framework\Model\ResourceModel\Db\Context $context,
  33. \Magento\Store\Model\StoreManagerInterface $storeManager,
  34. \Magento\Framework\DB\Helper\Mysql\Fulltext $fulltext,
  35. $connectionName = null
  36. ) {
  37. parent::__construct($context, $connectionName);
  38. $this->fullTextSelect = $fulltext;
  39. $this->storeManager = $storeManager;
  40. }
  41. /**
  42. * Custom load model: Get data by user query phrase
  43. *
  44. * @param \Magento\Search\Model\SynonymReader $object
  45. * @param string $phrase
  46. * @return $this
  47. */
  48. public function loadByPhrase(\Magento\Search\Model\SynonymReader $object, $phrase)
  49. {
  50. $rows = $this->queryByPhrase(strtolower($phrase));
  51. $synsPerScope = $this->getSynRowsPerScope($rows);
  52. if (!empty($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_STORES])) {
  53. $object->setData($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_STORES]);
  54. } elseif (!empty($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES])) {
  55. $object->setData($synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES]);
  56. } else {
  57. $object->setData($synsPerScope[\Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT]);
  58. }
  59. $this->_afterLoad($object);
  60. return $this;
  61. }
  62. /**
  63. * Init resource data
  64. *
  65. * @return void
  66. */
  67. protected function _construct()
  68. {
  69. $this->_init('search_synonyms', 'group_id');
  70. }
  71. /**
  72. * A helper function to query by phrase and get results
  73. *
  74. * @param string $phrase
  75. * @return array
  76. */
  77. private function queryByPhrase($phrase)
  78. {
  79. $matchQuery = $this->fullTextSelect->getMatchQuery(
  80. ['synonyms' => 'synonyms'],
  81. $phrase,
  82. Fulltext::FULLTEXT_MODE_BOOLEAN
  83. );
  84. $query = $this->getConnection()->select()->from(
  85. $this->getMainTable()
  86. )->where($matchQuery);
  87. return $this->getConnection()->fetchAll($query);
  88. }
  89. /**
  90. * A private helper function to retrieve matching synonym groups per scope
  91. *
  92. * @param array $rows
  93. * @return array
  94. */
  95. private function getSynRowsPerScope($rows)
  96. {
  97. $synRowsForStoreView = [];
  98. $synRowsForWebsite = [];
  99. $synRowsForDefault = [];
  100. // The synonyms configured for current store view gets highest priority. Second highest is current website
  101. // scope. If there were no store view and website specific synonyms then at last 'default' (All store views)
  102. // will be considered.
  103. foreach ($rows as $row) {
  104. if ($this->isSynRowForStoreView($row)) {
  105. // Check for current store view
  106. $synRowsForStoreView[] = $row;
  107. } elseif (empty($synRowsForStoreView) && $this->isSynRowForWebsite($row)) {
  108. // Check for current website
  109. $synRowsForWebsite[] = $row;
  110. } elseif (empty($synRowsForStoreView)
  111. && empty($synRowsForWebsite)
  112. && $this->isSynRowForDefaultScope($row)) {
  113. // Check for all store views (i.e. global/default config)
  114. $synRowsForDefault[] = $row;
  115. }
  116. }
  117. $synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_STORES] = $synRowsForStoreView;
  118. $synsPerScope[\Magento\Store\Model\ScopeInterface::SCOPE_WEBSITES] = $synRowsForWebsite;
  119. $synsPerScope[\Magento\Framework\App\Config\ScopeConfigInterface::SCOPE_TYPE_DEFAULT] = $synRowsForDefault;
  120. return $synsPerScope;
  121. }
  122. /**
  123. * A helper method to check if the synonym group row is for the current store view
  124. *
  125. * @param array $row
  126. * @return bool
  127. */
  128. private function isSynRowForStoreView($row)
  129. {
  130. $storeViewId = $this->storeManager->getStore()->getId();
  131. return ($row['store_id'] === $storeViewId);
  132. }
  133. /**
  134. * A helper method to check if the synonym group row is for the current website
  135. *
  136. * @param array $row
  137. * @return bool
  138. */
  139. private function isSynRowForWebsite($row)
  140. {
  141. $websiteId = $this->storeManager->getStore()->getWebsiteId();
  142. return (($row['website_id'] === $websiteId) && ($row['store_id'] == 0));
  143. }
  144. /**
  145. * A helper method to check if the synonym group row is for all store views (default or global scope)
  146. *
  147. * @param array $row
  148. * @return bool
  149. */
  150. private function isSynRowForDefaultScope($row)
  151. {
  152. return (($row['website_id'] == 0) && ($row['store_id'] == 0));
  153. }
  154. }