refactor: DiviSaver docblocks, one diviWritable field, REASON_CREATE with the constants (M-4, M-5, M-13)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-27 04:22:04 +02:00
co-authored by Claude Opus 5.5
parent 695f7b91ac
commit a413f761e7
4 changed files with 22 additions and 20 deletions
+5 -5
View File
@@ -57,7 +57,7 @@ final class DiviIntegration implements Integration
* @param (Closure(): bool)|null $libraryVisible Tools-tab gate for library entries at all (group * @param (Closure(): bool)|null $libraryVisible Tools-tab gate for library entries at all (group
* "Divi-Bibliothek" not disabled, ruling P9); null = always. * "Divi-Bibliothek" not disabled, ruling P9); null = always.
* @param (Closure(): bool)|null $diviWritable Whether lit/divi-insert is enabled – lit/divi-node-copy * @param (Closure(): bool)|null $diviWritable Whether lit/divi-insert is enabled – lit/divi-node-copy
* follows it (ruling P9, E9); null = always. * and lit-library-insert follow it (ruling P9, E9, audit M2); null = always.
* @param (Closure(): bool)|null $libraryInsertable Whether lit/library-insert is enabled – * @param (Closure(): bool)|null $libraryInsertable Whether lit/library-insert is enabled –
* lit/divi-node-copy follows it for library entries as source (audit L5); null = always. * lit/divi-node-copy follows it for library entries as source (audit L5); null = always.
*/ */
@@ -128,10 +128,10 @@ final class DiviIntegration implements Integration
} }
/** /**
* The group "Divi-Bibliothek" (lit/library-*), sharing this integration's library access; * The group "Divi-Bibliothek" (lit/library-*), sharing this integration's library access and its
* $diviWritable is whether lit/divi-insert is enabled (lit-library-insert follows it, audit M2). * $diviWritable gate (lit-library-insert follows lit/divi-insert, audit M2).
*/ */
public function library(?Closure $diviWritable = null): LibraryIntegration public function library(): LibraryIntegration
{ {
$loader = $this->loader(); $loader = $this->loader();
@@ -143,7 +143,7 @@ final class DiviIntegration implements Integration
new DiviSaver(), new DiviSaver(),
$this->log, $this->log,
$this->modules, $this->modules,
$diviWritable $this->diviWritable
); );
} }
@@ -34,6 +34,9 @@ class DiviLibraryStore
/** Taxonomies every new entry needs (et_pb_submit_layout). */ /** Taxonomies every new entry needs (et_pb_submit_layout). */
public const TAXONOMIES = ['scope', 'layout_type', 'module_width']; public const TAXONOMIES = ['scope', 'layout_type', 'module_width'];
/** Client text when the terms or meta of a new entry could not be written. */
public const REASON_CREATE = 'Der Bibliothekseintrag konnte nicht vollständig angelegt werden.';
public function isGlobal(int $id): bool public function isGlobal(int $id): bool
{ {
if (method_exists(self::GLOBAL_LAYOUT, 'is_global_layout_template')) { if (method_exists(self::GLOBAL_LAYOUT, 'is_global_layout_template')) {
@@ -138,9 +141,6 @@ class DiviLibraryStore
]; ];
} }
/** Client text when the terms or meta of a new entry could not be written. */
public const REASON_CREATE = 'Der Bibliothekseintrag konnte nicht vollständig angelegt werden.';
/** /**
* A published entry with the terms and meta of $spec and empty content (E4; the layout follows * A published entry with the terms and meta of $spec and empty content (E4; the layout follows
* through DiviSaver::saveNew()). All or nothing through $draft (ruling P6, the transaction of * through DiviSaver::saveNew()). All or nothing through $draft (ruling P6, the transaction of
+13 -11
View File
@@ -40,18 +40,19 @@ defined('ABSPATH') || exit;
* those hooks except the content itself (already cleaned); anything a third-party hook writes * those hooks except the content itself (already cleaned); anything a third-party hook writes
* there is saved without kses, as it would be for an administrator. The rollback write in * there is saved without kses, as it would be for an administrator. The rollback write in
* restore() uses the same window with the previous stored content; saveNew() (the first layout * restore() uses the same window with the previous stored content; saveNew() (the first layout
* of a new draft, lit/content-create) uses it for its single wp_update_post(). * of a new post – a draft of lit/content-create or a library entry of lit/library-save) uses it
* for its single wp_update_post().
* *
* Divi's own save filters are NOT kses and are never removed (ruling S7, defense in depth): * Divi's own save filters are NOT kses and are never removed (ruling S7, defense in depth):
* Security::initialize() (Divi 5.2.1 Security.php:74-81) registers on wp_insert_post_data * Security::initialize() (Divi 5.2.1 Security.php:74-81) registers on wp_insert_post_data
* AttributeSecurity (priority 5, always), HtmlSecurity (priority 6, by capability) and * AttributeSecurity (priority 5, always), HtmlSecurity (priority 6, by capability) and
* DynamicContentFixes (priority 10: strips enable_html for users without unfiltered_html). The first two re-serialize * DynamicContentFixes (priority 10: strips enable_html for users without unfiltered_html). The first
* the whole page when it holds custom attributes or htmlBefore/htmlAfter/elementType, so on such * two re-serialize the whole page when it holds custom attributes or htmlBefore/htmlAfter/elementType, so on such
* pages the bytes change for every user – reported as CHANGED_ON_SAVE. Finding R2 / rulings * pages the bytes change for every user – reported as CHANGED_ON_SAVE. Finding R2 / rulings
* S5, S7: docs/superpowers/notes/2026-09-26-etappe-2-entscheidungen.md. * S5, S7: docs/superpowers/notes/2026-09-26-etappe-2-entscheidungen.md.
* *
* SaveScope: Bibliothekseinträge bekommen keine Divi-Flags; ein globaler Eintrag leert zusätzlich den CSS-Cache * SaveScope: library entries get no Divi flags; a global (or referenced) entry additionally clears
* aller Seiten und den Theme-Builder-Cache. * the static CSS of every page and the Theme Builder cache.
* *
* If saving throws, the previous content is written back (WriteFailed: rolled back or not). * If saving throws, the previous content is written back (WriteFailed: rolled back or not).
* Not final so abilities can be tested with a mock. * Not final so abilities can be tested with a mock.
@@ -131,12 +132,13 @@ class DiviSaver
} }
/** /**
* The first content of a brand-new draft (lit/content-create with divi, which inserted the * The first content of a brand-new post: a draft of lit/content-create with divi or a library
* draft with its normal WordPress fields – title and excerpt went through kses as usual). * entry of lit/library-save, both inserted with their normal WordPress fields first (title and
* Same kses window as save(), holding only this wp_update_post() and its hooks; no restore * excerpt went through kses as usual). Same kses window as save(), holding only this
* point (the draft has no earlier state) and no static CSS to clear. The Divi flags are part * wp_update_post() and its hooks; no restore point (the post has no earlier state) and no
* of the write here: without them the new entry is no Divi layout. Every failure throws – * static CSS to clear. With SaveScope::Page the Divi flags are part of the write (without them
* the caller deletes the draft (all or nothing). * a new page is no Divi layout); SaveScope::LibraryItem sets none. Every failure throws – the
* caller deletes the new post (all or nothing).
* *
* @return list<string> Warnings (CHANGED_ON_SAVE). * @return list<string> Warnings (CHANGED_ON_SAVE).
* @throws RuntimeException * @throws RuntimeException
+1 -1
View File
@@ -108,7 +108,7 @@ final class Plugin
new WordPressIntegration($schema, $changeLog, $divi->contentComposer($diviWritable)), new WordPressIntegration($schema, $changeLog, $divi->contentComposer($diviWritable)),
new MediaIntegration($schema, $changeLog, $limits), new MediaIntegration($schema, $changeLog, $limits),
$divi, $divi,
$divi->library($diviWritable) $divi->library()
); );
$policy = ExposurePolicy::fromOption()->withGroups($registry->groupMap(...)); $policy = ExposurePolicy::fromOption()->withGroups($registry->groupMap(...));