22 'TEXT_IMAGE' =>
'textImage',
23 'TARIFFS' =>
'tariffs',
25 'FEEDBACK' =>
'feedback',
27 'SEPARATORS' =>
'separators',
30 private const BG_TYPES = [
31 'TRANSPARENT' =>
'transparent',
32 'PRIMARY' =>
'primary',
36 private const BG_SEPARATOR_TYPES = [
37 'TYPE_1' =>
'transparentToPrimary',
38 'TYPE_2' =>
'primaryToTransparent',
41 private const JUST_ONCE_SECTIONS = [
42 self::SECTIONS[
'TARIFFS'],
43 self::SECTIONS[
'TEAM'],
46 private const SEPARATOR_CREATION_PROBABILITY = 70;
51 private array $blocks = [];
56 private array $addedSections = [];
71 if (!empty($this->blocks))
76 $this->addRandomBlock(self::SECTIONS[
'MENU']);
77 $this->addRandomBlock(self::SECTIONS[
'COVER']);
78 $this->addRandomBlock(self::SECTIONS[
'TEXT_IMAGE']);
79 $this->addRandomBlock(self::SECTIONS[
'TEXT_IMAGE']);
80 $this->addRandomBlock($this->getRandomFromSections([
81 self::SECTIONS[
'TARIFFS'],
82 self::SECTIONS[
'TEXT_IMAGE'],
83 self::SECTIONS[
'TEAM'],
85 $this->addRandomBlock($this->getRandomFromSections([
86 self::SECTIONS[
'TEXT_IMAGE'],
87 self::SECTIONS[
'TARIFFS'],
88 self::SECTIONS[
'FEEDBACK'],
89 self::SECTIONS[
'TEAM'],
91 $this->addRandomBlock(self::SECTIONS[
'FORM']);
101 '26.2.separator' => [
102 'heightClass' =>
'g-height-70--md',
104 '26.3.separator' => [
105 'heightClass' =>
'g-height-70--md',
107 '26.4.separator' => [
108 'heightClass' =>
'g-height-70--md',
110 '26.5.separator' => [
111 'heightClass' =>
'g-height-70--md',
127 'property' => [
'--color'],
128 'styleValue' => [
'colorsHeadersTheme'],
131 'property' => [
'--color'],
132 'styleValue' => [
'colorsTextsTheme'],
135 'property' => [
'--border-color'],
136 'styleValue' => [
'colorsTextsTheme'],
140 $blocksStylesData = [
141 '04.7.one_col_fix_with_title_and_text_2' => [
142 '.landing-block-node-inner' => $sharedStyles[
'border'],
143 '.landing-block-node-subtitle' => $sharedStyles[
'text'],
144 '.landing-block-node-title' => $sharedStyles[
'title'],
145 '.landing-block-node-text' => $sharedStyles[
'text'],
147 '04.1.one_col_fix_with_title' => [
148 '.landing-block-node-inner' => $sharedStyles[
'border'],
149 '.landing-block-node-subtitle' => $sharedStyles[
'text'],
150 '.landing-block-node-title' => $sharedStyles[
'title'],
152 '08.4.fix_title_and_text' => [
153 '.landing-block-node-title' => [
154 'property' => [
'--color',
'--border-color'],
155 'styleValue' => [
'colorsHeadersTheme',
'colorsTextsTheme'],
157 '.landing-block-node-text' => $sharedStyles[
'text'],
159 '27.one_col_fix_title_and_text_2' => [
160 '.landing-block-node-title' => $sharedStyles[
'title'],
161 '.landing-block-node-text' => $sharedStyles[
'text'],
163 '27.3.one_col_fix_title' => [
164 '.landing-block-node-title' => $sharedStyles[
'title'],
166 '20.3.four_cols_fix_img_title_text' => [
167 '.landing-block-node-title' => $sharedStyles[
'title'],
168 '.landing-block-node-text' => $sharedStyles[
'text'],
170 '20.2.three_cols_fix_img_title_text' => [
171 '.landing-block-node-title' => $sharedStyles[
'title'],
172 '.landing-block-node-text' => $sharedStyles[
'text'],
174 '31.4.two_cols_img_text_fix' => [
175 '.landing-block-node-title' => $sharedStyles[
'title'],
176 '.landing-block-node-text' => $sharedStyles[
'text'],
178 '31.3.two_cols_text_img_fix' => [
179 '.landing-block-node-title' => $sharedStyles[
'title'],
180 '.landing-block-node-text' => $sharedStyles[
'text'],
182 '19.2.features_with_img' => [
183 '.landing-block-node-card-icon-border' => $sharedStyles[
'title'],
184 '.landing-block-node-subtitle' => $sharedStyles[
'title'],
185 '.landing-block-node-title' => $sharedStyles[
'title'],
186 '.landing-block-node-text' => $sharedStyles[
'text'],
187 '.landing-block-node-card-title' => $sharedStyles[
'title'],
188 '.landing-block-node-card-text' => $sharedStyles[
'text'],
190 '19.2.features_with_img_right' => [
191 '.landing-block-node-card-icon-border' => $sharedStyles[
'title'],
192 '.landing-block-node-subtitle' => $sharedStyles[
'title'],
193 '.landing-block-node-title' => $sharedStyles[
'title'],
194 '.landing-block-node-text' => $sharedStyles[
'text'],
195 '.landing-block-node-card-title' => $sharedStyles[
'title'],
196 '.landing-block-node-card-text' => $sharedStyles[
'text'],
198 '09.1.two_cols_fix_text_and_image_slider_2' => [
199 '.landing-block-node-header' => $sharedStyles[
'border'],
200 '.landing-block-node-subtitle' => $sharedStyles[
'title'],
201 '.landing-block-node-title' => $sharedStyles[
'title'],
202 '.landing-block-node-text' => $sharedStyles[
'text'],
204 '09.1.two_cols_fix_text_and_image_slider' => [
205 '.landing-block-node-header' => $sharedStyles[
'border'],
206 '.landing-block-node-subtitle' => $sharedStyles[
'title'],
207 '.landing-block-node-title' => $sharedStyles[
'title'],
208 '.landing-block-node-text' => $sharedStyles[
'text'],
210 '18.two_cols_fix_img_text_button' => [
211 '.landing-block-node-title' => $sharedStyles[
'title'],
212 '.landing-block-node-text' => $sharedStyles[
'text'],
213 '.landing-block-node-button' => [
214 'property' => [
'--color',
'--color-hover',
'--button-color'],
215 'styleValue' => [
'colorsTextsTheme',
'var(--primary)',
'colorsTextsTheme'],
218 '19.4.features_with_img' => [
219 '.landing-block-node-subtitle' => $sharedStyles[
'title'],
220 '.landing-block-node-title' => $sharedStyles[
'title'],
221 '.landing-block-node-text' => $sharedStyles[
'text'],
223 '19.4.features_with_img_left' => [
224 '.landing-block-node-subtitle' => $sharedStyles[
'title'],
225 '.landing-block-node-title' => $sharedStyles[
'title'],
226 '.landing-block-node-text' => $sharedStyles[
'text'],
228 '11.2.three_cols_fix_tariffs_with_img' => [
229 '.landing-block-node-title' => [
230 'property' => [
'--color',
'--border-color'],
231 'styleValue' => [
'colorsHeadersTheme',
'colorsHeadersTheme'],
233 '.landing-block-node-text' => $sharedStyles[
'text'],
235 '28.personal_slider_2' => [
236 '.landing-block-node-person-name' => $sharedStyles[
'title'],
237 '.landing-block-node-person-post' => $sharedStyles[
'title'],
238 '.landing-block-node-person-text' => $sharedStyles[
'text'],
239 '.landing-block-node-person-link' => $sharedStyles[
'text'],
241 '44.6.two_columns_with_peoples' => [
242 '.landing-block-node-card-name' => $sharedStyles[
'title'],
243 '.landing-block-node-card-post' => $sharedStyles[
'title'],
244 '.landing-block-node-card-text' => $sharedStyles[
'text'],
248 return $blocksStylesData[$codeBlock] ??
null;
254 '0.menu_14_music' =>
'.landing-block-node-menu-list-item-link',
255 '0.menu_19_travel' =>
'.landing-block-node-menu-list-item-link',
256 '0.menu_05' =>
'.landing-block-node-menu-list-item-link',
259 return $menuBlocksData[
$code] ??
null;
265 '0.menu_14_music' =>
'.landing-block-node-menu-list-item',
266 '0.menu_19_travel' =>
'.landing-block-node-menu-list-item',
267 '0.menu_05' =>
'.landing-block-node-menu-list-item',
270 return $menuBlocksData[
$code] ??
null;
275 $blocksWithAvatarNodes = [
276 '20.4.text_3cols_with_bottom_information' => [
277 'imgNodeCode' =>
'.landing-block-node-author-img',
278 'textNodeCode' =>
'.landing-block-node-author',
280 '23.big_carousel_blocks' => [
281 'imgNodeCode' =>
'.landing-block-node-img',
282 'textNodeCode' =>
'.landing-block-node-title',
284 '28.personal_slider_2' => [
285 'imgNodeCode' =>
'.landing-block-node-person-photo',
286 'textNodeCode' =>
'.landing-block-node-person-name',
289 'imgNodeCode' =>
'.landing-block-node-employee-photo',
290 'textNodeCode' =>
'.landing-block-node-employee-name',
292 '43.3.cover_with_feedback' => [
293 'imgNodeCode' =>
'.landing-block-node-card-photo',
294 'textNodeCode' =>
'.landing-block-node-card-name',
296 '43.5.cover_with_feedback_2' => [
297 'imgNodeCode' =>
'.landing-block-node-card-photo',
298 'textNodeCode' =>
'.landing-block-node-card-name',
300 '44.6.two_columns_with_peoples' => [
301 'imgNodeCode' =>
'.landing-block-node-card-photo',
302 'textNodeCode' =>
'.landing-block-node-card-name',
306 return $blocksWithAvatarNodes[$codeBlock] ?? [];
311 $blocksTitlesNodes = [
312 '04.1.one_col_fix_with_title' => [
313 '.landing-block-node-inner',
315 '04.7.one_col_fix_with_title_and_text_2' => [
316 '.landing-block-node-inner',
318 '08.4.fix_title_and_text' => [
319 '.landing-block-node-title',
321 '09.1.two_cols_fix_text_and_image_slider' => [
322 '.landing-block-node-header',
324 '09.1.two_cols_fix_text_and_image_slider_2' => [
325 '.landing-block-node-header',
327 '11.2.three_cols_fix_tariffs_with_img' => [
328 '.landing-block-node-title',
330 '27.one_col_fix_title_and_text_2' => [
331 '.landing-block-node-title',
333 '27.3.one_col_fix_title' => [
334 '.landing-block-node-title',
337 '.landing-block-node-title',
341 return $blocksTitlesNodes[$codeBlock] ?? [];
347 '01.big_with_text_3' => [
348 '.landing-block-node-img',
350 '01.big_with_text_3_1' => [
351 '.landing-block-node-img',
353 '41.3.announcement_with_slider' => [
354 '.landing-block-node-bgimg',
359 private function finalize(): void
361 $this->pasteTitleBlocks();
362 $this->applyBgTypeToNextBlock();
363 $this->pasteSeparatorBlocks();
373 private function addRandomBlock(
string $section): void
375 $allowedBlocks = $this->getAllowedBlocks();
377 if (!$this->isValidSection($section, $allowedBlocks))
382 $code = $this->getRandomElement(array_keys($allowedBlocks[$section]));
383 $bgType = $this->getRandomElement($allowedBlocks[$section][
$code][
'bgType']);
385 if (!
$code || !$bgType)
390 $block = self::createBlock(
$code, $section, $bgType);
392 $this->blocks[] = $block;
393 $this->addedSections[] = $section;
396 private function isValidSection(
string $section,
array $allowedBlocks): bool
398 if (!isset($allowedBlocks[$section]))
413 private function getRandomElement(
array $variants): ?string
415 if (empty($variants))
420 return $variants[array_rand($variants)];
423 private static function createBlock(
string $code,
string $section,
string $bgType): Data\Block
425 $block =
new Data\Block(
$code, $section, $bgType);
426 self::createNodesInBlock($block);
431 private static function createNodesInBlock(Data\Block $block): void
433 $blockCode = $block->getCode();
434 $manifest = Block::getManifestFile($blockCode);
435 if (!isset($manifest[
'nodes']))
440 $nodes = $manifest[
'nodes'];
441 $blockContent = Block::getContentFromRepository($blockCode);
443 foreach ($nodes as
$code => $node)
445 $nodeCode = ltrim(
$code,
'.');
446 $countElements = substr_count($blockContent, $nodeCode .
' ');
447 $countElements += substr_count($blockContent, $nodeCode .
'"');
448 $node[
'placeholders'] = array_fill(0, $countElements,
'');
449 if (in_array(
$code, self::getAvatarNodes($blockCode),
true))
451 $node[
'isAvatarNode'] =
true;
453 if ($node[
'type'] ===
'img' && !$block->isMenu())
456 $node[
'sizeData'] = $dataImages;
458 $node[
'defaultSrc'] = $defaultSrcData[
'src'];
459 if ($node[
'create2xByDefault'] ===
false)
461 $node[
'defaultSrc2x'] = $node[
'defaultSrc'];
465 $node[
'defaultSrc2x'] = $defaultSrcData[
'src2x'];
469 $type = NodeType::from($node[
'type'] ??
'');
473 $block->addNode($createdNode);
483 private function pasteSeparatorBlocks(): void
485 $separatorsGroup = $this->getRandomSeparatorsGroup($this->getAllowedBlocks());
487 if (!$separatorsGroup)
492 $blocksListWithSeparators = [];
493 $previousBgType =
null;
494 $previousSectionIsMenu =
false;
496 foreach ($this->blocks as $block)
498 $currentBgType = $block->getBgType();
499 $randomSeparatorProbability = rand(1, 100);
502 $randomSeparatorProbability <= self::SEPARATOR_CREATION_PROBABILITY
503 && !$previousSectionIsMenu
504 && $this->shouldAddSeparator($previousBgType, $currentBgType)
507 $blocksListWithSeparators[] = $this->createSeparatorBlock($separatorsGroup, $currentBgType);
510 $blocksListWithSeparators[] = $block;
511 $previousBgType = $currentBgType;
512 $previousSectionIsMenu = $block->isMenu();
515 $this->blocks = $blocksListWithSeparators;
523 private function pasteTitleBlocks(): void
525 $allowedBlocks = $this->getAllowedBlocks();
526 $blocksListWithSeparators = [];
527 foreach ($this->blocks as $block)
529 if ($this->isNeedTitles($block->getCode()))
531 $code = $this->getRandomElement(array_keys($allowedBlocks[self::SECTIONS[
'TITLE']]));
532 $preferredBgType = $block->getBgType();
533 if (in_array($preferredBgType, $allowedBlocks[self::SECTIONS[
'TITLE']][
$code][
'bgType'],
true))
535 $bgType = $preferredBgType;
539 $bgType = $this->getRandomElement($allowedBlocks[self::SECTIONS[
'TITLE']][
$code][
'bgType']);
541 $blocksListWithSeparators[] = $this->createTitleBlock(
$code, $bgType);
543 $blocksListWithSeparators[] = $block;
545 $this->blocks = $blocksListWithSeparators;
556 private function shouldAddSeparator(?
string $previousBgType,
string $currentBgType): bool
558 return ($currentBgType === self::BG_TYPES[
'PRIMARY'] && $previousBgType === self::BG_TYPES[
'TRANSPARENT'])
559 || ($currentBgType === self::BG_TYPES[
'TRANSPARENT'] && $previousBgType === self::BG_TYPES[
'PRIMARY']);
570 private function createSeparatorBlock(
array $separatorsGroup,
string $currentBgType): Data\Block
572 $separatorCode = $separatorsGroup[array_rand($separatorsGroup)];
573 $bgTypeIsPrimary = $currentBgType === self::BG_TYPES[
'PRIMARY'];
574 $separatorBg = $bgTypeIsPrimary ? self::BG_SEPARATOR_TYPES[
'TYPE_1'] : self::BG_SEPARATOR_TYPES[
'TYPE_2'];
576 $separatorBlock =
new Data\Block($separatorCode, self::SECTIONS[
'SEPARATORS'], $separatorBg);
577 $nodes = Block::getManifestFile($separatorCode)[
'nodes'];
579 foreach ($nodes as
$key => $node)
581 if (isset($node[
'type']))
583 $type = NodeType::from($node[
'type']);
587 $separatorBlock->addNode($node);
592 return $separatorBlock;
603 private function createTitleBlock(
string $code,
string $bgType): Data\Block
605 return self::createBlock(
$code, self::SECTIONS[
'TITLE'], $bgType);
615 private function getRandomSeparatorsGroup(
array $allowedBlocks): ?
array
617 if (empty($allowedBlocks[self::SECTIONS[
'SEPARATORS']]))
622 return $allowedBlocks[self::SECTIONS[
'SEPARATORS']][array_rand($allowedBlocks[self::SECTIONS[
'SEPARATORS']])];
631 private function applyBgTypeToNextBlock(): void
633 $blocksCount =
count($this->blocks);
634 foreach ($this->blocks as $index => $block)
636 if ($this->canApplyBgTypeToNextBlock($block, $index, $blocksCount))
638 $this->setBgTypeToNextBlock($block, $index);
652 private function canApplyBgTypeToNextBlock(Data\Block $block,
int $index,
int $blocksCount): bool
654 $allowedBlocks = $this->getAllowedBlocks();
656 $index + 1 > $blocksCount
658 $block->getSection() !== self::SECTIONS[
'TITLE']
659 && $block->getCode() !==
'41.3.announcement_with_slider'
666 if (isset($this->blocks[$index + 1]))
668 $nextBlock = $this->blocks[$index + 1];
669 $nextSection = $nextBlock->getSection();
670 $nextCode = $nextBlock->getCode();
672 return isset($allowedBlocks[$nextSection][$nextCode][
'bgType'])
673 && in_array($block->getBgType(), $allowedBlocks[$nextSection][$nextCode][
'bgType'],
true);
685 private function setBgTypeToNextBlock(Data\Block $block,
int $index): void
687 $nextBlock = $this->blocks[$index + 1];
688 $nextBlock->setBgType($block->getBgType());
698 private function getRandomFromSections(
array $sections): string
700 $sections = array_filter(
701 $sections,
function($section) {
702 if (!in_array($section, self::JUST_ONCE_SECTIONS,
true))
707 return !in_array($section, $this->addedSections,
true);
711 return $sections[array_rand($sections)];
719 private function getAllowedBlocks():
array
722 'notImage' => [self::BG_TYPES[
'TRANSPARENT'], self::BG_TYPES[
'PRIMARY']],
726 self::SECTIONS[
'MENU'] => [
728 'bgType' => $typeGroups[
'notImage'],
730 '0.menu_14_music' => [
731 'bgType' => $typeGroups[
'notImage'],
733 '0.menu_19_travel' => [
734 'bgType' => $typeGroups[
'notImage'],
737 self::SECTIONS[
'COVER'] => [
738 '01.big_with_text_3' => [
739 'bgType' => [self::BG_TYPES[
'IMAGE']],
741 '01.big_with_text_3_1' => [
742 'bgType' => [self::BG_TYPES[
'IMAGE']],
744 '41.3.announcement_with_slider' => [
745 'bgType' => $typeGroups[
'notImage'],
748 self::SECTIONS[
'TITLE'] => [
749 '04.1.one_col_fix_with_title' => [
750 'bgType' => $typeGroups[
'notImage'],
752 '04.7.one_col_fix_with_title_and_text_2' => [
753 'bgType' => $typeGroups[
'notImage'],
755 '08.4.fix_title_and_text' => [
756 'bgType' => $typeGroups[
'notImage'],
758 '27.one_col_fix_title_and_text_2' => [
759 'bgType' => $typeGroups[
'notImage'],
761 '27.3.one_col_fix_title' => [
762 'bgType' => $typeGroups[
'notImage'],
765 self::SECTIONS[
'TEXT_IMAGE'] => [
766 '01.big_with_text_2' => [
767 'bgType' => [self::BG_TYPES[
'IMAGE']],
769 '09.1.two_cols_fix_text_and_image_slider' => [
770 'bgType' => $typeGroups[
'notImage'],
772 '09.1.two_cols_fix_text_and_image_slider_2' => [
773 'bgType' => $typeGroups[
'notImage'],
775 '18.two_cols_fix_img_text_button' => [
776 'bgType' => $typeGroups[
'notImage'],
778 '19.2.features_with_img' => [
779 'bgType' => $typeGroups[
'notImage'],
781 '19.2.features_with_img_right' => [
782 'bgType' => $typeGroups[
'notImage'],
784 '19.4.features_with_img' => [
785 'bgType' => $typeGroups[
'notImage'],
787 '19.4.features_with_img_left' => [
788 'bgType' => $typeGroups[
'notImage'],
790 '20.2.three_cols_fix_img_title_text' => [
791 'bgType' => $typeGroups[
'notImage'],
793 '20.3.four_cols_fix_img_title_text' => [
794 'bgType' => $typeGroups[
'notImage'],
796 '20.4.text_3cols_with_bottom_information' => [
797 'bgType' => $typeGroups[
'notImage'],
799 '31.3.two_cols_text_img_fix' => [
800 'bgType' => $typeGroups[
'notImage'],
802 '31.4.two_cols_img_text_fix' => [
803 'bgType' => $typeGroups[
'notImage'],
805 '32.3.img_grid_1_2cols_1' => [
806 'bgType' => $typeGroups[
'notImage'],
808 '32.5.img_grid_3cols_1' => [
809 'bgType' => $typeGroups[
'notImage'],
811 '32.10.img_grid_2cols_3' => [
812 'bgType' => $typeGroups[
'notImage'],
814 '32.11.img_grid_4cols_4' => [
815 'bgType' => $typeGroups[
'notImage'],
817 '32.15.img_one_big_full' => [
818 'bgType' => $typeGroups[
'notImage'],
820 '40.2.two_cols_carousel' => [
821 'bgType' => $typeGroups[
'notImage'],
823 '40.6.two_img_top_bottom' => [
824 'bgType' => $typeGroups[
'notImage'],
827 self::SECTIONS[
'FEEDBACK'] => [
828 '23.big_carousel_blocks' => [
829 'bgType' => $typeGroups[
'notImage'],
831 '43.3.cover_with_feedback' => [
832 'bgType' => [self::BG_TYPES[
'IMAGE']],
834 '43.5.cover_with_feedback_2' => [
835 'bgType' => [self::BG_TYPES[
'IMAGE']],
838 self::SECTIONS[
'TARIFFS'] => [
839 '11.2.three_cols_fix_tariffs_with_img' => [
840 'bgType' => $typeGroups[
'notImage'],
842 '44.7.three_columns_with_img_and_price' => [
843 'bgType' => $typeGroups[
'notImage'],
846 self::SECTIONS[
'TEAM'] => [
847 '28.personal_slider_2' => [
848 'bgType' => $typeGroups[
'notImage'],
851 'bgType' => [self::BG_TYPES[
'IMAGE']],
853 '44.6.two_columns_with_peoples' => [
854 'bgType' => $typeGroups[
'notImage'],
857 self::SECTIONS[
'FORM'] => [
858 '33.1.form_1_transparent_black_left_text' => [
859 'bgType' => [self::BG_TYPES[
'IMAGE']],
861 '33.2.form_1_transparent_black_right_text' => [
862 'bgType' => [self::BG_TYPES[
'IMAGE']],
864 '33.10.form_2_light_left_text' => [
865 'bgType' => [self::BG_TYPES[
'TRANSPARENT']],
867 '33.12.form_2_light_right_text' => [
868 'bgType' => [self::BG_TYPES[
'TRANSPARENT']],
871 self::SECTIONS[
'SEPARATORS'] => [
872 [
'26.2.separator',
'26.3.separator'],
873 [
'26.4.separator',
'26.5.separator'],
874 [
'26.6.separator_waves'],
879 private function isNeedTitles($codeBlock): bool
881 $blockCodesWhichNeedTitles = [
882 '20.2.three_cols_fix_img_title_text',
883 '20.3.four_cols_fix_img_title_text',
884 '20.4.text_3cols_with_bottom_information',
885 '32.3.img_grid_1_2cols_1',
886 '32.5.img_grid_3cols_1',
887 '32.10.img_grid_2cols_3',
888 '32.11.img_grid_4cols_4',
889 '32.15.img_one_big_full',
890 '40.2.two_cols_carousel',
891 '40.6.two_img_top_bottom',
892 '23.big_carousel_blocks',
893 '44.7.three_columns_with_img_and_price',
894 '28.personal_slider_2',
895 '44.6.two_columns_with_peoples',
898 if (in_array($codeBlock, $blockCodesWhichNeedTitles,
true))