Adds per-path attribute kind (text/richtext/code/url/image/color/enum/ onoff/number/list/icon), derived from Divi's field component metadata where an attribute path names one unambiguously (module.paths() itself is unchanged; kinds() is a new, separate lookup exposed as path_kinds on lit/divi-catalog's module detail). This is not in the task-4 brief; it is added because 2b's sanitization routing (ruling R3) needs a metadata-derived field kind per attribute path. Verified live against the full 100-module catalog (564/4358 paths resolve a kind; the rest default to "unknown" and fall back to 2b's key-name routing). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
139 lines
4.3 KiB
PHP
139 lines
4.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace LIT\MCP;
|
|
|
|
use LIT\MCP\Abilities\AbilityRegistrar;
|
|
use LIT\MCP\Abilities\ExposurePolicy;
|
|
use LIT\MCP\Admin\AccessTab;
|
|
use LIT\MCP\Admin\AdminNotices;
|
|
use LIT\MCP\Admin\ConnectionRepository;
|
|
use LIT\MCP\Admin\ConnectionStatus;
|
|
use LIT\MCP\Admin\ConnectionTab;
|
|
use LIT\MCP\Admin\LimitsTab;
|
|
use LIT\MCP\Admin\LogTab;
|
|
use LIT\MCP\Admin\SettingsPage;
|
|
use LIT\MCP\Admin\SiteHealth;
|
|
use LIT\MCP\Admin\ToolsTab;
|
|
use LIT\MCP\ChangeLog\ChangeLog;
|
|
use LIT\MCP\ChangeLog\ChangeLogCleanup;
|
|
use LIT\MCP\ChangeLog\ChangeLogInstaller;
|
|
use LIT\MCP\Guides\InstructionsBuilder;
|
|
use LIT\MCP\Integrations\Core\CoreIntegration;
|
|
use LIT\MCP\Integrations\Divi\DiviIntegration;
|
|
use LIT\MCP\Integrations\IntegrationRegistry;
|
|
use LIT\MCP\Integrations\Media\MediaIntegration;
|
|
use LIT\MCP\Integrations\Pods\PodsFieldSource;
|
|
use LIT\MCP\Integrations\WordPress\Schema\ContentSchema;
|
|
use LIT\MCP\Integrations\WordPress\Schema\RegisteredMetaSource;
|
|
use LIT\MCP\Integrations\WordPress\Schema\SampledMetaSource;
|
|
use LIT\MCP\Integrations\WordPress\WordPressIntegration;
|
|
use LIT\MCP\Server\RequestContext;
|
|
use LIT\MCP\Server\ServerRegistrar;
|
|
use LIT\MCP\Server\VisibilityFilter;
|
|
|
|
/**
|
|
* Wires WP-LIT-MCP into WordPress.
|
|
*/
|
|
final class Plugin
|
|
{
|
|
public const VERSION = '0.2.0';
|
|
|
|
private static string $pluginFile = '';
|
|
private static ?SettingsPage $settingsPage = null;
|
|
|
|
public static function boot(string $pluginFile): void
|
|
{
|
|
self::$pluginFile = $pluginFile;
|
|
|
|
$missing = (new Dependencies())->missing();
|
|
if ($missing !== []) {
|
|
self::noticeMissing($missing);
|
|
return;
|
|
}
|
|
|
|
$access = new Access();
|
|
$access->register();
|
|
(new RequestContext())->register();
|
|
(new VisibilityFilter())->register();
|
|
|
|
$limits = new Limits();
|
|
$changeLog = new ChangeLog();
|
|
(new ChangeLogInstaller($changeLog))->maybeInstall();
|
|
(new ChangeLogCleanup($changeLog, $limits))->register();
|
|
|
|
$schema = self::contentSchema();
|
|
$registry = new IntegrationRegistry(
|
|
new CoreIntegration(self::pluginDir() . '/docs/guides'),
|
|
new WordPressIntegration($schema, $changeLog),
|
|
new MediaIntegration($schema, $changeLog, $limits),
|
|
new DiviIntegration($schema)
|
|
);
|
|
|
|
$policy = ExposurePolicy::fromOption();
|
|
(new AbilityRegistrar($registry, $policy))->register();
|
|
(new ServerRegistrar(
|
|
$registry,
|
|
new InstructionsBuilder($registry, static fn (): array => $schema->postTypeNames(), $policy),
|
|
null,
|
|
null,
|
|
null,
|
|
$policy
|
|
))->register();
|
|
|
|
$status = new ConnectionStatus();
|
|
(new SiteHealth($status))->register();
|
|
self::$settingsPage = new SettingsPage([
|
|
new ConnectionTab($status),
|
|
new AccessTab($access, new ConnectionRepository()),
|
|
new ToolsTab($registry, $policy),
|
|
new LogTab($changeLog, $limits),
|
|
new LimitsTab(),
|
|
]);
|
|
if (is_admin()) {
|
|
self::$settingsPage->register();
|
|
(new AdminNotices($status))->register();
|
|
}
|
|
|
|
\WPMedia\MCP\OAuth\Bootstrap::instance();
|
|
}
|
|
|
|
public static function settingsPage(): ?SettingsPage
|
|
{
|
|
return self::$settingsPage;
|
|
}
|
|
|
|
public static function pluginDir(): string
|
|
{
|
|
return dirname(self::$pluginFile);
|
|
}
|
|
|
|
/**
|
|
* @param list<string> $missing
|
|
*/
|
|
public static function noticeMissing(array $missing): void
|
|
{
|
|
add_action('admin_notices', static function () use ($missing): void {
|
|
printf(
|
|
'<div class="notice notice-error"><p>%s</p></div>',
|
|
esc_html(sprintf(
|
|
/* translators: %s: comma separated list of missing components */
|
|
__('WP-LIT-MCP ist inaktiv. Es fehlt: %s', 'wp-lit-mcp'),
|
|
implode(', ', $missing)
|
|
))
|
|
);
|
|
});
|
|
}
|
|
|
|
private static function contentSchema(): ContentSchema
|
|
{
|
|
$sources = [new RegisteredMetaSource(), new SampledMetaSource()];
|
|
if (PodsFieldSource::isAvailable()) {
|
|
array_unshift($sources, new PodsFieldSource());
|
|
}
|
|
|
|
return new ContentSchema($sources);
|
|
}
|
|
}
|