Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
landing.php
1<?php
3
6use \Bitrix\Landing\Landing as LandingCore;
8use \Bitrix\Landing\Site as SiteCore;
10use \Bitrix\Landing\Transfer\AppConfiguration;
11use \Bitrix\Landing\File;
12use \Bitrix\Landing\Folder;
13use \Bitrix\Landing\Hook;
14use \Bitrix\Landing\Repo;
15use \Bitrix\Landing\Block;
16use \Bitrix\Landing\Node;
17use \Bitrix\Main\Event;
19use \Bitrix\Rest\AppTable;
20use \Bitrix\Rest\Configuration;
21use \Bitrix\Crm;
22
27{
32 protected static $forceAppendRestBlocks = true;
33
39 public static function setForceAppendRestBlocks(bool $mode): void
40 {
41 self::$forceAppendRestBlocks = $mode;
42 }
43
50 public static function getRepoId(string $appCode, string $xmlId): ?int
51 {
52 static $items = null;
53
54 if ($items === null)
55 {
56 $items = [];
57 $res = Repo::getList([
58 'select' => [
59 'ID', 'APP_CODE', 'XML_ID'
60 ]
61 ]);
62 while ($row = $res->fetch())
63 {
64 $items[$row['APP_CODE'] . '@' . $row['XML_ID']] = $row['ID'];
65 }
66 }
67
68 if (isset($items[$appCode . '@' . $xmlId]))
69 {
70 return $items[$appCode . '@' . $xmlId];
71 }
72
73 return null;
74 }
75
84 protected static function addFilesToBlock(Block $block, array $data, Configuration\Structure $structure, bool $ignoreManifest = false): array
85 {
86 if (!$ignoreManifest)
87 {
88 $manifest = $block->getManifest();
89 }
90
91 foreach ($data as $selector => &$nodes)
92 {
93 if (!$ignoreManifest)
94 {
95 if (!isset($manifest['nodes'][$selector]))
96 {
97 continue;
98 }
99 if (
100 $manifest['nodes'][$selector]['type'] !== Node\Type::IMAGE
101 && $manifest['nodes'][$selector]['type'] !== Node\Type::STYLE_IMAGE
102 )
103 {
104 continue;
105 }
106 }
107 foreach ($nodes as &$node)
108 {
109 foreach (['', '2x'] as $x)
110 {
111 if (isset($node['id' . $x]))
112 {
113 $unpackedFile = $structure->getUnpackFile($node['id' . $x]);
114 if ($unpackedFile)
115 {
116 $newFileId = AppConfiguration::saveFile($unpackedFile);
117 if ($newFileId)
118 {
119 $newFilePath = File::getFilePath($newFileId);
120 if ($newFilePath)
121 {
122 File::addToBlock($block->getId(), $newFileId);
123 $node['id' . $x] = $newFileId;
124 $node['src' . $x] = $newFilePath;
125 }
126 }
127 }
128 }
129 }
130 }
131 unset($node);
132 }
133 unset($nodes);
134
135 return $data;
136 }
137
143 public static function saveDataToBlock(Block $blockInstance, array $block): void
144 {
145 // update cards
146 if (isset($block['cards']) && is_array($block['cards']))
147 {
148 $blockInstance->updateCards(
149 $block['cards']
150 );
151 }
152 // update style
153 if (isset($block['style']) && is_array($block['style']))
154 {
155 foreach ($block['style'] as $selector => $styleData)
156 {
157 if ($selector === '#wrapper')
158 {
159 $selector = '#' . $blockInstance->getAnchor($blockInstance->getId());
160 }
161 $styleToSet = [];
162 // compatibility for old style export
163 if (!isset($styleData['classList']) && !isset($styleData['style']))
164 {
165 foreach ((array)$styleData as $clPos => $clVal)
166 {
167 // todo: check compatibility
168 $selectorUpd = $selector . '@' . $clPos;
169 $styleToSet[$selectorUpd]['classList'] = (array)$clVal;
170 }
171 }
172
173 // new style export format (classList + style)
174 if (isset($styleData['classList']))
175 {
176 foreach ($styleData['classList'] as $clPos => $class)
177 {
178 if ($class)
179 {
180 $selectorUpd = $selector . '@' . $clPos;
181 $styleToSet[$selectorUpd]['classList'] = explode(' ', $class);
182 }
183 }
184 }
185 if (isset($styleData['style']))
186 {
187 foreach ($styleData['style'] as $stPos => $styles)
188 {
189 if (!empty($styles))
190 {
191 $selectorUpd = $selector . '@' . $stPos;
192 $styleToSet[$selectorUpd]['style'] = $styles;
193 }
194 }
195 }
196
197 if (!empty($styleToSet))
198 {
199 $blockInstance->setClasses($styleToSet);
200 }
201 }
202 }
203 // update nodes
204 if (isset($block['nodes']) && is_array($block['nodes']))
205 {
206 $blockInstance->updateNodes($block['nodes']);
207 }
208 // update menu
209 if (isset($block['menu']) && !empty($block['menu']))
210 {
211 $blockInstance->updateNodes($block['menu']);
212 }
213 // update attrs
214 if (isset($block['attrs']) && !empty($block['attrs']))
215 {
216 if (isset($block['attrs']['#wrapper']))
217 {
218 $attrCode = '#' . $blockInstance->getAnchor($blockInstance->getId());
219 $block['attrs'][$attrCode] = $block['attrs']['#wrapper'];
220 unset($block['attrs']['#wrapper']);
221 }
222 $blockInstance->setAttributes($block['attrs']);
223 }
224 // update dynamic source
225 if (isset($block['dynamic']) && is_array($block['dynamic']))
226 {
227 $blockInstance->saveDynamicParams($block['dynamic']);
228 }
229 }
230
239 protected static function importBlock(LandingCore $landing, array $block, Configuration\Structure $structure, bool &$pending = false): int
240 {
241 static $sort = 0;
242 static $appChecked = [];
243
244 $blockId = 0;
245
246 // if this is a REST block
247 if (
248 isset($block['repo_block']['app_code']) &&
249 isset($block['repo_block']['xml_id']) &&
250 is_string($block['repo_block']['app_code']) &&
251 is_string($block['repo_block']['xml_id'])
252 )
253 {
254 unset($block['code']);
255
256 $repoId = self::getRepoId(
257 $block['repo_block']['app_code'],
258 $block['repo_block']['xml_id']
259 );
260 if ($repoId)
261 {
262 $block['code'] = 'repo_' . $repoId;
263 }
264
265 // force append REST blocks
266 if (
267 !isset($block['code']) &&
268 !empty($block['repo_info']) &&
269 self::$forceAppendRestBlocks
270 )
271 {
272 $appCode = $block['repo_block']['app_code'];
273 if (!array_key_exists($appCode, $appChecked))
274 {
275 $appChecked[$appCode] = \Bitrix\Landing\Repo::getAppByCode($appCode);
276 }
277
278 if ($appChecked[$appCode])
279 {
280 $repoInfo = $block['repo_info'];
281 $res = Repo::add([
282 'APP_CODE' => $block['repo_block']['app_code'],
283 'XML_ID' => $block['repo_block']['xml_id'],
284 'NAME' => $repoInfo['NAME'] ?? null,
285 'DESCRIPTION' => $repoInfo['DESCRIPTION'] ?? null,
286 'SECTIONS' => $repoInfo['SECTIONS'] ?? null,
287 'PREVIEW' => $repoInfo['PREVIEW'] ?? null,
288 'MANIFEST' => serialize(unserialize($repoInfo['MANIFEST'] ?? '', ['allowed_classes' => false])),
289 'CONTENT' => $repoInfo['CONTENT'] ?? null
290 ]);
291 if ($res->isSuccess())
292 {
293 $block['code'] = 'repo_' . $res->getId();
294 }
295 }
296 }
297
298 if (!isset($block['code']))
299 {
300 $pending = true;
301 $blockId = $landing->addBlock(
302 AppConfiguration::SYSTEM_BLOCK_REST_PENDING,
303 [
304 'PUBLIC' => 'N',
305 'SORT' => $sort,
306 'ANCHOR' => $block['anchor'] ?? '',
307 'INITIATOR_APP_CODE' => $block['repo_block']['app_code'] ?? null
308 ]
309 );
310 if ($blockId)
311 {
312 $sort += 500;
313 $blockInstance = $landing->getBlockById($blockId);
314 if ($blockInstance)
315 {
316 if (isset($block['nodes']) && is_array($block['nodes']))
317 {
318 $block['nodes'] = self::addFilesToBlock(
319 $blockInstance,
320 $block['nodes'],
321 $structure,
322 true
323 );
324 }
325 $blockInstance->updateNodes([
326 AppConfiguration::SYSTEM_COMPONENT_REST_PENDING => [
327 'BLOCK_ID' => $blockId,
328 'DATA' => base64_encode(serialize($block)),
329 ],
330 ]);
331 $blockInstance->save();
332 }
333 }
334 return $blockId;
335 }
336 }
337
338 if (!isset($block['code']))
339 {
340 return $blockId;
341 }
342
343 // add block to the landing
344 $blockFields = [
345 'PUBLIC' => 'N',
346 'SORT' => $sort,
347 'ANCHOR' => $block['anchor'] ?? '',
348 'INITIATOR_APP_CODE' => $block['repo_block']['app_code'] ?? null
349 ];
350 if ($block['full_content'] ?? null)
351 {
352 $blockFields['CONTENT'] = str_replace(
353 ['<?', '?>'],
354 ['< ?', '? >'],
355 $block['full_content']
356 );
357 }
358 if ($block['designed'] ?? null)
359 {
360 $blockFields['DESIGNED'] = 'Y';
361 }
362 $blockId = $landing->addBlock(
363 $block['code'],
364 $blockFields
365 );
366 if ($blockId)
367 {
368 $sort += 500;
369 $blockInstance = $landing->getBlockById($blockId);
370 if (isset($block['nodes']) && is_array($block['nodes']))
371 {
372 $block['nodes'] = self::addFilesToBlock(
373 $blockInstance,
374 $block['nodes'],
375 $structure
376 );
377 }
378 if ($block['meta']['FAVORITE_META'] ?? [])
379 {
380 $favoriteMeta = $block['meta']['FAVORITE_META'];
381 if ($block['repo_block']['app_code'] ?? null)
382 {
383 $favoriteMeta['tpl_code'] = $block['repo_block']['app_code'];
384 }
385 if (intval($favoriteMeta['preview'] ?? 0) > 0)
386 {
387 $unpackFile = $structure->getUnpackFile($favoriteMeta['preview']);
388 if ($unpackFile)
389 {
390 $favoriteMeta['preview'] = AppConfiguration::saveFile($unpackFile);
391 File::addToBlock($blockInstance->getId(), $favoriteMeta['preview']);
392 }
393 if (!$favoriteMeta['preview'])
394 {
395 unset($favoriteMeta['preview']);
396 }
397 }
398 $blockInstance->changeFavoriteMeta($favoriteMeta);
399 \Bitrix\Landing\Block::clearRepositoryCache();
400 }
401 if ($blockFields['CONTENT'] ?? null)
402 {
403 $blockInstance->saveContent($blockFields['CONTENT'], $block['designed'] ?? false);
404 }
405 self::saveDataToBlock($blockInstance, $block);
406 $blockInstance->save();
407 // if block is favorite
408 if (intval($block['meta']['LID'] ?? -1) === 0)
409 {
410 $blockInstance->changeLanding(0);
411 }
412 }
413
414 return $blockId;
415 }
416
422 public static function importLanding(Event $event): ?array
423 {
424 $code = $event->getParameter('CODE');
425 $content = $event->getParameter('CONTENT');
426 $ratio = $event->getParameter('RATIO');
427 $contextUser = $event->getParameter('CONTEXT_USER');
428 $additional = $event->getParameter('ADDITIONAL_OPTION');
429 $appId = $event->getParameter('APP_ID');
430 $structure = new Configuration\Structure($contextUser);
431 $return = [
432 'RATIO' => $ratio[$code] ?? [],
433 'ERROR_MESSAGES' => []
434 ];
435
436 if (!isset($content['~DATA']))
437 {
438 return null;
439 }
440
441 if (isset($return['RATIO']['TYPE']))
442 {
443 SiteCore\Type::setScope(
444 $return['RATIO']['TYPE']
445 );
446 }
447
448 if (!self::isNeedImport($event))
449 {
450 return $return;
451 }
452
453 $data = $content['~DATA'];
454 $oldId = $data['ID'] ?? null;
455
456 if (isset($ratio[$code]['SITE_ID']) && (int)$ratio[$code]['SITE_ID'] > 0)
457 {
458 $data['SITE_ID'] = (int)$ratio[$code]['SITE_ID'];
459 }
460 elseif ($additional && (int)$additional['siteId'] > 0)
461 {
462 $data['SITE_ID'] = (int)$additional['siteId'];
463 $return['RATIO']['SITE_ID'] = (int)$additional['siteId'];
464 }
465
466 if (($additional['siteId'] ?? 0) > 0)
467 {
468 LandingCore::enableCheckUniqueAddress();
469 }
470
471 $data = self::prepareData($data);
472 $data = self::prepareAdditionalFiles($data, $structure);
473
474 // folders' old format
475 $convertFolderOldFormat = false;
476 $return['RATIO']['FOLDERS_REF'] = $return['RATIO']['FOLDERS_REF'] ?? [];
477 if ($data['FOLDER'] === 'Y')
478 {
479 $convertFolderOldFormat = true;
480 $data['FOLDER'] = 'N';
481 $res = SiteCore::addFolder($ratio[$code]['SITE_ID'], [
482 'TITLE' => $data['TITLE'],
483 'CODE' => $data['CODE']
484 ]);
485 if ($res->isSuccess())
486 {
487 $data['FOLDER_ID'] = $res->getId();
488 $return['RATIO']['FOLDERS_REF'][$oldId] = $data['FOLDER_ID'];
489 }
490 }
491 elseif ($additional && $additional['folderId'])
492 {
493 $data['FOLDER_ID'] = (int)$additional['folderId'];
494 }
495
496 // set external partners info
497 $appCode = null;
498 if ($appId)
499 {
500 $app = AppTable::getById($appId)->fetch();
501 $appCode = $app['CODE'] ?? null;
502 if ($appCode)
503 {
504 $data['XML_ID'] = $data['TITLE'] . '|' . $appCode;
505 $data['PREVIOUS_TPL_CODE'] = $data['TPL_CODE'];
506 $data['TPL_CODE'] = $appCode;
507 }
508 }
509
510 // base adding
511 $data['ACTIVE'] = 'N';
512 $data['PUBLIC'] = 'N';
513 $data['FOLDER_SKIP_CHECK'] = 'Y';
514 $data['INITIATOR_APP_CODE'] = $appCode;
515 unset($data['CODE']);
516 if ($additional)
517 {
518 $data = self::prepareAdditionalFields($data, $additional, $ratio);
519 }
520 $res = LandingCore::add($data);
521 if ($res->isSuccess())
522 {
523 if ($convertFolderOldFormat && ($data['FOLDER_ID'] ?? 0))
524 {
525 Folder::update($data['FOLDER_ID'], ['INDEX_ID' => $res->getId()]);
526 }
527
528 if (isset($data['BLOCKS']) && is_array($data['BLOCKS']))
529 {
530 $data = self::prepareBlocksData($data, $event);
531 }
532
533 self::saveAdditionalFilesToLanding($data, $res->getId());
534
535 $landing = LandingCore::createInstance($res->getId());
536 // store old id and other references
537 if ($oldId)
538 {
539 $return['RATIO']['LANDINGS'][$oldId] = $res->getId();
540 }
541 if (isset($data['TPL_ID']) && $data['TPL_ID'])
542 {
543 $return['RATIO']['TEMPLATE_LINKING'][$res->getId()] = [
544 'TPL_ID' => (int) $data['TPL_ID'],
545 'TEMPLATE_REF' => isset($data['TEMPLATE_REF'])
546 ? (array) $data['TEMPLATE_REF']
547 : []
548 ];
549 }
550 if (isset($data['BLOCKS']) && is_array($data['BLOCKS']))
551 {
552 foreach ($data['BLOCKS'] as $oldBlockId => $blockItem)
553 {
554 if (is_array($blockItem))
555 {
556 $pending = false;
557 $newBlockId = self::importBlock(
558 $landing,
559 $blockItem,
560 $structure,
561 $pending
562 );
563 $return['RATIO']['BLOCKS'][$oldBlockId] = $newBlockId;
564 if ($pending)
565 {
566 $return['RATIO']['BLOCKS_PENDING'][] = $newBlockId;
567 }
568 }
569 }
570 }
571 }
572 else
573 {
574 $return['ERROR_MESSAGES'] = $res->getErrorMessages();
575 }
576
577 return $return;
578 }
579
585 public static function replaceLanding(Event $event): ?array
586 {
587 $code = $event->getParameter('CODE');
588 $content = $event->getParameter('CONTENT');
589 $ratio = $event->getParameter('RATIO');
590 $contextUser = $event->getParameter('CONTEXT_USER');
591 $additional = $event->getParameter('ADDITIONAL_OPTION');
592 $structure = new Configuration\Structure($contextUser);
593
594 if (!isset($content['~DATA']))
595 {
596 return null;
597 }
598
599 $return = [
600 'RATIO' => $ratio[$code] ?? [],
601 'ERROR_MESSAGES' => []
602 ];
603
604 $replaceLid = (int)$additional['replaceLid'];
605 if ($replaceLid <= 0)
606 {
607 $return['ERROR_MESSAGES'] = 'Not set landing ID for replace';
608
609 return $return;
610 }
611
612 if (isset($return['RATIO']['TYPE']))
613 {
614 SiteCore\Type::setScope($return['RATIO']['TYPE']);
615 }
616 LandingCore::setEditMode();
617 $landing = LandingCore::createInstance($replaceLid);
618 if (!$landing->exist())
619 {
620 $return['ERROR_MESSAGES'] = 'Raplaced landing is not exists';
621
622 return $return;
623 }
624
625 // no landing imported
626 $return['RATIO']['LANDINGS'][$replaceLid] = $replaceLid;
627
628 if (!self::isNeedImport($event))
629 {
630 return $return;
631 }
632
633 $data = $content['~DATA'];
634 $data = self::prepareData($data);
635
636 $additionalFieldsBefore = self::getAdditionalFieldsForReplaceByLanding($replaceLid);
637 if (is_array($ratio[$code]['ADDITIONAL_FIELDS_SITE']) && !empty($ratio[$code]['ADDITIONAL_FIELDS_SITE']))
638 {
639 $data = self::mergeAdditionalFieldsForReplace($data, $ratio[$code]['ADDITIONAL_FIELDS_SITE']);
640 $data = self::prepareAdditionalFiles($data, $structure);
641 self::saveAdditionalFieldsToLanding($data, $replaceLid);
642 self::saveAdditionalFilesToLanding($data, $replaceLid);
643 }
644
645 if (isset($data['BLOCKS']) && is_array($data['BLOCKS']))
646 {
647 $data = self::prepareBlocksData($data, $event);
648 $blocksBefore = [];
649 $blocksAfter = [];
650
652 foreach ($landing->getBlocks() as $block)
653 {
654 $blockId = $block->getId();
655 $block->setAccess(Block::ACCESS_X);
656 if ($landing->markDeletedBlock($block->getId(), true))
657 {
658 $blocksBefore[] = $blockId;
659 }
660 }
661
662 foreach ($data['BLOCKS'] as $oldBlockId => $block)
663 {
664 if (is_array($block) && !empty($block))
665 {
666 $pending = false;
667 $newBlockId = self::importBlock(
668 $landing,
669 $block,
670 $structure,
671 $pending
672 );
673 $blocksAfter[] = $newBlockId;
674 $return['RATIO']['BLOCKS'][$oldBlockId] = $newBlockId;
675 if ($pending)
676 {
677 $return['RATIO']['BLOCKS_PENDING'][] = $newBlockId;
678 }
679 }
680 }
681
682 // find form block and replace form ID if need
683 $meta = $landing->getMeta();
684 if ($meta['SITE_SPECIAL'] === 'Y')
685 {
686 $specialType = SiteCore\Type::getSiteTypeForms($meta['SITE_CODE']);
687 }
688 if (
689 isset($specialType)
690 && $specialType === 'crm_forms'
691 && Loader::includeModule('crm')
692 )
693 {
694 // find form
695 $res = Crm\WebForm\Internals\LandingTable::getList([
696 'select' => [
697 'FORM_ID'
698 ],
699 'filter' => [
700 '=LANDING_ID' => $replaceLid
701 ]
702 ]);
703 $row = $res->fetch();
704 $formId = $row ? $row['FORM_ID'] : null;
705 if ($formId)
706 {
707 foreach ($landing->getBlocks() as $block)
708 {
709 $manifest = $block->getManifest();
710 if (($manifest['block']['subtype'] ?? null) === 'form')
711 {
712 Form::setFormIdToBlock($block->getId(), $formId);
713 if ($block->getAccess() > Block::ACCESS_W)
714 {
715 BlockTable::update($block->getId(), [
716 'ACCESS' => Block::ACCESS_W
717 ]);
718 }
719 }
720 }
721 }
722 }
723
725 {
726 $landing->publication();
727 }
728
730 $history = new History($replaceLid, History::ENTITY_TYPE_LANDING);
731 $history->push('REPLACE_LANDING', [
732 'lid' => $replaceLid,
733 'template' => $code,
734 'blocksBefore' => $blocksBefore,
735 'blocksAfter' => $blocksAfter,
736 'additionalFieldsBefore' => $additionalFieldsBefore,
737 'additionalFieldsAfter' => $data['ADDITIONAL_FIELDS'],
738 ]);
739 }
740
741 return $return;
742 }
743
749 protected static function isNeedImport(Event $event): bool
750 {
751 $code = $event->getParameter('CODE');
752 $content = $event->getParameter('CONTENT');
753 $ratio = $event->getParameter('RATIO');
754
755 if (
756 $ratio[$code]['IS_PAGE_IMPORT']
757 && isset($ratio[$code]['SPECIAL_PAGES']['LANDING_ID_INDEX'])
758 && (int)$content['DATA']['ID'] !== $ratio[$code]['SPECIAL_PAGES']['LANDING_ID_INDEX']
759 )
760 {
761 return false;
762 }
763
764 return true;
765 }
766
767 protected static function prepareData(array $data): array
768 {
769 // clear old keys
770 $notAllowedKeys = [
771 'ID', 'VIEWS', 'DATE_CREATE', 'DATE_MODIFY',
772 'DATE_PUBLIC', 'CREATED_BY_ID', 'MODIFIED_BY_ID'
773 ];
774 foreach ($notAllowedKeys as $key)
775 {
776 if (isset($data[$key]))
777 {
778 unset($data[$key]);
779 }
780 }
781
782 return $data;
783 }
784
785 protected static function prepareBlocksData(array $data, Event $event): array
786 {
787 // @fix wrapper classes from original
788 $appCode = $data['INITIATOR_APP_CODE'];
789 $newTplCode = $data['PREVIOUS_TPL_CODE'] ?? $data['TPL_CODE'];
790 $delobotAppCode = 'local.5eea949386cd05.00160385';
791 $kraytAppCode = 'local.5f11a19f813b13.97126836';
792 $bitrixAppCode = 'bitrix.';
793 if (
794 strpos($newTplCode, $delobotAppCode) !== false
795 || strpos($newTplCode, $kraytAppCode) !== false
796 || strpos($appCode, $bitrixAppCode) === 0
797 )
798 {
799 $wrapperClasses = [];
800 $http = new \Bitrix\Main\Web\HttpClient;
801 $resPreview = $http->get('https://preview.bitrix24.site/tools/blocks.php?tplCode=' . $newTplCode);
802 if ($resPreview)
803 {
804 try
805 {
806 $wrapperClasses = \Bitrix\Main\Web\Json::decode($resPreview);
807 }
808 catch (\Exception $e){}
809 }
810
811 if ($wrapperClasses)
812 {
813 $i = 0;
814 foreach ($data['BLOCKS'] as &$blockData)
815 {
816 if (isset($wrapperClasses[$i]) && $wrapperClasses[$i]['code'] === $blockData['code'])
817 {
818 $blockData['style']['#wrapper'] = ['classList' => [$wrapperClasses[$i]['classList']]];
819 }
820 $i++;
821 }
822 unset($blockData);
823 }
824 }
825 unset($delobotAppCode, $kraytAppCode);
826
827 //fix, delete copyright block
828 $content = $event->getParameter('CONTENT');
829 $templateDateCreate = strtotime($content['DATA']['DATE_CREATE']);
830 $lastDate = strtotime('17.02.2022 00:00:00');
831 if ($templateDateCreate < $lastDate)
832 {
833 $kraytCode = 'bitrix.krayt';
834 $delobotCode = 'bitrix.delobot';
835 if (strpos($appCode, $kraytCode) !== false || strpos($appCode, $delobotCode) !== false)
836 {
837 if (array_slice($data['BLOCKS'], -1)[0]['code'] === '17.copyright')
838 {
839 array_pop($data['BLOCKS']);
840 }
841 }
842 unset($kraytCode, $delobotCode);
843 }
844
845 foreach ($data['BLOCKS'] as &$block)
846 {
847 //fix contact data
848 if (isset($block['nodes']) && strpos($appCode, $bitrixAppCode) === 0)
849 {
850 foreach ($block['nodes'] as &$node)
851 {
852 $countNodeItem = 0;
853 foreach ($node as &$nodeItem)
854 {
855 if (isset($nodeItem['href']))
856 {
857 $setContactsBlockCode = [
858 '14.1.contacts_4_cols',
859 '14.2contacts_3_cols',
860 '14.3contacts_2_cols'
861 ];
862 if (preg_match('/^tel:.*$/i', $nodeItem['href']))
863 {
864 $nodeItem['href'] = 'tel:#crmPhone1';
865 if (isset($nodeItem['text']))
866 {
867 $nodeItem['text'] = '#crmPhoneTitle1';
868 }
869 if (
870 (isset($block['nodes']['.landing-block-node-linkcontact-text'])
871 && in_array($block['code'], $setContactsBlockCode, true))
872 )
873 {
874 $block['nodes']['.landing-block-node-linkcontact-text'][$countNodeItem] = '#crmPhoneTitle1';
875 }
876 }
877 if (preg_match('/^mailto:.*$/i', $nodeItem['href']))
878 {
879 $nodeItem['href'] = 'mailto:#crmEmail1';
880 if (isset($nodeItem['text']))
881 {
882 $nodeItem['text'] = '#crmEmailTitle1';
883 }
884 if (
885 isset($block['nodes']['.landing-block-node-linkcontact-text'])
886 && (in_array($block['code'], $setContactsBlockCode, true))
887 )
888 {
889 $block['nodes']['.landing-block-node-linkcontact-text'][$countNodeItem] = '#crmEmailTitle1';
890 }
891 }
892 }
893 $countNodeItem++;
894 }
895 unset($nodeItem);
896 }
897 unset($node);
898 }
899 //fix countdown until the next unexpired date
900 if (isset($block['attrs']))
901 {
902 foreach ($block['attrs'] as &$attr)
903 {
904 foreach ($attr as &$attrItem)
905 {
906 if (array_key_exists('data-end-date', $attrItem))
907 {
908 $neededAttr = $attrItem['data-end-date'] / 1000;
909 $currenDate = time();
910 if ($neededAttr < $currenDate)
911 {
912 $m = date('m', $neededAttr);
913 $d = date('d', $neededAttr);
914 $currenDateY = (int)date('Y', $currenDate);
915 $currenDateM = date('m', $currenDate);
916 $currenDateD = date('d', $currenDate);
917 if ($currenDateM > $m)
918 {
919 $y = $currenDateY + 1;
920 }
921 else if (($currenDateM === $m) && $currenDateD >= $d)
922 {
923 $y = $currenDateY + 1;
924 }
925 else
926 {
927 $y = $currenDateY;
928 }
929 $time = '10:00:00';
930 $timestamp = strtotime($y . '-' . $m . '-' . $d . ' ' . $time) * 1000;
931 $attrItem['data-end-date'] = (string)$timestamp;
932
933 if (preg_match_all(
934 '/data-end-date="\d+"/',
935 $block['full_content'],
936 $matches)
937 )
938 {
939 $block['full_content'] = str_replace(
940 $matches[0],
941 'data-end-date="' . $attrItem['data-end-date'] . '"',
942 $block['full_content']
943 );
944 }
945 }
946 }
947 }
948 unset($attrItem);
949 }
950 unset($attr);
951 }
952 }
953 unset($block);
954
955 return $data;
956 }
957
964 protected static function prepareAdditionalFiles(array $data, Configuration\Structure $structure): array
965 {
966 foreach (Hook::HOOKS_CODES_FILES as $hookCode)
967 {
968 if (
969 isset($data['ADDITIONAL_FIELDS'][$hookCode]) &&
970 $data['ADDITIONAL_FIELDS'][$hookCode] > 0
971 )
972 {
973 $unpackFile = $structure->getUnpackFile($data['ADDITIONAL_FIELDS'][$hookCode]);
974
975 if ($unpackFile)
976 {
977 $data['ADDITIONAL_FIELDS'][$hookCode] = AppConfiguration::saveFile(
978 $unpackFile
979 );
980 }
981 else
982 {
983 unset($data['ADDITIONAL_FIELDS'][$hookCode]);
984 }
985 }
986 }
987
988 return $data;
989 }
990
997 protected static function saveAdditionalFilesToLanding(array $data, $landingId): void
998 {
999 foreach (Hook::HOOKS_CODES_FILES as $hookCode)
1000 {
1001 if (
1002 isset($data['ADDITIONAL_FIELDS'][$hookCode]) &&
1003 $data['ADDITIONAL_FIELDS'][$hookCode] > 0
1004 )
1005 {
1006 File::addToLanding($landingId, $data['ADDITIONAL_FIELDS'][$hookCode]);
1007 }
1008 }
1009 }
1010
1018 protected static function prepareAdditionalFields(array $data, array $additional, array $ratio = null): array
1019 {
1020 $data['ADDITIONAL_FIELDS']['THEME_USE'] = 'N';
1021 if (isset($additional['theme']) || isset($additional['theme_use_site']))
1022 {
1023 $color = $additional['theme_use_site'] ?? $additional['theme'];
1024 if ($color[0] !== '#')
1025 {
1026 $color = '#'.$color;
1027 }
1028 $data['ADDITIONAL_FIELDS']['THEME_COLOR'] = $color;
1029 unset($data['ADDITIONAL_FIELDS']['THEME_CODE']);
1030
1031 // for variant if import only page in existing site
1032 $isSinglePage = !is_array($ratio) || empty($ratio);
1033 if ($isSinglePage && !$additional['theme_use_site'])
1034 {
1035 $data['ADDITIONAL_FIELDS']['THEME_USE'] = 'Y';
1036 }
1037 }
1038
1039 // todo: how detecd mainpage?
1040 $isMainpage = false;
1041 if ($additional['title'] && $isMainpage)
1042 {
1043 $data['ADDITIONAL_FIELDS']['METAOG_TITLE'] = $additional['title'];
1044 $data['ADDITIONAL_FIELDS']['METAMAIN_TITLE'] = $additional['title'];
1045 }
1046
1047 if ($additional['description'] && $isMainpage)
1048 {
1049 $data['ADDITIONAL_FIELDS']['METAOG_DESCRIPTION'] = $additional['description'];
1050 $data['ADDITIONAL_FIELDS']['METAMAIN_DESCRIPTION'] = $additional['description'];
1051 }
1052
1053 //default widget value
1054 $buttons = \Bitrix\Landing\Hook\Page\B24button::getButtons();
1055 $buttonKeys = array_keys($buttons);
1056 if (!empty($buttonKeys))
1057 {
1058 $data['ADDITIONAL_FIELDS']['B24BUTTON_CODE'] = $buttonKeys[0];
1059 }
1060 else
1061 {
1062 $data['ADDITIONAL_FIELDS']['B24BUTTON_CODE'] = 'N';
1063 }
1064 $data['ADDITIONAL_FIELDS']['B24BUTTON_USE'] = 'N';
1065
1066 return $data;
1067 }
1068
1069 protected static function getAdditionalFieldsForReplaceByLanding(int $lid): array
1070 {
1071 $additionalFields = [];
1073 foreach ($hooks as $hook => $fields)
1074 {
1075 foreach ($fields as $code => $field)
1076 {
1077 $additionalFields[$hook . '_' . $code] = $field;
1078 }
1079 }
1080
1081 return self::getAdditionalFieldsForReplace($additionalFields);
1082 }
1083
1084
1091 protected static function mergeAdditionalFieldsForReplace(array $data, array $additionalFieldsSite): array
1092 {
1093 $additionalFields = $data['ADDITIONAL_FIELDS'] ?? [];
1094 foreach (self::getAdditionalFieldsForReplace($additionalFieldsSite) as $code => $field)
1095 {
1096 if (!isset($additionalFields[$code]))
1097 {
1098 $additionalFields[$code] = $field;
1099 }
1100 }
1101 $data['ADDITIONAL_FIELDS'] = $additionalFields;
1102
1103 return $data;
1104 }
1105
1111 protected static function getAdditionalFieldsForReplace(array $additionalFields): array
1112 {
1113 $result = [];
1114 foreach (Hook::HOOKS_CODES_DESIGN as $hookCode)
1115 {
1116 $result[$hookCode] = $additionalFields[$hookCode] ?? '';
1117 }
1118
1119 return $result;
1120 }
1121
1122 protected static function saveAdditionalFieldsToLanding(array $data, int $landingId): void
1123 {
1124 if (is_array($data['ADDITIONAL_FIELDS']) && !empty($data['ADDITIONAL_FIELDS']))
1125 {
1126 LandingCore::saveAdditionalFields($landingId, $data['ADDITIONAL_FIELDS']);
1127 }
1128 }
1129}
getManifest($extended=false, $missCache=false, array $params=array())
Definition block.php:2117
updateNodes($data, $additional=array())
Definition block.php:4367
saveDynamicParams(array $sourceParams=[], array $params=[])
Definition block.php:3396
updateCards(array $data=array())
Definition block.php:4636
static getAnchor($id)
Definition block.php:1717
static addToLanding($lid, $fileId)
Definition file.php:266
static addToBlock(int $blockId, $fileId, bool $temp=false)
Definition file.php:305
static getFilePath($fileId)
Definition file.php:600
const HOOKS_CODES_FILES
Definition hook.php:45
static getData($id, $type, $asIs=false)
Definition hook.php:104
const HOOKS_CODES_DESIGN
Definition hook.php:53
const ENTITY_TYPE_LANDING
Definition hook.php:25
static isAutoPublicationEnabled()
Definition manager.php:437
static add($fields)
Definition repo.php:19
static setFormIdToBlock(int $blockId, int $formId)
Definition form.php:679
static addFilesToBlock(Block $block, array $data, Configuration\Structure $structure, bool $ignoreManifest=false)
Definition landing.php:84
static mergeAdditionalFieldsForReplace(array $data, array $additionalFieldsSite)
Definition landing.php:1091
static prepareBlocksData(array $data, Event $event)
Definition landing.php:785
static setForceAppendRestBlocks(bool $mode)
Definition landing.php:39
static saveDataToBlock(Block $blockInstance, array $block)
Definition landing.php:143
static isNeedImport(Event $event)
Definition landing.php:749
static replaceLanding(Event $event)
Definition landing.php:585
static importLanding(Event $event)
Definition landing.php:422
static saveAdditionalFieldsToLanding(array $data, int $landingId)
Definition landing.php:1122
static prepareAdditionalFields(array $data, array $additional, array $ratio=null)
Definition landing.php:1018
static getAdditionalFieldsForReplaceByLanding(int $lid)
Definition landing.php:1069
static saveAdditionalFilesToLanding(array $data, $landingId)
Definition landing.php:997
static prepareAdditionalFiles(array $data, Configuration\Structure $structure)
Definition landing.php:964
static getRepoId(string $appCode, string $xmlId)
Definition landing.php:50
static importBlock(LandingCore $landing, array $block, Configuration\Structure $structure, bool &$pending=false)
Definition landing.php:239
static getAdditionalFieldsForReplace(array $additionalFields)
Definition landing.php:1111
getParameter($key)
Definition event.php:80