Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
section.php
1<?php
3
4use Bitrix\Iblock\Copy\Implement\Element as ElementImplementer;
13
14class Section extends Stepper
15{
16 protected static $moduleId = "photogallery";
17
18 protected $queueName = "SectionGroupQueue";
19 protected $checkerName = "SectionGroupChecker_";
20 protected $baseName = "SectionGroupStepper_";
21 protected $errorName = "SectionGroupError_";
22
31 public function execute(array &$option)
32 {
33 if (!Loader::includeModule("iblock") || !Loader::includeModule("photogallery"))
34 {
35 return false;
36 }
37
38 try
39 {
40 $queue = $this->getQueue();
41 $this->setQueue($queue);
42 $queueOption = $this->getQueueOption();
43 if (empty($queueOption))
44 {
45 $this->deleteQueueOption();
46 return !$this->isQueueEmpty();
47 }
48
49 $sectionId = ($queueOption["sectionId"] ?: 0);
50 $copiedSectionId = ($queueOption["copiedSectionId"] ?: 0);
51 $errorOffset = ($queueOption["errorOffset"] ?: 0);
52
53 $limit = 5;
54 $offset = $this->getOffset($copiedSectionId) + $errorOffset;
55
56 $enumRatio = ($queueOption["enumRatio"] ?: []);
57 $sectionsRatio = ($queueOption["sectionsRatio"] ?: []);
58 $mapIdsCopiedElements = ($queueOption["mapIdsCopiedElements"] ?: []);
59
60 if ($sectionId)
61 {
62 list($elementIds, $selectedRowsCount) = $this->getElementIds($sectionId, $limit, $offset);
63
64 $elementCopier = $this->getElementCopier();
65 $containerCollection = $this->getContainerCollection($elementIds, $sectionsRatio, $enumRatio);
66 $result = $elementCopier->copy($containerCollection);
67 if (!$result->isSuccess())
68 {
69 $queueOption["errorOffset"] += $this->getErrorOffset($elementCopier);
70 }
71
72 $mapIdsCopiedElements = $elementCopier->getMapIdsCopiedEntity() + $mapIdsCopiedElements;
73 $queueOption["mapIdsCopiedElements"] = $mapIdsCopiedElements;
74 $this->saveQueueOption($queueOption);
75
76 if ($selectedRowsCount < $limit)
77 {
78 $this->onAfterQueueCopy($queueOption);
79 $this->deleteQueueOption();
80 return !$this->isQueueEmpty();
81 }
82 else
83 {
84 $option["steps"] = $offset;
85 return true;
86 }
87 }
88 else
89 {
90 $this->onAfterQueueCopy($queueOption);
91 $this->deleteQueueOption();
92 return !$this->isQueueEmpty();
93 }
94 }
95 catch (\Exception $exception)
96 {
97 $this->writeToLog($exception);
98 $this->deleteQueueOption();
99 return false;
100 }
101 }
102
103 private function getElementIds(int $sectionId, int $limit, int $offset): array
104 {
105 $elementIds = [];
106
107 $connection = Application::getInstance()->getConnection();
108 $sqlHelper = $connection->getSqlHelper();
109
110 $queryObject = $connection->query("SELECT ID FROM `b_iblock_element` WHERE `IBLOCK_SECTION_ID` = '".
111 $sqlHelper->forSql($sectionId)."' ORDER BY ID ASC LIMIT ".$limit." OFFSET ".$offset);
112 $selectedRowsCount = $queryObject->getSelectedRowsCount();
113 while ($element = $queryObject->fetch())
114 {
115 $elementIds[] = $element["ID"];
116 }
117
118 return [$elementIds, $selectedRowsCount];
119 }
120
121 private function getOffset(int $copiedSectionId): int
122 {
123 $elementIds = [];
124
125 $connection = Application::getInstance()->getConnection();
126 $sqlHelper = $connection->getSqlHelper();
127
128 $queryObject = $connection->query("SELECT ID FROM `b_iblock_element` WHERE `IBLOCK_SECTION_ID` = '".
129 $sqlHelper->forSql($copiedSectionId)."' ORDER BY ID");
130 while ($element = $queryObject->fetch())
131 {
132 $elementIds[] = $element["ID"];
133 }
134
135 return count($elementIds);
136 }
137
138 private function getErrorOffset(EntityCopier $elementCopier): int
139 {
140 $numberIds = count($elementCopier->getMapIdsCopiedEntity());
141 $numberSuccessIds = count(array_filter($elementCopier->getMapIdsCopiedEntity()));
142 return $numberIds - $numberSuccessIds;
143 }
144
145 private function getContainerCollection($elementIds, array $sectionsRatio, array $enumRatio, $targetIblockId = 0)
146 {
147 $containerCollection = new ContainerCollection();
148
149 foreach ($elementIds as $elementId)
150 {
151 $container = new Container($elementId);
152 $dictionary = new Dictionary(
153 [
154 "targetIblockId" => $targetIblockId,
155 "enumRatio" => $enumRatio,
156 "sectionsRatio" => $sectionsRatio
157 ]
158 );
159 $container->setDictionary($dictionary);
160
161 $containerCollection[] = $container;
162 }
163
164 return $containerCollection;
165 }
166
167 private function getElementCopier()
168 {
169 $elementImplementer = new ElementImplementer();
170 return new EntityCopier($elementImplementer);
171 }
172
173 private function onAfterQueueCopy(array $queueOption): void
174 {
175 $copiedSectionId = ($queueOption["copiedSectionId"] ?: 0);
176 if (!$copiedSectionId)
177 {
178 return;
179 }
180
181 $queryObject = \CIBlockSection::getList([], [
182 "ID" => $copiedSectionId, "CHECK_PERMISSIONS" => "N"], false, ["IBLOCK_ID"]);
183 if ($fields = $queryObject->fetch())
184 {
185 $iblockId = $fields["IBLOCK_ID"];
186 if (!$iblockId)
187 {
188 return;
189 }
190
191 $sectionIds = [];
192 $queryObject = \CIBlockSection::getTreeList(["IBLOCK_ID" => $iblockId], ["ID"]);
193 while ($section = $queryObject->fetch())
194 {
195 $sectionIds[] = $section["ID"];
196 }
197
198 PClearComponentCacheEx($iblockId, $sectionIds);
199 }
200 }
201
202 protected function getQueue(): array
203 {
204 return $this->getOptionData($this->queueName);
205 }
206
207 protected function setQueue(array $queue): void
208 {
209 $queueId = (string) current($queue);
210 $this->checkerName = (mb_strpos($this->checkerName, $queueId) === false ?
211 $this->checkerName.$queueId : $this->checkerName);
212 $this->baseName = (mb_strpos($this->baseName, $queueId) === false ?
213 $this->baseName.$queueId : $this->baseName);
214 $this->errorName = (mb_strpos($this->errorName, $queueId) === false ?
215 $this->errorName.$queueId : $this->errorName);
216 }
217
218 protected function getQueueOption()
219 {
220 return $this->getOptionData($this->baseName);
221 }
222
223 protected function saveQueueOption(array $data)
224 {
225 Option::set(static::$moduleId, $this->baseName, serialize($data));
226 }
227
228 protected function deleteQueueOption()
229 {
230 $queue = $this->getQueue();
231 $this->setQueue($queue);
232 $this->deleteCurrentQueue($queue);
233 Option::delete(static::$moduleId, ["name" => $this->checkerName]);
234 Option::delete(static::$moduleId, ["name" => $this->baseName]);
235 }
236
237 protected function deleteCurrentQueue(array $queue): void
238 {
239 $queueId = current($queue);
240 $currentPos = array_search($queueId, $queue);
241 if ($currentPos !== false)
242 {
243 unset($queue[$currentPos]);
244 Option::set(static::$moduleId, $this->queueName, serialize($queue));
245 }
246 }
247
248 protected function isQueueEmpty()
249 {
250 $queue = $this->getOptionData($this->queueName);
251 return empty($queue);
252 }
253
254 protected function getOptionData($optionName)
255 {
256 $option = Option::get(static::$moduleId, $optionName);
257 $option = ($option !== "" ? unserialize($option, ['allowed_classes' => false]) : []);
258 return (is_array($option) ? $option : []);
259 }
260
261 protected function deleteOption($optionName)
262 {
263 Option::delete(static::$moduleId, ["name" => $optionName]);
264 }
265}
writeToLog(\Exception $exception)
Definition stepper.php:406