34 private function loadCurrentStatus()
37 $this->status = Option::get(
'landing', self::OPTION_STATUS_NAME,
'');
38 $this->status = ($this->status !==
'' ? @unserialize($this->status, [
'allowed_classes' =>
false]) : array());
39 $this->status = (is_array($this->status) ? $this->status : array());
42 if (empty($this->status))
47 foreach (Option::getForModule(
'landing') as $key => $option)
49 if (mb_strpos($key, self::OPTION_NAME) === 0 && $key != self::OPTION_STATUS_NAME)
51 $option = ($option !==
'' ? @unserialize($option, [
'allowed_classes' =>
false]) : array());
53 if(!isset($option[
'BLOCKS']))
55 Option::delete(
'landing', array(
'name' => $key));
60 $params[$key] = $option[
'PARAMS'];
63 'CODE' => array_keys($option[
'BLOCKS']),
67 isset($option[
'PARAMS'][
'UPDATE_PUBLISHED_SITES']) &&
68 $option[
'PARAMS'][
'UPDATE_PUBLISHED_SITES'] !=
'Y'
71 $filter[
'PUBLIC'] =
'N';
74 $res = BlockTable::getList(array(
82 if ($row = $res->fetch())
84 $count += $row[
'CNT'];
89 $this->status[
'COUNT'] = $count;
90 $this->status[
'STEPS'] = 0;
91 $this->status[
'SITES_TO_UPDATE'] = array();
92 $this->status[
'UPDATER_ID'] =
'';
93 $this->status[
'PARAMS'] = $params;
95 Option::set(
'landing', self::OPTION_STATUS_NAME, serialize($this->status));
104 private function getUpdaterUniqueId()
107 if ($this->status[
'UPDATER_ID'] !==
'')
109 return $this->status[
'UPDATER_ID'];
112 $updaterOptions = Option::getForModule(
'landing');
113 $allOptions = preg_grep(
'/' . self::OPTION_NAME .
'.+/', array_keys($updaterOptions));
114 $allOptions = array_diff($allOptions, array(self::OPTION_STATUS_NAME));
117 if (!empty($allOptions))
119 return str_replace(self::OPTION_NAME,
'', $allOptions[0]);
131 $this->loadCurrentStatus();
133 if (!$this->status[
'COUNT'])
141 $this->status[
'UPDATER_ID'] = $this->getUpdaterUniqueId();
143 if (!$this->status[
'UPDATER_ID'])
150 $this->processBlocks();
153 if (!is_array($this->dataToUpdate[
'BLOCKS']) || empty($this->dataToUpdate[
'BLOCKS']))
155 $this->finishOption();
158 $result[
'count'] = $this->status[
'COUNT'];
159 $result[
'steps'] = $this->status[
'STEPS'];
168 private static function finish()
170 self::clearOptions();
180 private static function clearOptions()
182 foreach (Option::getForModule(
'landing') as $key => $option)
184 if (mb_strpos($key, self::OPTION_NAME) === 0)
186 Option::delete(
'landing', array(
'name' => $key));
196 private function getOptionName()
198 return self::OPTION_NAME . $this->status[
'UPDATER_ID'];
202 private function collectBlocks()
204 $this->dataToUpdate = Option::get(self::$moduleId, $this->getOptionName());
205 $this->dataToUpdate = ($this->dataToUpdate !==
'' ? @unserialize($this->dataToUpdate, [
'allowed_classes' =>
false]) : array());
206 $this->codesToStep = array_unique(array_keys($this->dataToUpdate[
'BLOCKS']));
207 $this->codesToStep = array_slice($this->codesToStep, 0, self::STEP_PORTION);
211 'CODE' => $this->codesToStep,
215 isset($this->status[
'PARAMS'][$this->getOptionName()][
'UPDATE_PUBLISHED_SITES']) &&
216 $this->status[
'PARAMS'][$this->getOptionName()][
'UPDATE_PUBLISHED_SITES'] !=
'Y'
219 $filter[
'PUBLIC'] =
'N';
222 $resBlock = BlockTable::getList(array(
233 'SITE_ID' =>
'LANDING.SITE_ID',
241 while ($row = $resBlock->fetch())
243 $this->blocksToUpdate[$row[
'CODE']][$row[
'ID']] =
new Block($row[
'ID'], $row);
244 if (count($this->blocksToUpdate) > self::STEP_PORTION)
246 unset($this->blocksToUpdate[$row[
'CODE']]);
251 $this->sitesToUpdate[$row[
'ID']] = $row[
'SITE_ID'];
256 private function processBlocks()
258 $this->collectBlocks();
260 foreach ($this->blocksToUpdate as $code => $blocks)
262 foreach ($blocks as $block)
264 if (is_array($this->dataToUpdate[
'BLOCKS'][$code]) && !empty($this->dataToUpdate[
'BLOCKS'][$code]))
266 $this->updateBlock($block);
270 isset($this->status[
'PARAMS'][$this->getOptionName()][
'UPDATE_PUBLISHED_SITES']) &&
271 $this->status[
'PARAMS'][$this->getOptionName()][
'UPDATE_PUBLISHED_SITES'] ==
'Y'
274 $this->status[
'SITES_TO_UPDATE'][] = $this->sitesToUpdate[$block->getId()];
278 $this->status[
'STEPS']++;
285 private function updateBlock(Block $block)
287 $code = $block->getCode();
288 $doc = $block->getDom();
290 foreach ($this->dataToUpdate[
'BLOCKS'][$code][
'NODES'] as $selector => $rules)
292 $resultList = $doc->querySelectorAll($selector);
295 $nodeAttrs = array();
296 if (is_array($rules[
'ATTRS_ADD']) && !empty($rules[
'ATTRS_ADD']))
298 $nodeAttrs = array_merge($nodeAttrs, $rules[
'ATTRS_ADD']);
300 if (is_array($rules[
'ATTRS_REMOVE']) && !empty($rules[
'ATTRS_REMOVE']))
302 $nodeAttrs = array_merge($nodeAttrs, array_fill_keys(array_values($rules[
'ATTRS_REMOVE']),
''));
306 foreach ($resultList as $nth => $resultNode)
310 if (is_array($rules[
'FILTER']) && !empty($rules[
'FILTER']))
315 isset($rules[
'FILTER'][
'CONTENT']) && is_array($rules[
'FILTER'][
'CONTENT']) &&
317 $rules[
'FILTER'][
'CONTENT'][
'VALUE'] != $resultNode->getInnerHTML() ||
319 $rules[
'FILTER'][
'CONTENT'][
'NOT'] &&
320 $rules[
'FILTER'][
'CONTENT'][
'VALUE'] == $resultNode->getInnerHTML()
330 isset($rules[
'FILTER'][
'NTH']) && is_array($rules[
'FILTER'][
'NTH']) &&
331 isset($rules[
'FILTER'][
'NTH'][
'VALUE']) &&
332 $nth + 1 != $rules[
'FILTER'][
'NTH'][
'VALUE']
345 $classesChange =
false;
346 $nodeClasses = $resultNode->getClassList();
347 if (is_array($rules[
'CLASSES_REMOVE']) && !empty($rules[
'CLASSES_REMOVE']))
349 $nodeClasses = array_diff($nodeClasses, $rules[
'CLASSES_REMOVE']);
350 $classesChange =
true;
353 if (is_array($rules[
'CLASSES_ADD']) && !empty($rules[
'CLASSES_ADD']))
355 $nodeClasses = array_merge($nodeClasses, $rules[
'CLASSES_ADD']);
356 $classesChange =
true;
359 if (is_array($rules[
'CLASSES_REPLACE']) &&
360 array_key_exists(
'PATTERN', $rules[
'CLASSES_REPLACE']) &&
361 array_key_exists(
'REPLACE', $rules[
'CLASSES_REPLACE']))
363 $nodeClassesStr = implode(
' ', $nodeClasses);
364 $nodeClassesReplace = preg_replace(
365 '/' . $rules[
'CLASSES_REPLACE'][
'PATTERN'] .
'/i',
366 $rules[
'CLASSES_REPLACE'][
'REPLACE'],
369 if ($nodeClassesReplace !==
null)
371 $nodeClasses = explode(
' ', $nodeClassesReplace);
372 $classesChange =
true;
377 $nodeClasses = array_unique($nodeClasses);
380 $resultNode->setClassName(implode(
' ', $nodeClasses));
384 if ($rules[
'ID_REMOVE'] && $rules[
'ID_REMOVE'] ==
'Y')
386 $resultNode->removeAttribute(
'id');
390 foreach ($nodeAttrs as $name => $value)
393 $value = str_replace(array(
"\n",
"\t"),
"", $value);
397 $resultNode->setAttribute($name, is_array($value) ? json_encode($value) : $value);
401 $resultNode->removeAttribute($name);
406 if (isset($rules[
'NODE_REMOVE']) && $rules[
'NODE_REMOVE'] ===
true)
408 $resultNode->getParentNode()->removeChild($resultNode);
414 isset($rules[
'REPLACE_CONTENT']) && is_array($rules[
'REPLACE_CONTENT']) &&
415 array_key_exists(
'regexp', $rules[
'REPLACE_CONTENT']) &&
416 array_key_exists(
'replace', $rules[
'REPLACE_CONTENT'])
419 $innerHtml = $resultNode->getInnerHTML();
420 $innerHtml = preg_replace($rules[
'REPLACE_CONTENT'][
'regexp'], $rules[
'REPLACE_CONTENT'][
'replace'], $innerHtml);
423 $resultNode->setInnerHTML($innerHtml);
431 isset($rules[
'CONTAINER_ADD']) && is_array($rules[
'CONTAINER_ADD']) &&
432 isset($rules[
'CONTAINER_ADD'][
'CLASSES']) &&
436 if (!is_array($rules[
'CONTAINER_ADD'][
'CLASSES']))
438 $rules[
'CONTAINER_ADD'][
'CLASSES'] = [$rules[
'CONTAINER_ADD'][
'CLASSES']];
441 $firstNode = $resultList[0];
442 $parentNode = $firstNode->getParentNode();
443 $parentClasses = $parentNode->getClassList();
444 if (!empty(array_diff($rules[
'CONTAINER_ADD'][
'CLASSES'], $parentClasses)))
447 if (!isset($rules[
'CONTAINER_ADD'][
'TO_EACH']) || $rules[
'CONTAINER_ADD'][
'TO_EACH'] !==
true)
449 $containerNode =
new Element($rules[
'CONTAINER_ADD'][
'TAG'] ? $rules[
'CONTAINER_ADD'][
'TAG'] :
'div');
450 $containerNode->setOwnerDocument($doc);
451 $containerNode->setClassName(implode(
' ', $rules[
'CONTAINER_ADD'][
'CLASSES']));
452 $parentNode->insertBefore($containerNode, $firstNode);
453 foreach ($resultList as $resultNode)
455 $parentNode->removeChild($resultNode);
456 $containerNode->appendChild($resultNode);
461 foreach ($resultList as $resultNode)
463 $containerNode =
new Element($rules[
'CONTAINER_ADD'][
'TAG'] ? $rules[
'CONTAINER_ADD'][
'TAG'] :
'div');
464 $containerNode->setOwnerDocument($doc);
465 $containerNode->setClassName(implode(
' ', $rules[
'CONTAINER_ADD'][
'CLASSES']));
466 $parentNode->insertBefore($containerNode, $resultNode);
468 $parentNode->removeChild($resultNode);
469 $containerNode->appendChild($resultNode);
475 $block->saveContent($doc->saveHTML());
478 if (is_array($this->dataToUpdate[
'BLOCKS'][$code][
'UPDATE_COMPONENTS']))
480 foreach ($this->dataToUpdate[
'BLOCKS'][$code][
'UPDATE_COMPONENTS'] as $selector => $params)
482 $block->updateNodes(array($selector => $params));
488 $this->dataToUpdate[
'BLOCKS'][$code][
'CLEAR_PHP'] &&
489 $this->dataToUpdate[
'BLOCKS'][$code][
'CLEAR_PHP'] ==
'Y'
492 $content = $block->getContent();
493 $content = preg_replace(
'/<\?.*\?>/s',
'', $content);
494 $block->saveContent($content);
499 $this->dataToUpdate[
'BLOCKS'][$code][
'SET_SORT'] &&
500 is_numeric($this->dataToUpdate[
'BLOCKS'][$code][
'SET_SORT'])
503 $block->setSort($this->dataToUpdate[
'BLOCKS'][$code][
'SET_SORT']);
510 private function finishStep()
513 foreach ($this->codesToStep as $code)
515 unset($this->dataToUpdate[
'BLOCKS'][$code]);
518 Option::set(
'landing', $this->getOptionName(), serialize($this->dataToUpdate));
519 Option::set(
'landing', self::OPTION_STATUS_NAME, serialize($this->status));
522 private function finishOption()
525 $this->updateSites();
528 Option::delete(
'landing', array(
'name' => $this->getOptionName()));
529 $this->status[
'SITES_TO_UPDATE'] = array();
530 $this->status[
'UPDATER_ID'] =
'';
531 Option::set(
'landing', self::OPTION_STATUS_NAME, serialize($this->status));
535 private function updateSites()
538 isset($this->status[
'PARAMS'][$this->getOptionName()][
'UPDATE_PUBLISHED_SITES']) &&
539 $this->status[
'PARAMS'][$this->getOptionName()][
'UPDATE_PUBLISHED_SITES'] ==
'Y' &&
540 Loader::includeModule(
'bitrix24')
546 foreach (array_unique($this->status[
'SITES_TO_UPDATE']) as $siteId)
564 if (\
Bitrix\
Landing\Update\Stepper::checkAgentActivity(
'\Bitrix\Landing\Update\Block\NodeAttributes'))
566 $result =
new Entity\EventResult();
567 $result->setErrors(array(
570 'BLOCK_DISABLE_DELETE'
589 if (\
Bitrix\
Landing\Update\Stepper::checkAgentActivity(
'\Bitrix\Landing\Update\Block\NodeAttributes'))
591 $result =
new Entity\EventResult;
592 $result->setErrors(array(
595 'LANDING_DISABLE_PUBLICATION'
613 $eventManager = \Bitrix\Main\EventManager::getInstance();
614 $eventManager->unregisterEventHandler(
616 '\Bitrix\Landing\Internals\Block::OnBeforeDelete',
618 '\Bitrix\Landing\Update\Block\NodeAttributes',
619 'disableBlockDelete');
620 $eventManager->unregisterEventHandler(
622 'onLandingPublication',
624 '\Bitrix\Landing\Update\Block\NodeAttributes',
638 "Now using embedded forms, no need domain. You must remove updateFormDomainByConnector() call",
652 "Now using embedded forms, no need domain. You must remove updateFormDomain() call",