refactor: Divi-Boot-Schritte in DiviIntegration::boot() (Bootable) – Upgrader-Hook, Prüf-Route, CLI und Reiter „Divi“ über lit_mcp_admin_tabs; IntegrationRegistry::boot() bootet jede Integration genau einmal; Prüfseiten-Aufräumen im load-Hook statt beim Rendern
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
06148fb8c1
commit
6c59934caa
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* An integration with boot steps of its own (hooks, REST routes, WP-CLI commands, admin tabs), so the composition
|
||||
* root does not need to know them. IntegrationRegistry::boot() calls boot() whether or not the integration is
|
||||
* available: Plugin boots on plugins_loaded, before the theme – isAvailable() cannot be asked yet.
|
||||
*/
|
||||
interface Bootable
|
||||
{
|
||||
/** Registers the integration's own hooks, routes, CLI commands and admin tabs. Called once by Plugin. */
|
||||
public function boot(): void;
|
||||
}
|
||||
@@ -5,7 +5,11 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Integrations\Divi;
|
||||
|
||||
use Closure;
|
||||
use LIT\MCP\Admin\DiviTab;
|
||||
use LIT\MCP\Admin\SettingsPage;
|
||||
use LIT\MCP\ChangeLog\ChangeLog;
|
||||
use LIT\MCP\Cli\DiviCheckCommand;
|
||||
use LIT\MCP\Integrations\Bootable;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\Parser;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||
use LIT\MCP\Integrations\Divi\Design\DesignSystemWriter;
|
||||
@@ -47,6 +51,9 @@ use LIT\MCP\Integrations\Divi\Pages\DiviSaver;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviUpdateAbility;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DiviWriter;
|
||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||
use LIT\MCP\Integrations\Divi\Release\CompatibilityCheck;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviCheckRoute;
|
||||
use LIT\MCP\Integrations\Divi\Release\ReleaseResolver;
|
||||
use LIT\MCP\Integrations\Divi\Schema\DiviCatalogAbility;
|
||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||
@@ -66,9 +73,9 @@ defined('ABSPATH') || exit;
|
||||
* Divi 5 pages (spec §5, Etappe 2). Only available when the Divi 5 builder is loaded
|
||||
* (spec §2 principle 4); Divi 4 is never edited (spec §3.4). The write abilities share one
|
||||
* DiviWriter; each binds the composition to its entry via DiviWriter::composition().
|
||||
* contentComposer() gives lit/content-create the Divi short form (spec §6.2).
|
||||
* contentComposer() gives lit/content-create the Divi short form (spec §6.2). boot() registers Divi's own hooks.
|
||||
*/
|
||||
final class DiviIntegration implements Integration
|
||||
final class DiviIntegration implements Integration, Bootable
|
||||
{
|
||||
private DiviModules $modules;
|
||||
private DesignSystemReader $design;
|
||||
@@ -190,6 +197,27 @@ final class DiviIntegration implements Integration
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divi's own boot steps, registered whether or not Divi is loaded yet (Bootable): a theme update checks the
|
||||
* fingerprints again at once (spec §5.4), the admin check as REST route and WP-CLI command (spec §6, §7) and
|
||||
* the tab "Divi" after the plugin's own tabs.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
// Spec §5.4: a theme update checks the Divi fingerprints again at once (the state key would, too).
|
||||
add_action('upgrader_process_complete', static function (): void {
|
||||
delete_transient(ReleaseResolver::CACHE);
|
||||
});
|
||||
|
||||
// Spec §6: the admin check runs as a REST request (same context as MCP calls). Its short form has no
|
||||
// Tools-tab gate: the check tests Divi, not this site's tool switches.
|
||||
$check = fn (): CompatibilityCheck => CompatibilityCheck::create($this->contentComposer());
|
||||
(new DiviCheckRoute($check))->register();
|
||||
DiviCheckCommand::register($check);
|
||||
|
||||
add_filter(SettingsPage::TABS_FILTER, fn (array $tabs): array => [...$tabs, new DiviTab(log: $this->log)]);
|
||||
}
|
||||
|
||||
public function abilities(): array
|
||||
{
|
||||
$loader = $this->loader();
|
||||
|
||||
@@ -16,11 +16,32 @@ final class IntegrationRegistry
|
||||
/** @var list<array{Integration, list<Ability>}>|null Available integrations with their abilities. */
|
||||
private ?array $loaded = null;
|
||||
|
||||
private bool $booted = false;
|
||||
|
||||
public function __construct(Integration ...$integrations)
|
||||
{
|
||||
$this->integrations = array_values($integrations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Boots every Bootable integration once, in registry order – available or not: Plugin boots on plugins_loaded,
|
||||
* before the theme (Divi) is loaded, so isAvailable() is not known yet (as the hooks were registered before
|
||||
* Bootable). A second call does nothing.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
if ($this->booted) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->booted = true;
|
||||
foreach ($this->integrations as $integration) {
|
||||
if ($integration instanceof Bootable) {
|
||||
$integration->boot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @return list<Integration> */
|
||||
public function available(): array
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user