PageRenderTime 51ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/landing/lib/copy/integration/groupstepper.php

https://gitlab.com/alexprowars/bitrix
PHP | 364 lines | 315 code | 49 blank | 0 comment | 17 complexity | f1c24c2f278a7dbd04b50e7dff3d23d6 MD5 | raw file
  1. <?php
  2. namespace Bitrix\Landing\Copy\Integration;
  3. use Bitrix\Landing;
  4. use Bitrix\Landing\Folder;
  5. use Bitrix\Landing\Site\Type;
  6. use Bitrix\Main\Config\Option;
  7. use Bitrix\Main\Copy\Container;
  8. use Bitrix\Main\Copy\ContainerCollection;
  9. use Bitrix\Main\Copy\EntityCopier;
  10. use Bitrix\Main\Loader;
  11. use Bitrix\Main\Result;
  12. use Bitrix\Main\Update\Stepper;
  13. class GroupStepper extends Stepper
  14. {
  15. protected static $moduleId = 'landing';
  16. protected $queueName = 'LandingGroupQueue';
  17. protected $checkerName = 'LandingGroupChecker_';
  18. protected $baseName = 'LandingGroupStepper_';
  19. protected $errorName = 'LandingGroupError_';
  20. const LIMIT = 5;
  21. public function execute(array &$option)
  22. {
  23. if (!Loader::includeModule(self::$moduleId))
  24. {
  25. return false;
  26. }
  27. try
  28. {
  29. $queue = $this->getQueue();
  30. $this->setQueue($queue);
  31. $queueOption = $this->getOptionData($this->baseName);
  32. if (empty($queueOption))
  33. {
  34. $this->deleteQueueOption();
  35. return !$this->isQueueEmpty();
  36. }
  37. $executiveUserId = ($queueOption["executiveUserId"] ?: 0);
  38. $siteId = ($queueOption['siteId'] ?: 0);
  39. $copiedSiteId = ($queueOption['copiedSiteId'] ?: 0);
  40. Landing\Rights::setContextUserId($executiveUserId);
  41. Type::setScope(Type::SCOPE_CODE_GROUP);
  42. $copiedPageIds = $this->getPageIdsBySiteId($copiedSiteId);
  43. $offset = count($copiedPageIds);
  44. $pageIdsToCopy = $this->getPageIdsBySiteId($siteId);
  45. $count = count($pageIdsToCopy);
  46. $pageIdsToCopy = array_slice($pageIdsToCopy, $offset, self::LIMIT);
  47. if ($pageIdsToCopy)
  48. {
  49. $pageCopier = $this->getPageCopier($copiedSiteId);
  50. $containerCollection = new ContainerCollection();
  51. foreach ($pageIdsToCopy as $pageId)
  52. {
  53. $container = new Container($pageId);
  54. $containerCollection[] = $container;
  55. }
  56. $result = $pageCopier->copy($containerCollection);
  57. if (!$result->isSuccess())
  58. {
  59. $this->deleteQueueOption();
  60. return !$this->isQueueEmpty();
  61. }
  62. $this->saveCopiedMapIds($pageCopier, $queueOption, $result);
  63. $option['count'] = $count;
  64. $option['steps'] = $offset;
  65. }
  66. else
  67. {
  68. $this->onAfterCopy($queueOption);
  69. $this->deleteQueueOption();
  70. return !$this->isQueueEmpty();
  71. }
  72. return true;
  73. }
  74. catch (\Exception $exception)
  75. {
  76. $this->clearContextUserId();
  77. $this->writeToLog($exception);
  78. $this->deleteQueueOption();
  79. return false;
  80. }
  81. }
  82. private function getPageIdsBySiteId(int $siteId): array
  83. {
  84. $pageIds = [];
  85. $queryObject = Landing\Landing::getList([
  86. 'select' => ['ID'],
  87. 'filter' => ['SITE_ID' => $siteId],
  88. ]);
  89. while ($page = $queryObject->fetch())
  90. {
  91. $pageIds[] = $page['ID'];
  92. }
  93. return $pageIds;
  94. }
  95. private function getPageCopier(int $copiedSiteId): EntityCopier
  96. {
  97. $pageCopyImplementer = new Landing\Copy\Implement\Landing();
  98. $pageCopyImplementer->setTargetSiteId($copiedSiteId);
  99. return new EntityCopier($pageCopyImplementer);
  100. }
  101. private function saveCopiedMapIds(EntityCopier $pageCopier, array $queueOption, Result $result): void
  102. {
  103. $pageMapIds = ($queueOption['pageMapIds'] ?: []);
  104. $blockMapIds = ($queueOption['blockMapIds'] ?: []);
  105. $pageMapIds = $pageCopier->getMapIdsByImplementer(
  106. Landing\Copy\Implement\Landing::class, $result->getData()
  107. ) + $pageMapIds;
  108. $queueOption['pageMapIds'] = $pageMapIds;
  109. $blockMapIds = $pageCopier->getMapIdsByImplementer(
  110. 'LandingBlocks', $result->getData()
  111. ) + $blockMapIds;
  112. $queueOption['blockMapIds'] = $blockMapIds;
  113. $this->saveQueueOption($queueOption);
  114. }
  115. private function onAfterCopy(array $queueOption)
  116. {
  117. $siteId = ($queueOption['siteId'] ?: 0);
  118. $copiedSiteId = ($queueOption['copiedSiteId'] ?: 0);
  119. $pageMapIds = array_filter(($queueOption['pageMapIds'] ?: []));
  120. $folderMapIds = array_filter(($queueOption['folderMapIds'] ?: []));
  121. $folderIndexIds = array_filter(($queueOption['folderIndexIds'] ?: []));
  122. $blockMapIds = array_filter(($queueOption['blockMapIds'] ?: []));
  123. if ($pageMapIds)
  124. {
  125. if ($folderMapIds)
  126. {
  127. $this->updateFolderIds($copiedSiteId, $folderMapIds);
  128. $this->updateFolderIndexes($folderMapIds, $folderIndexIds, $pageMapIds);
  129. }
  130. $this->updateBlockIds($pageMapIds, $blockMapIds);
  131. $this->updateCopiedSite($siteId, $copiedSiteId, $pageMapIds);
  132. }
  133. $this->clearContextUserId();
  134. }
  135. private function clearContextUserId()
  136. {
  137. Landing\Rights::clearContextUserId();
  138. }
  139. private function updateFolderIds(int $siteId, array $folderMapIds): void
  140. {
  141. \Bitrix\Landing\Landing::disableCheckUniqueAddress();
  142. $res = Landing\Landing::getList([
  143. 'select' => [
  144. 'ID', 'FOLDER_ID'
  145. ],
  146. 'filter' => [
  147. 'SITE_ID' => $siteId,
  148. 'FOLDER_ID' => array_keys($folderMapIds)
  149. ]
  150. ]);
  151. while ($row = $res->fetch())
  152. {
  153. if (isset($folderMapIds[$row['FOLDER_ID']]))
  154. {
  155. Landing\Landing::update($row['ID'], [
  156. 'FOLDER_ID' => $folderMapIds[$row['FOLDER_ID']]
  157. ]);
  158. }
  159. }
  160. \Bitrix\Landing\Landing::enableCheckUniqueAddress();
  161. }
  162. private function updateFolderIndexes(array $folderMapIds, array $folderIndexIds, array $pageMapIds): void
  163. {
  164. foreach ($folderMapIds as $oldFolderId => $newFolderId)
  165. {
  166. Folder::update($newFolderId, [
  167. 'INDEX_ID' => $pageMapIds[ $folderIndexIds[$oldFolderId] ] ?? null
  168. ]);
  169. }
  170. }
  171. private function updateBlockIds(array $pageMapIds, array $blockMapIds): void
  172. {
  173. ksort($pageMapIds);
  174. ksort($blockMapIds);
  175. Landing\Landing::setEditMode();
  176. foreach ($pageMapIds as $pageId => $copiedPageId)
  177. {
  178. $pageMapIds['#landing'.$pageId] = '#landing'.$copiedPageId;
  179. unset($pageMapIds[$pageId]);
  180. }
  181. foreach ($blockMapIds as $blockId => $copiedBlockId)
  182. {
  183. $blockMapIds['#block'.$blockId] = '#block'.$copiedBlockId;
  184. unset($blockMapIds[$blockId]);
  185. }
  186. foreach ($pageMapIds as $pageId => $copiedPageId)
  187. {
  188. $copiedLandingInstance = Landing\Landing::createInstance(mb_substr($copiedPageId, 8));
  189. foreach ($copiedLandingInstance->getBlocks() as $copiedBlock)
  190. {
  191. $content = $copiedBlock->getContent();
  192. $content = str_replace(
  193. array_keys($pageMapIds),
  194. array_values($pageMapIds),
  195. $content
  196. );
  197. $content = str_replace(
  198. array_keys($blockMapIds),
  199. array_values($blockMapIds),
  200. $content
  201. );
  202. $copiedBlock->saveContent($content);
  203. $copiedBlock->save();
  204. }
  205. }
  206. }
  207. private function updateCopiedSite(int $siteId, int $copiedSiteId, array $pageMapIds): void
  208. {
  209. $siteData = $this->getSiteData($siteId);
  210. $siteDataForUpdate = $this->getSiteDataForUpdateCopiedSite($siteData, $pageMapIds);
  211. if ($siteData['TPL_ID'])
  212. {
  213. $siteDataForUpdate['TPL_ID'] = $siteData['TPL_ID'];
  214. $this->copyTemplate($siteId, $copiedSiteId, $pageMapIds);
  215. }
  216. if ($siteDataForUpdate)
  217. {
  218. Landing\Site::update($copiedSiteId, $siteDataForUpdate);
  219. }
  220. }
  221. private function getSiteData(int $siteId): array
  222. {
  223. $queryObject = Landing\Site::getList(['filter' => ['ID' => $siteId]]);
  224. return (($siteData = $queryObject->fetch()) ? $siteData : []);
  225. }
  226. private function getSiteDataForUpdateCopiedSite(array $siteData, array $pageMapIds): array
  227. {
  228. $copiedSiteData = [];
  229. $codes = ['LANDING_ID_INDEX', 'LANDING_ID_404', 'LANDING_ID_503'];
  230. foreach ($codes as $code)
  231. {
  232. if ($siteData[$code] && isset($pageMapIds[$siteData[$code]]))
  233. {
  234. $copiedSiteData[$code] = $pageMapIds[$siteData[$code]];
  235. }
  236. }
  237. return $copiedSiteData;
  238. }
  239. private function copyTemplate(int $siteId, int $copiedSiteId, array $pageMapIds): void
  240. {
  241. if (($refs = Landing\TemplateRef::getForSite($siteId)))
  242. {
  243. foreach ($refs as $areaId => $oldId)
  244. {
  245. if (isset($pageMapIds[$oldId]))
  246. {
  247. $refs[$areaId] = $pageMapIds[$oldId];
  248. }
  249. else
  250. {
  251. unset($refs[$areaId]);
  252. }
  253. }
  254. if ($refs)
  255. {
  256. Landing\TemplateRef::setForSite($copiedSiteId, $refs);
  257. }
  258. }
  259. }
  260. protected function getQueue(): array
  261. {
  262. return $this->getOptionData($this->queueName);
  263. }
  264. protected function setQueue(array $queue): void
  265. {
  266. $queueId = (string) current($queue);
  267. $this->checkerName = (mb_strpos($this->checkerName, $queueId) === false ?
  268. $this->checkerName.$queueId : $this->checkerName);
  269. $this->baseName = (mb_strpos($this->baseName, $queueId) === false ?
  270. $this->baseName.$queueId : $this->baseName);
  271. $this->errorName = (mb_strpos($this->errorName, $queueId) === false ?
  272. $this->errorName.$queueId : $this->errorName);
  273. }
  274. protected function getQueueOption()
  275. {
  276. return $this->getOptionData($this->baseName);
  277. }
  278. protected function saveQueueOption(array $data)
  279. {
  280. Option::set(static::$moduleId, $this->baseName, serialize($data));
  281. }
  282. protected function deleteQueueOption()
  283. {
  284. $queue = $this->getQueue();
  285. $this->setQueue($queue);
  286. $this->deleteCurrentQueue($queue);
  287. Option::delete(static::$moduleId, ["name" => $this->checkerName]);
  288. Option::delete(static::$moduleId, ["name" => $this->baseName]);
  289. }
  290. protected function deleteCurrentQueue(array $queue): void
  291. {
  292. $queueId = current($queue);
  293. $currentPos = array_search($queueId, $queue);
  294. if ($currentPos !== false)
  295. {
  296. unset($queue[$currentPos]);
  297. Option::set(static::$moduleId, $this->queueName, serialize($queue));
  298. }
  299. }
  300. protected function isQueueEmpty()
  301. {
  302. $queue = $this->getOptionData($this->queueName);
  303. return empty($queue);
  304. }
  305. protected function getOptionData($optionName)
  306. {
  307. $option = Option::get(static::$moduleId, $optionName);
  308. $option = ($option !== "" ? unserialize($option, ['allowed_classes' => false]) : []);
  309. return (is_array($option) ? $option : []);
  310. }
  311. protected function deleteOption($optionName)
  312. {
  313. Option::delete(static::$moduleId, ["name" => $optionName]);
  314. }
  315. }