feat: lit-divi-move warnt, wenn Schleifen-Inhalte ihre Schleife verlassen oder in eine andere Art kommen (X3, A11)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
8888d246a9
commit
ed6fe12ada
@@ -6,6 +6,10 @@ namespace LIT\MCP\Integrations\Divi\Pages;
|
||||
|
||||
use LIT\MCP\Abilities\Annotations;
|
||||
use LIT\MCP\Abilities\Errors;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Block;
|
||||
use LIT\MCP\Integrations\Divi\Compose\LoopContext;
|
||||
use LIT\MCP\Integrations\Divi\Compose\LoopScope;
|
||||
use LIT\MCP\Integrations\Divi\Compose\VariableRef;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviFeature;
|
||||
use WP_Error;
|
||||
|
||||
@@ -14,7 +18,8 @@ defined('ABSPATH') || exit;
|
||||
/**
|
||||
* lit/divi-move: moves a node (with everything inside) to parent / before / after – also into
|
||||
* another row or section, as long as the structure rules allow it (spec §5.7). Read-only
|
||||
* nodes (global modules, foreign blocks) move as a whole, unchanged.
|
||||
* nodes (global modules, foreign blocks) move as a whole, unchanged. Loop content that leaves its loop scope (out
|
||||
* of a loop, into one of another kind) is moved with a warning – Divi allows it (rulings X3, A11).
|
||||
*/
|
||||
final class DiviMoveAbility extends DiviWriteAbility
|
||||
{
|
||||
@@ -76,6 +81,9 @@ final class DiviMoveAbility extends DiviWriteAbility
|
||||
return DiviErrors::position($position);
|
||||
}
|
||||
|
||||
// Both scopes from the tree before the move: the new parent never lies inside $node (TreeEditor::move()).
|
||||
$from = self::loopAt($page->index, $page->index->parentBlock($node));
|
||||
$to = self::loopAt($page->index, $position['parent']);
|
||||
$problem = $editor->move($page->index, $node, $position);
|
||||
if ($problem !== null) {
|
||||
return Errors::invalidInput(
|
||||
@@ -84,6 +92,58 @@ final class DiviMoveAbility extends DiviWriteAbility
|
||||
);
|
||||
}
|
||||
|
||||
return (new DiviChange(sprintf('Knoten %s verschoben', $id)))->record($node, 'moved');
|
||||
$change = (new DiviChange(sprintf('Knoten %s verschoben', $id)))->record($node, 'moved');
|
||||
$names = self::loopContent($node);
|
||||
if ($names !== [] && $from->kind() !== $to->kind()) {
|
||||
$change->warning(self::loopWarning($names, $from, $to));
|
||||
}
|
||||
|
||||
return $change;
|
||||
}
|
||||
|
||||
/**
|
||||
* The loop_* options $block and its descendants show in the scope around $block; a block that runs its own
|
||||
* loop keeps its content's scope, read-only blocks are not entered.
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private static function loopContent(Block $block): array
|
||||
{
|
||||
if ($block->isOpaque() || LoopContext::enabled($block->attrs())) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$names = [];
|
||||
$attrs = $block->attrs();
|
||||
array_walk_recursive($attrs, static function (mixed $value) use (&$names): void {
|
||||
$name = is_string($value) ? VariableRef::nameOf($value) : null;
|
||||
if ($name !== null && str_starts_with($name, 'loop_')) {
|
||||
$names[] = $name;
|
||||
}
|
||||
});
|
||||
foreach ($block->children() as $child) {
|
||||
array_push($names, ...self::loopContent($child));
|
||||
}
|
||||
|
||||
return array_values(array_unique($names));
|
||||
}
|
||||
|
||||
/** @param list<string> $names */
|
||||
private static function loopWarning(array $names, LoopScope $from, LoopScope $to): string
|
||||
{
|
||||
$where = $to->active()
|
||||
? sprintf(
|
||||
'jetzt in einer Divi-Schleife vom Typ: %s (vorher: %s); passen sie nicht zu dieser Art, zeigt Divi '
|
||||
. 'sie leer oder mit Daten eines anderen Objekts mit derselben ID',
|
||||
$to->label(),
|
||||
$from->active() ? $from->label() : 'keine Schleife'
|
||||
)
|
||||
: 'jetzt außerhalb jeder Divi-Schleife; Divi zeigt sie dort leer';
|
||||
|
||||
return sprintf(
|
||||
'Schleifen-Inhalte (%s) liegen %s. Zurückverschieben oder die Inhalte anpassen.',
|
||||
implode(', ', $names),
|
||||
$where
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user