From b389f983def941daba05eea2e865febd1b2e430e Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Sun, 27 Sep 2026 00:44:31 +0200 Subject: [PATCH] feat: render summary notes global modules it cannot show (F8) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7 --- .../Render/PageRenderSummaryAbility.php | 28 ++++++++++++++++- .../Render/PageRenderSummaryAbilityTest.php | 31 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php b/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php index 67be670..b111c95 100644 --- a/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php +++ b/src/Integrations/WordPress/Render/PageRenderSummaryAbility.php @@ -19,6 +19,9 @@ defined('ABSPATH') || exit; */ final class PageRenderSummaryAbility implements Ability { + /** At most this many global-module notes per summary. */ + private const GLOBAL_NOTES = 20; + public function __construct(private ContentSchema $schema, private PageRenderer $renderer) { } @@ -40,7 +43,8 @@ final class PageRenderSummaryAbility implements Ability . 'Alt-Texte). Header, Footer und Theme-Builder-Vorlagen sind nicht enthalten. Das Rendern führt die ' . 'üblichen Inhalts-Filter aus (Shortcodes, Divi, andere Plugins) und kann dabei Netzwerkanfragen ' . 'auslösen, z. B. oEmbed-Abrufe, die von WordPress oder anderen Plugins zwischengespeichert werden. ' - . 'Gut zum Prüfen nach Änderungen.'; + . 'Gut zum Prüfen nach Änderungen. Globale Module (Divi-Bibliothek) fehlen im Auszug und werden ' + . 'unter notes genannt.'; } public function inputSchema(): array @@ -104,10 +108,32 @@ final class PageRenderSummaryAbility implements Ability $notes[] = 'Der Eintrag ist passwortgeschützt; Besucher sehen zuerst das Passwortformular.'; } + foreach (array_slice(self::globalModuleIds((string) $post->post_content), 0, self::GLOBAL_NOTES) as $id) { + $notes[] = sprintf( + 'Globales Modul %s ist im Auszug nicht enthalten (beim Aufruf über die Schnittstelle rendert Divi ' + . 'globale Module nicht); Inhalt mit lit-divi-outline mit post_id %s lesen.', + $id, + $id + ); + } + return array_merge( ['post_id' => (int) $post->ID, 'url' => (string) get_permalink($post)], RenderSummary::fromHtml($this->renderer->render($post)), ['notes' => $notes] ); } + + /** + * IDs of the global modules in $content, found the way Divi finds them (a string scan for + * "globalModule", BlockParserStore::get_global_layout_content – parse_blocks() is unreliable there). + * + * @return list + */ + private static function globalModuleIds(string $content): array + { + preg_match_all('/"globalModule":"?(\d+)"?/', $content, $matches); + + return array_values(array_unique($matches[1])); + } } diff --git a/tests/Unit/Integrations/WordPress/Render/PageRenderSummaryAbilityTest.php b/tests/Unit/Integrations/WordPress/Render/PageRenderSummaryAbilityTest.php index 62d4d8b..e154723 100644 --- a/tests/Unit/Integrations/WordPress/Render/PageRenderSummaryAbilityTest.php +++ b/tests/Unit/Integrations/WordPress/Render/PageRenderSummaryAbilityTest.php @@ -8,6 +8,8 @@ use Brain\Monkey\Functions; use LIT\MCP\Integrations\WordPress\Render\PageRenderer; use LIT\MCP\Integrations\WordPress\Render\PageRenderSummaryAbility; use LIT\MCP\Integrations\WordPress\Render\RenderSummary; +use LIT\MCP\Integrations\WordPress\Schema\ContentSchema; +use LIT\MCP\Tests\Support\DiviFixtures; use LIT\MCP\Tests\Support\SchemaFixture; use LIT\MCP\Tests\Unit\TestCase; use Mockery; @@ -138,4 +140,33 @@ final class PageRenderSummaryAbilityTest extends TestCase self::assertTrue($ability->isDirect()); self::assertTrue($ability->annotations()['readonly']); } + + public function testNotesEveryGlobalModuleTheSummaryCannotShow(): void + { + $content = DiviFixtures::markup('stage3/page--globale-instanzen.html'); + $post = new WP_Post(['ID' => 7, 'post_type' => 'page', 'post_status' => 'draft', 'post_content' => $content]); + Functions\when('get_post')->justReturn($post); + Functions\when('current_user_can')->justReturn(true); + Functions\when('get_permalink')->justReturn('https://kunde.test/?page_id=7'); + $renderer = Mockery::mock(PageRenderer::class); + $renderer->allows('render')->andReturn('

Text

'); + $ability = new PageRenderSummaryAbility(SchemaFixture::managed(), $renderer); + + $notes = $ability->execute(['post_id' => 7])['notes']; + + $globals = array_values(array_filter($notes, static fn (string $note): bool => str_starts_with($note, 'Globales Modul'))); + self::assertCount(2, $globals); + self::assertStringContainsString('Globales Modul 1058 ist im Auszug nicht enthalten', $globals[0]); + self::assertStringContainsString('lit-divi-outline mit post_id 1059', $globals[1]); + } + + public function testLibraryEntriesAreNoManagedContent(): void + { + Functions\when('get_post')->justReturn(new WP_Post(['ID' => 1058, 'post_type' => 'et_pb_layout'])); + $schema = Mockery::mock(ContentSchema::class); + $schema->allows('isManaged')->with('et_pb_layout')->andReturn(false); + $ability = new PageRenderSummaryAbility($schema, Mockery::mock(PageRenderer::class)); + + self::assertToolError($ability->permission(['post_id' => 1058]), 'not_found'); + } }