PageRenderTime 49ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/Magento/CatalogSearch/Model/Advanced.php

https://gitlab.com/crazybutterfly815/magento2
PHP | 388 lines | 218 code | 30 blank | 140 comment | 43 complexity | cee67249925a8a366ffcdafd78d2a765 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright © 2016 Magento. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\CatalogSearch\Model;
  7. use Magento\Catalog\Model\Config;
  8. use Magento\Catalog\Model\Product\Visibility;
  9. use Magento\Catalog\Model\ProductFactory;
  10. use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
  11. use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory as AttributeCollectionFactory;
  12. use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
  13. use Magento\CatalogSearch\Model\ResourceModel\Advanced\Collection as ProductCollection;
  14. use Magento\CatalogSearch\Model\ResourceModel\AdvancedFactory;
  15. use Magento\Directory\Model\CurrencyFactory;
  16. use Magento\Eav\Model\Entity\Attribute as EntityAttribute;
  17. use Magento\Framework\Model\Context;
  18. use Magento\Framework\Exception\LocalizedException;
  19. use Magento\Framework\Registry;
  20. use Magento\Store\Model\StoreManagerInterface;
  21. /**
  22. * Catalog advanced search model
  23. * @method \Magento\CatalogSearch\Model\ResourceModel\Advanced getResource()
  24. * @method int getEntityTypeId()
  25. * @method \Magento\CatalogSearch\Model\Advanced setEntityTypeId(int $value)
  26. * @method int getAttributeSetId()
  27. * @method \Magento\CatalogSearch\Model\Advanced setAttributeSetId(int $value)
  28. * @method string getTypeId()
  29. * @method \Magento\CatalogSearch\Model\Advanced setTypeId(string $value)
  30. * @method string getSku()
  31. * @method \Magento\CatalogSearch\Model\Advanced setSku(string $value)
  32. * @method int getHasOptions()
  33. * @method \Magento\CatalogSearch\Model\Advanced setHasOptions(int $value)
  34. * @method int getRequiredOptions()
  35. * @method \Magento\CatalogSearch\Model\Advanced setRequiredOptions(int $value)
  36. * @method string getCreatedAt()
  37. * @method \Magento\CatalogSearch\Model\Advanced setCreatedAt(string $value)
  38. * @method string getUpdatedAt()
  39. * @method \Magento\CatalogSearch\Model\Advanced setUpdatedAt(string $value)
  40. *
  41. * @author Magento Core Team <core@magentocommerce.com>
  42. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  43. */
  44. class Advanced extends \Magento\Framework\Model\AbstractModel
  45. {
  46. /**
  47. * User friendly search criteria list
  48. *
  49. * @var array
  50. */
  51. protected $_searchCriterias = [];
  52. /**
  53. * Product collection
  54. *
  55. * @var ProductCollection
  56. */
  57. protected $_productCollection;
  58. /**
  59. * Initialize dependencies
  60. *
  61. * @var Config
  62. */
  63. protected $_catalogConfig;
  64. /**
  65. * Catalog product visibility
  66. *
  67. * @var Visibility
  68. */
  69. protected $_catalogProductVisibility;
  70. /**
  71. * Attribute collection factory
  72. *
  73. * @var AttributeCollectionFactory
  74. */
  75. protected $_attributeCollectionFactory;
  76. /**
  77. * Store manager
  78. *
  79. * @var \Magento\Store\Model\StoreManagerInterface
  80. */
  81. protected $_storeManager;
  82. /**
  83. * Product factory
  84. *
  85. * @var ProductFactory
  86. */
  87. protected $_productFactory;
  88. /**
  89. * Currency factory
  90. *
  91. * @var CurrencyFactory
  92. */
  93. protected $_currencyFactory;
  94. /**
  95. * Advanced Collection Factory
  96. *
  97. * @var ProductCollectionFactory
  98. */
  99. protected $productCollectionFactory;
  100. /**
  101. * Construct
  102. *
  103. * @param Context $context
  104. * @param Registry $registry
  105. * @param AttributeCollectionFactory $attributeCollectionFactory
  106. * @param Visibility $catalogProductVisibility
  107. * @param Config $catalogConfig
  108. * @param CurrencyFactory $currencyFactory
  109. * @param ProductFactory $productFactory
  110. * @param StoreManagerInterface $storeManager
  111. * @param ProductCollectionFactory $productCollectionFactory
  112. * @param AdvancedFactory $advancedFactory
  113. * @param array $data
  114. *
  115. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  116. */
  117. public function __construct(
  118. Context $context,
  119. Registry $registry,
  120. AttributeCollectionFactory $attributeCollectionFactory,
  121. Visibility $catalogProductVisibility,
  122. Config $catalogConfig,
  123. CurrencyFactory $currencyFactory,
  124. ProductFactory $productFactory,
  125. StoreManagerInterface $storeManager,
  126. ProductCollectionFactory $productCollectionFactory,
  127. AdvancedFactory $advancedFactory,
  128. array $data = []
  129. ) {
  130. $this->_attributeCollectionFactory = $attributeCollectionFactory;
  131. $this->_catalogProductVisibility = $catalogProductVisibility;
  132. $this->_catalogConfig = $catalogConfig;
  133. $this->_currencyFactory = $currencyFactory;
  134. $this->_productFactory = $productFactory;
  135. $this->_storeManager = $storeManager;
  136. $this->productCollectionFactory = $productCollectionFactory;
  137. parent::__construct(
  138. $context,
  139. $registry,
  140. $advancedFactory->create(),
  141. $this->productCollectionFactory->create(),
  142. $data
  143. );
  144. }
  145. /**
  146. * Add advanced search filters to product collection
  147. *
  148. * @param array $values
  149. * @return $this
  150. * @throws LocalizedException
  151. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  152. * @SuppressWarnings(PHPMD.NPathComplexity)
  153. */
  154. public function addFilters($values)
  155. {
  156. $attributes = $this->getAttributes();
  157. $allConditions = [];
  158. foreach ($attributes as $attribute) {
  159. /* @var $attribute Attribute */
  160. if (!isset($values[$attribute->getAttributeCode()])) {
  161. continue;
  162. }
  163. $value = $values[$attribute->getAttributeCode()];
  164. $preparedSearchValue = $this->getPreparedSearchCriteria($attribute, $value);
  165. if (false === $preparedSearchValue) {
  166. continue;
  167. }
  168. $this->addSearchCriteria($attribute, $preparedSearchValue);
  169. if ($attribute->getAttributeCode() == 'price') {
  170. $rate = 1;
  171. $store = $this->_storeManager->getStore();
  172. $currency = $store->getCurrentCurrencyCode();
  173. if ($currency != $store->getBaseCurrencyCode()) {
  174. $rate = $store->getBaseCurrency()->getRate($currency);
  175. }
  176. $value['from'] = (isset($value['from']) && is_numeric($value['from']))
  177. ? (float)$value['from'] / $rate
  178. : '';
  179. $value['to'] = (isset($value['to']) && is_numeric($value['to']))
  180. ? (float)$value['to'] / $rate
  181. : '';
  182. }
  183. if ($attribute->getBackendType() == 'datetime') {
  184. $value['from'] = (isset($value['from']) && !empty($value['from']))
  185. ? date('Y-m-d\TH:i:s\Z', strtotime($value['from']))
  186. : '';
  187. $value['to'] = (isset($value['to']) && !empty($value['to']))
  188. ? date('Y-m-d\TH:i:s\Z', strtotime($value['to']))
  189. : '';
  190. }
  191. $condition = $this->_getResource()->prepareCondition(
  192. $attribute,
  193. $value,
  194. $this->getProductCollection()
  195. );
  196. if ($condition === false) {
  197. continue;
  198. }
  199. $table = $attribute->getBackend()->getTable();
  200. if ($attribute->getBackendType() == 'static') {
  201. $attributeId = $attribute->getAttributeCode();
  202. } else {
  203. $attributeId = $attribute->getId();
  204. }
  205. $allConditions[$table][$attributeId] = $condition;
  206. }
  207. if ($allConditions) {
  208. $this->_registry->register('advanced_search_conditions', $allConditions);
  209. $this->getProductCollection()->addFieldsToFilter($allConditions);
  210. } else {
  211. throw new LocalizedException(__('Please specify at least one search term.'));
  212. }
  213. return $this;
  214. }
  215. /**
  216. * Retrieve array of attributes used in advanced search
  217. *
  218. * @return array|\Magento\Catalog\Model\ResourceModel\Product\Attribute\Collection
  219. */
  220. public function getAttributes()
  221. {
  222. $attributes = $this->getData('attributes');
  223. if ($attributes === null) {
  224. $product = $this->_productFactory->create();
  225. $attributes = $this->_attributeCollectionFactory
  226. ->create()
  227. ->addHasOptionsFilter()
  228. ->addDisplayInAdvancedSearchFilter()
  229. ->addStoreLabel($this->_storeManager->getStore()->getId())
  230. ->setOrder('main_table.attribute_id', 'asc')
  231. ->load();
  232. foreach ($attributes as $attribute) {
  233. $attribute->setEntity($product->getResource());
  234. }
  235. $this->setData('attributes', $attributes);
  236. }
  237. return $attributes;
  238. }
  239. /**
  240. * Retrieve advanced search product collection
  241. *
  242. * @return Collection
  243. */
  244. public function getProductCollection()
  245. {
  246. if ($this->_productCollection === null) {
  247. $collection = $this->productCollectionFactory->create();
  248. $this->prepareProductCollection($collection);
  249. if (!$collection) {
  250. return $collection;
  251. }
  252. $this->_productCollection = $collection;
  253. }
  254. return $this->_productCollection;
  255. }
  256. /**
  257. * Prepare product collection
  258. *
  259. * @param Collection $collection
  260. * @return $this
  261. */
  262. public function prepareProductCollection($collection)
  263. {
  264. $collection
  265. ->addAttributeToSelect($this->_catalogConfig->getProductAttributes())
  266. ->setStore($this->_storeManager->getStore())
  267. ->addMinimalPrice()
  268. ->addTaxPercents()
  269. ->addStoreFilter()
  270. ->setVisibility($this->_catalogProductVisibility->getVisibleInSearchIds());
  271. return $this;
  272. }
  273. /**
  274. * @param EntityAttribute $attribute
  275. * @param mixed $value
  276. * @return void
  277. */
  278. protected function addSearchCriteria($attribute, $value)
  279. {
  280. if (!empty($value)) {
  281. $this->_searchCriterias[] = ['name' => $attribute->getStoreLabel(), 'value' => $value];
  282. }
  283. }
  284. /**
  285. * Add data about search criteria to object state
  286. *
  287. * @todo: Move this code to block
  288. *
  289. * @param EntityAttribute $attribute
  290. * @param mixed $value
  291. * @return string|bool
  292. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  293. * @SuppressWarnings(PHPMD.NPathComplexity)
  294. */
  295. protected function getPreparedSearchCriteria($attribute, $value)
  296. {
  297. if (is_array($value)) {
  298. if (isset($value['from']) && isset($value['to'])) {
  299. if (!empty($value['from']) || !empty($value['to'])) {
  300. if (isset($value['currency'])) {
  301. /** @var $currencyModel Currency */
  302. $currencyModel = $this->_currencyFactory->create()->load($value['currency']);
  303. $from = $currencyModel->format($value['from'], [], false);
  304. $to = $currencyModel->format($value['to'], [], false);
  305. } else {
  306. $currencyModel = null;
  307. }
  308. if (strlen($value['from']) > 0 && strlen($value['to']) > 0) {
  309. // -
  310. $value = sprintf(
  311. '%s - %s',
  312. $currencyModel ? $from : $value['from'],
  313. $currencyModel ? $to : $value['to']
  314. );
  315. } elseif (strlen($value['from']) > 0) {
  316. // and more
  317. $value = __('%1 and greater', $currencyModel ? $from : $value['from']);
  318. } elseif (strlen($value['to']) > 0) {
  319. // to
  320. $value = __('up to %1', $currencyModel ? $to : $value['to']);
  321. }
  322. } else {
  323. return '';
  324. }
  325. }
  326. }
  327. if (($attribute->getFrontendInput() == 'select' ||
  328. $attribute->getFrontendInput() == 'multiselect') && is_array($value)
  329. ) {
  330. foreach ($value as $key => $val) {
  331. $value[$key] = $attribute->getSource()->getOptionText($val);
  332. if (is_array($value[$key])) {
  333. $value[$key] = $value[$key]['label'];
  334. }
  335. }
  336. $value = implode(', ', $value);
  337. } elseif ($attribute->getFrontendInput() == 'select' || $attribute->getFrontendInput() == 'multiselect') {
  338. $value = $attribute->getSource()->getOptionText($value);
  339. if (is_array($value)) {
  340. $value = $value['label'];
  341. }
  342. } elseif ($attribute->getFrontendInput() == 'boolean') {
  343. $value = $value == 1
  344. ? __('Yes')
  345. : __('No');
  346. }
  347. return $value;
  348. }
  349. /**
  350. * Returns prepared search criterias in text
  351. *
  352. * @return array
  353. */
  354. public function getSearchCriterias()
  355. {
  356. return $this->_searchCriterias;
  357. }
  358. }