| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- <?php
- namespace App\Support;
- use DOMDocument;
- use DOMElement;
- use App\Support\Traits\BlockLayoutDetectorTrait;
- use App\Support\Traits\BlockLayoutBuilderTrait;
- use App\Support\Traits\BlockLayoutHelpersTrait;
- /*
- * BlockLayoutParser — разбирает произвольный HTML-фрагмент и автоматически:
- * 1. Определяет поля блока (плоские или repeater-группу).
- * 2. Генерирует черновик Blade-шаблона с {{ $data[...] }} / {{ $item[...] }}.
- *
- * Логика разбита по трейтам (app/Support/Traits/):
- * BlockLayoutDetectorTrait — detectRepeater, allSimilar
- * BlockLayoutBuilderTrait — buildFlat, buildRepeater
- * BlockLayoutHelpersTrait — extractFields, mkField, applyTokens, replaceTokens,
- * serializeChildren, publicFields, elementChildren
- */
- class BlockLayoutParser
- {
- use BlockLayoutDetectorTrait;
- use BlockLayoutBuilderTrait;
- use BlockLayoutHelpersTrait;
- private DOMDocument $dom;
- private array $usedNames = [];
- private array $tokens = []; // token => bladeExpr
- /**
- * Разбирает HTML и возвращает:
- * fields — определения полей для BlockLayoutRegistry
- * blade — черновик Blade-шаблона
- * is_repeater — обнаружена ли repeater-структура
- */
- public function parse(string $html): array
- {
- $this->usedNames = [];
- $this->tokens = [];
- $this->dom = new DOMDocument('1.0', 'UTF-8');
- libxml_use_internal_errors(true);
- // charset-мета нужна чтобы DOMDocument корректно читал UTF-8 (emoji, кириллица)
- $this->dom->loadHTML(
- '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
- . '<div id="BLPARSER">' . $html . '</div>'
- );
- libxml_clear_errors();
- $wrapper = $this->dom->getElementById('BLPARSER');
- if (!$wrapper) {
- return ['fields' => [], 'blade' => $html, 'is_repeater' => false];
- }
- // Ищем repeater-группу
- $repeater = $this->detectRepeater($wrapper);
- if ($repeater) {
- [$container, $items] = $repeater;
- return $this->buildRepeater($wrapper, $container, $items);
- }
- return $this->buildFlat($wrapper);
- }
- }
|