Base.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Indexer\Action;
  7. use Magento\Framework\App\ResourceConnection as AppResource;
  8. use Magento\Framework\App\ResourceConnection\SourceProviderInterface;
  9. use Magento\Framework\DB\Adapter\AdapterInterface;
  10. use Magento\Framework\DB\Ddl\Table;
  11. use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
  12. use Magento\Framework\Stdlib\StringUtils as StdString;
  13. use Magento\Framework\Indexer\ActionInterface;
  14. use Magento\Framework\Indexer\FieldsetPool;
  15. use Magento\Framework\Indexer\HandlerPool;
  16. use Magento\Framework\Indexer\IndexStructureInterface;
  17. use Magento\Framework\Indexer\SaveHandlerFactory;
  18. use Magento\Framework\App\ResourceConnection\SourceFactory;
  19. use Magento\Framework\Indexer\HandlerInterface;
  20. /**
  21. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  22. * @SuppressWarnings(PHPMD.TooManyFields)
  23. */
  24. class Base implements ActionInterface
  25. {
  26. /**
  27. * Prefix
  28. */
  29. const PREFIX = 'index_';
  30. /**
  31. * @var FieldsetPool
  32. */
  33. protected $fieldsetPool;
  34. /**
  35. * @var AdapterInterface
  36. * @deprecated 101.0.0
  37. */
  38. protected $connection;
  39. /**
  40. * @var SourceProviderInterface[]
  41. * @deprecated 101.0.0
  42. */
  43. protected $sources;
  44. /**
  45. * @var SourceProviderInterface
  46. */
  47. protected $primarySource;
  48. /**
  49. * @var HandlerInterface[]
  50. * @deprecated 101.0.0
  51. */
  52. protected $handlers;
  53. /**
  54. * @var array
  55. */
  56. protected $data;
  57. /**
  58. * @var array
  59. * @deprecated 101.0.0
  60. */
  61. protected $columnTypesMap = [
  62. 'varchar' => ['type' => Table::TYPE_TEXT, 'size' => 255],
  63. 'mediumtext' => ['type' => Table::TYPE_TEXT, 'size' => 16777216],
  64. 'text' => ['type' => Table::TYPE_TEXT, 'size' => 65536],
  65. ];
  66. /**
  67. * @var array
  68. * @deprecated 101.0.0
  69. */
  70. protected $filterColumns;
  71. /**
  72. * @var array
  73. * @deprecated 101.0.0
  74. */
  75. protected $searchColumns;
  76. /**
  77. * @var SourceFactory
  78. */
  79. protected $sourceFactory;
  80. /**
  81. * @var HandlerPool
  82. */
  83. protected $handlerPool;
  84. /**
  85. * @var SaveHandlerFactory
  86. */
  87. protected $saveHandlerFactory;
  88. /**
  89. * @var String
  90. * @deprecated 101.0.0
  91. */
  92. protected $string;
  93. /**
  94. * @var IndexStructureInterface
  95. */
  96. protected $indexStructure;
  97. /**
  98. * @var array
  99. * @deprecated 101.0.0
  100. */
  101. protected $filterable = [];
  102. /**
  103. * @var array
  104. * @deprecated 101.0.0
  105. */
  106. protected $searchable = [];
  107. /**
  108. * @var IndexerInterface
  109. */
  110. protected $saveHandler;
  111. /**
  112. * @var string
  113. */
  114. protected $tableAlias = 'main_table';
  115. /**
  116. * @param AppResource $resource
  117. * @param SourceFactory $sourceFactory
  118. * @param HandlerPool $handlerPool
  119. * @param SaveHandlerFactory $saveHandlerFactory
  120. * @param FieldsetPool $fieldsetPool
  121. * @param StdString $string
  122. * @param IndexStructureInterface $indexStructure
  123. * @param array $data
  124. */
  125. public function __construct(
  126. AppResource $resource,
  127. SourceFactory $sourceFactory,
  128. HandlerPool $handlerPool,
  129. SaveHandlerFactory $saveHandlerFactory,
  130. FieldsetPool $fieldsetPool,
  131. StdString $string,
  132. IndexStructureInterface $indexStructure,
  133. $data = []
  134. ) {
  135. $this->connection = $resource->getConnection();
  136. $this->fieldsetPool = $fieldsetPool;
  137. $this->data = $data;
  138. $this->sourceFactory = $sourceFactory;
  139. $this->handlerPool = $handlerPool;
  140. $this->saveHandlerFactory = $saveHandlerFactory;
  141. $this->string = $string;
  142. $this->indexStructure = $indexStructure;
  143. }
  144. /**
  145. * Execute
  146. *
  147. * @param null|int|array $ids
  148. * @return void
  149. */
  150. protected function execute(array $ids = [])
  151. {
  152. $this->prepareFields();
  153. if (!count($ids)) {
  154. $this->getSaveHandler()->cleanIndex([]);
  155. }
  156. $this->getSaveHandler()->deleteIndex([], new \ArrayObject($ids));
  157. $this->getSaveHandler()->saveIndex([], $this->prepareDataSource($ids));
  158. }
  159. /**
  160. * Execute full indexation
  161. *
  162. * @return void
  163. */
  164. public function executeFull()
  165. {
  166. $this->execute();
  167. }
  168. /**
  169. * Execute partial indexation by ID list
  170. *
  171. * @param int[] $ids
  172. * @return void
  173. */
  174. public function executeList(array $ids)
  175. {
  176. $this->execute($ids);
  177. }
  178. /**
  179. * Execute partial indexation by ID
  180. *
  181. * @param int $id
  182. * @return void
  183. */
  184. public function executeRow($id)
  185. {
  186. $this->execute([$id]);
  187. }
  188. /**
  189. * Prepare select query
  190. *
  191. * @param array|int|null $ids
  192. * @return SourceProviderInterface
  193. */
  194. protected function prepareDataSource(array $ids = [])
  195. {
  196. return !count($ids)
  197. ? $this->createResultCollection()
  198. : $this->createResultCollection()->addFieldToFilter($this->getPrimaryResource()->getIdFieldName(), $ids);
  199. }
  200. /**
  201. * Return index table name
  202. *
  203. * @return string
  204. */
  205. protected function getTableName()
  206. {
  207. return self::PREFIX . $this->getPrimaryResource()->getMainTable();
  208. }
  209. /**
  210. * Return save handler
  211. *
  212. * @return IndexerInterface
  213. */
  214. protected function getSaveHandler()
  215. {
  216. if ($this->saveHandler === null) {
  217. $this->saveHandler = $this->saveHandlerFactory->create(
  218. $this->data['saveHandler'],
  219. [
  220. 'indexStructure' => $this->indexStructure,
  221. 'data' => $this->data,
  222. ]
  223. );
  224. }
  225. return $this->saveHandler;
  226. }
  227. /**
  228. * Return primary source provider
  229. *
  230. * @return SourceProviderInterface
  231. */
  232. protected function getPrimaryResource()
  233. {
  234. return $this->getPrimaryFieldset()['source'];
  235. }
  236. /**
  237. * Return primary fieldset
  238. *
  239. * @return []
  240. */
  241. protected function getPrimaryFieldset()
  242. {
  243. return $this->data['fieldsets'][0];
  244. }
  245. /**
  246. * Create select from indexer configuration
  247. *
  248. * @return SourceProviderInterface
  249. */
  250. protected function createResultCollection()
  251. {
  252. $select = $this->getPrimaryResource()->getSelect();
  253. $select->reset(\Magento\Framework\DB\Select::COLUMNS);
  254. $select->columns($this->getPrimaryResource()->getIdFieldName());
  255. foreach ($this->data['fieldsets'] as $fieldset) {
  256. if (isset($fieldset['references'])) {
  257. foreach ($fieldset['references'] as $reference) {
  258. $source = $fieldset['source'];
  259. /** @var SourceProviderInterface $source */
  260. $currentEntityName = $source->getMainTable();
  261. $alias = $this->getPrimaryFieldset()['name'] == $reference['fieldset']
  262. ? $this->tableAlias
  263. : $reference['fieldset'];
  264. $select->joinLeft(
  265. [$fieldset['name'] => $currentEntityName],
  266. new \Zend_Db_Expr(
  267. $fieldset['name'] . '.' . $reference['from'] . '=' . $alias . '.' . $reference['to']
  268. ),
  269. null
  270. );
  271. }
  272. }
  273. foreach ($fieldset['fields'] as $field) {
  274. $handler = $field['handler'];
  275. /** @var HandlerInterface $handler */
  276. $handler->prepareSql(
  277. $this->getPrimaryResource(),
  278. $this->getPrimaryFieldset()['name'] == $fieldset['name'] ? $this->tableAlias : $fieldset['name'],
  279. $field
  280. );
  281. }
  282. }
  283. return $this->getPrimaryResource();
  284. }
  285. /**
  286. * Prepare configuration data
  287. *
  288. * @return void
  289. */
  290. protected function prepareFields()
  291. {
  292. foreach ($this->data['fieldsets'] as $fieldsetName => $fieldset) {
  293. $this->data['fieldsets'][$fieldsetName]['source'] = $this->sourceFactory->create($fieldset['source']);
  294. if (isset($fieldset['provider'])) {
  295. $fieldsetObject = $this->fieldsetPool->get($fieldset['provider']);
  296. $this->data['fieldsets'][$fieldsetName] =
  297. $fieldsetObject->addDynamicData($this->data['fieldsets'][$fieldsetName]);
  298. }
  299. foreach ($this->data['fieldsets'][$fieldsetName]['fields'] as $fieldName => $field) {
  300. $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['origin'] =
  301. $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['origin']
  302. ?: $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['name'];
  303. if ($fieldsetName != 0) {
  304. $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['name'] =
  305. $this->data['fieldsets'][$fieldsetName]['name'] . '_'
  306. . $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['name'];
  307. }
  308. $this->saveFieldByType($field);
  309. $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['handler'] =
  310. $this->handlerPool->get($field['handler']);
  311. $this->data['fieldsets'][$fieldsetName]['fields'][$fieldName]['dataType'] =
  312. isset($field['dataType']) ? $field['dataType'] : 'varchar';
  313. }
  314. }
  315. }
  316. /**
  317. * Save field by type
  318. *
  319. * @param array $field
  320. * @return void
  321. *
  322. * @deprecated 101.0.0
  323. */
  324. protected function saveFieldByType($field)
  325. {
  326. switch ($field['type']) {
  327. case 'filterable':
  328. $this->filterable[] = $field;
  329. break;
  330. case 'searchable':
  331. $this->searchable[] = $field;
  332. break;
  333. }
  334. }
  335. }