catalog->has($child)) { return sprintf('unbekanntes Modul "%s" (siehe lit-divi-catalog)', $child); } if ($parent === null) { return $child === 'divi/section' ? null : 'auf oberster Ebene sind nur Abschnitte (section) erlaubt'; } if (! $parent->isDivi() || $parent->isOpaque()) { return 'der Zielknoten ist nur lesbar (globales Modul oder fremder Block)'; } $parentName = $parent->name(); if ($parentName === 'divi/section') { return $this->inSection($parent, $child); } if (in_array($parentName, self::ROWS, true)) { return 'Spalten entstehen mit der Zeile ("columns"); eine neue Zeile mit der gewünschten Aufteilung ' . 'einfügen'; } if (in_array($parentName, self::COLUMNS, true) && self::isSpecialtyColumn($parent)) { return 'Spezialspalten (specialty) nur im Divi-Builder umbauen; Module in ihre inneren Spalten einfügen'; } if (in_array($parentName, self::COLUMNS, true) || $parentName === 'divi/group') { // A nested row: only straight into a (Divi 5) column – like the builder's drop target. $nestedRow = $child === 'divi/row' && $parentName === 'divi/column'; return $this->isPlainModule($child) || $child === 'divi/group' || $nestedRow ? null : sprintf('%s passt nicht in eine Spalte', $child); } $children = $this->catalog->childrenOf($parentName); if ($children === []) { return sprintf('%s kann keine Kind-Module enthalten', $parentName); } return in_array($child, $children, true) ? null : sprintf('%s erlaubt nur %s als Kind', $parentName, implode(', ', $children)); } /** A module that goes into a column: catalog category "module" (not "fullwidth-module"). */ public function isPlainModule(string $name): bool { return $this->catalog->category($name) === 'module'; } /** A column of a specialty section: it holds inner rows, not modules. */ private static function isSpecialtyColumn(Block $column): bool { $specialty = AttrMap::desktop($column->attrs(), 'module.advanced.specialtyColumns'); if ($specialty !== null && $specialty !== '') { return true; } foreach ($column->children() as $child) { if ($child->name() === 'divi/row-inner') { return true; } } return false; } private function inSection(Block $section, string $child): ?string { $type = AttrMap::desktop($section->attrs(), 'module.advanced.type'); if ($type === 'specialty') { return 'Spezialabschnitte (specialty) nur im Divi-Builder umbauen; Module in ihre Spalten einfügen'; } if ($type === 'fullwidth') { return $this->catalog->category($child) === self::FULLWIDTH ? null : 'in einen Vollbreite-Abschnitt passen nur fullwidth-Module'; } return $child === 'divi/row' ? null : 'ein Abschnitt enthält Zeilen (row)'; } }