fix: library IDs stay hidden without library access (ruling P13)
Outline, node-get, write outlines, the render summary and replace-text's opaque-node match name no library ID unless the library group is visible and the user has divi_library; read-only still names them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,7 @@ use LIT\MCP\Integrations\Divi\Pages\DiviPageLoader;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviReplaceTextAbility;
|
||||
use LIT\MCP\Tests\Support\DiviFixtures;
|
||||
use LIT\MCP\Tests\Support\DiviWriterFixture;
|
||||
use LIT\MCP\Tests\Support\LibraryFixtures;
|
||||
use LIT\MCP\Tests\Unit\TestCase;
|
||||
use Mockery;
|
||||
use RuntimeException;
|
||||
@@ -38,13 +39,19 @@ final class DiviReplaceTextAbilityTest extends TestCase
|
||||
private array $failures = [];
|
||||
|
||||
/** @param list<int> $ids Rows of the prefilter query. */
|
||||
private function ability(?string $content = null, bool $unfiltered = false, array $ids = [7]): DiviReplaceTextAbility
|
||||
{
|
||||
private function ability(
|
||||
?string $content = null,
|
||||
bool $unfiltered = false,
|
||||
array $ids = [7],
|
||||
bool $library = false
|
||||
): DiviReplaceTextAbility {
|
||||
$this->post = DiviFixtures::givenPost($content ?? DiviFixtures::markup('synthetic-basic.html'));
|
||||
Functions\when('get_post_type_object')->justReturn((object) ['cap' => (object) ['edit_posts' => 'edit_pages', 'edit_others_posts' => 'edit_others_pages']]);
|
||||
Functions\when('get_preview_post_link')->justReturn('https://kunde.test/?page_id=7&preview=true');
|
||||
$schema = DiviFixtures::schema();
|
||||
$loader = new DiviPageLoader($schema);
|
||||
$loader = $library
|
||||
? new DiviPageLoader($schema, new Parser(), LibraryFixtures::access())
|
||||
: new DiviPageLoader($schema);
|
||||
$db = Mockery::mock(\wpdb::class)->makePartial();
|
||||
$db->allows('get_col')->andReturnUsing(function (string $sql) use ($ids): array {
|
||||
$this->queries[] = $sql;
|
||||
@@ -420,6 +427,43 @@ final class DiviReplaceTextAbilityTest extends TestCase
|
||||
self::assertSame([], $this->saved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ruling P13: without library access a search for a library ID finds nothing – the ID a global
|
||||
* instance (and its children's globalParent) stores is as good as absent; with access it is reported.
|
||||
*/
|
||||
public function testWithoutLibraryAccessLibraryIdsAreNoHits(): void
|
||||
{
|
||||
$content = DiviFixtures::markup('stage3/page--globale-instanzen.html');
|
||||
foreach (['1058', '1059', '"globalModule":"1058"', 'globalParent":"1058'] as $search) {
|
||||
$ability = $this->ability($content);
|
||||
$dry = $ability->execute(['search' => $search, 'replace' => 'x']);
|
||||
$result = $this->replaceFor($ability, ['search' => $search, 'replace' => 'x']);
|
||||
|
||||
self::assertSame([], $dry['skipped_nodes'], $search);
|
||||
self::assertSame([], $dry['matches'], $search);
|
||||
self::assertSame([], $result['skipped_nodes'], $search);
|
||||
self::assertStringNotContainsString('1058', (string) json_encode([$dry, $result]), $search);
|
||||
self::assertStringNotContainsString('1059', (string) json_encode([$dry, $result]), $search);
|
||||
self::assertSame([], $this->saved);
|
||||
}
|
||||
|
||||
$shown = $this->ability($content, false, [7], true)->execute(['search' => '1058', 'replace' => 'x']);
|
||||
self::assertSame(['g0'], array_column($shown['skipped_nodes'], 'id'));
|
||||
}
|
||||
|
||||
/** Ruling P13: text of a global instance is still reported without library access (not an ID). */
|
||||
public function testWithoutLibraryAccessGlobalTextIsStillReported(): void
|
||||
{
|
||||
$global = ['divi/text', ['globalModule' => '123', 'content' => ['innerContent' => ['desktop' => ['value' => '<p>Müller</p>']]]]];
|
||||
$ability = $this->ability(self::page([$global]));
|
||||
|
||||
$dry = $ability->execute(['search' => 'Müller', 'replace' => 'Schmidt']);
|
||||
$byId = $ability->execute(['search' => '123', 'replace' => 'x']);
|
||||
|
||||
self::assertSame(['s0.r0.c0.g0'], array_column($dry['skipped_nodes'], 'id'));
|
||||
self::assertSame([], $byId['skipped_nodes']);
|
||||
}
|
||||
|
||||
/** No effective change (search == replacement, cleaned replacement == match): nothing saved. */
|
||||
public function testNoEffectiveChangeSavesNothing(): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user