fix: Task 7 review round 1 - copy the raw admin label verbatim on duplicate
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,6 @@ namespace LIT\MCP\Integrations\Divi\Pages;
|
|||||||
use LIT\MCP\Abilities\Ability;
|
use LIT\MCP\Abilities\Ability;
|
||||||
use LIT\MCP\Abilities\ToolResult;
|
use LIT\MCP\Abilities\ToolResult;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
|
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\NodeSummary;
|
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,10 +85,16 @@ final class DiviDuplicateNodeAbility implements Ability
|
|||||||
|
|
||||||
$copy = $this->writer->composition($page)->editor()->duplicate($page->index, $node);
|
$copy = $this->writer->composition($page)->editor()->duplicate($page->index, $node);
|
||||||
if ($copy->isDivi() && ! $copy->isOpaque()) {
|
if ($copy->isDivi() && ! $copy->isOpaque()) {
|
||||||
$label = NodeSummary::label($node);
|
// The raw stored desktop value (never NodeSummary::label()'s display-shortened
|
||||||
$copy->setAttrs(AttrMap::set($copy->attrs(), 'module.meta.adminLabel', [
|
// text): a long or multi-line label must be copied verbatim, only " (Kopie)" added.
|
||||||
'desktop' => ['value' => ($label === '' ? $node->shortName() : $label) . ' (Kopie)'],
|
// Setting only the ".desktop.value" leaf keeps every other breakpoint untouched.
|
||||||
]));
|
$raw = AttrMap::desktop($node->attrs(), 'module.meta.adminLabel');
|
||||||
|
$label = is_string($raw) ? $raw : '';
|
||||||
|
$copy->setAttrs(AttrMap::set(
|
||||||
|
$copy->attrs(),
|
||||||
|
'module.meta.adminLabel.desktop.value',
|
||||||
|
($label === '' ? $node->shortName() : $label) . ' (Kopie)'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$change = (new DiviChange(sprintf('Knoten %s dupliziert', $id)))->changed($copy, 'duplicated');
|
$change = (new DiviChange(sprintf('Knoten %s dupliziert', $id)))->changed($copy, 'duplicated');
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace LIT\MCP\Tests\Unit\Integrations\Divi\Pages;
|
|||||||
use Brain\Monkey\Functions;
|
use Brain\Monkey\Functions;
|
||||||
use LIT\MCP\Abilities\Rev;
|
use LIT\MCP\Abilities\Rev;
|
||||||
use LIT\MCP\ChangeLog\ChangeLog;
|
use LIT\MCP\ChangeLog\ChangeLog;
|
||||||
|
use LIT\MCP\Integrations\Divi\BlockTree\AttrMap;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
|
use LIT\MCP\Integrations\Divi\BlockTree\NodeIndex;
|
||||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||||
@@ -458,6 +459,60 @@ final class DiviWriteAbilitiesTest extends TestCase
|
|||||||
self::assertSame(str_replace($globalRow, $globalRow . $globalRow, $mixed), $this->saved[0]);
|
self::assertSame(str_replace($globalRow, $globalRow . $globalRow, $mixed), $this->saved[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix round 1 (Important-1): the copy's admin label must be the raw stored desktop value
|
||||||
|
* plus " (Kopie)" – never NodeSummary::label()'s display-shortened text (80-char limit).
|
||||||
|
*/
|
||||||
|
public function testDuplicateCopiesALongAdminLabelVerbatim(): void
|
||||||
|
{
|
||||||
|
$long = str_repeat('Ausführliche Beschriftung, ', 4) . 'Ende';
|
||||||
|
self::assertGreaterThan(80, strlen($long), 'precondition: longer than the NodeSummary::label() display limit');
|
||||||
|
$content = str_replace(
|
||||||
|
'"module":{"meta":{"adminLabel":{"desktop":{"value":"Hero – Button"}}}}',
|
||||||
|
'"module":{"meta":{"adminLabel":{"desktop":{"value":"' . $long . '"}}}}',
|
||||||
|
$this->original
|
||||||
|
);
|
||||||
|
self::assertNotSame($content, $this->original, 'precondition: replaced exactly once');
|
||||||
|
$this->post->post_content = $content;
|
||||||
|
|
||||||
|
$result = $this->duplicate()->execute(['post_id' => 7, 'tree_rev' => Rev::of($content), 'id' => 's0.r0.c1.m2']);
|
||||||
|
|
||||||
|
self::assertTrue($result['ok'], (string) json_encode($result));
|
||||||
|
$index = NodeIndex::build((new Parser())->parse($this->saved[0]));
|
||||||
|
$copy = $index->find('s0.r0.c1.m3');
|
||||||
|
self::assertNotNull($copy, 'the duplicate sits right after the original module');
|
||||||
|
self::assertSame(
|
||||||
|
$long . ' (Kopie)',
|
||||||
|
AttrMap::desktop($copy->attrs(), 'module.meta.adminLabel'),
|
||||||
|
'stored verbatim, not shortened/ellipsised for display'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDuplicateCopiesALabelWithNewlinesAndMultipleSpacesVerbatim(): void
|
||||||
|
{
|
||||||
|
$messy = "Erste Zeile mit viel Leerraum\nZweite Zeile";
|
||||||
|
$encoded = substr((string) json_encode($messy, JSON_UNESCAPED_UNICODE), 1, -1);
|
||||||
|
$content = str_replace(
|
||||||
|
'"module":{"meta":{"adminLabel":{"desktop":{"value":"Hero – Button"}}}}',
|
||||||
|
'"module":{"meta":{"adminLabel":{"desktop":{"value":"' . $encoded . '"}}}}',
|
||||||
|
$this->original
|
||||||
|
);
|
||||||
|
self::assertNotSame($content, $this->original, 'precondition: replaced exactly once');
|
||||||
|
$this->post->post_content = $content;
|
||||||
|
|
||||||
|
$result = $this->duplicate()->execute(['post_id' => 7, 'tree_rev' => Rev::of($content), 'id' => 's0.r0.c1.m2']);
|
||||||
|
|
||||||
|
self::assertTrue($result['ok'], (string) json_encode($result));
|
||||||
|
$index = NodeIndex::build((new Parser())->parse($this->saved[0]));
|
||||||
|
$copy = $index->find('s0.r0.c1.m3');
|
||||||
|
self::assertNotNull($copy, 'the duplicate sits right after the original module');
|
||||||
|
self::assertSame(
|
||||||
|
$messy . ' (Kopie)',
|
||||||
|
AttrMap::desktop($copy->attrs(), 'module.meta.adminLabel'),
|
||||||
|
'whitespace/newlines kept verbatim, not collapsed'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** Permission denied (edit_post false) for all three new abilities. */
|
/** Permission denied (edit_post false) for all three new abilities. */
|
||||||
public function testPermissionDeniedWhenNotEditable(): void
|
public function testPermissionDeniedWhenNotEditable(): void
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user