refactor: Divi catalog adapter with manifest
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,7 @@ final class DiviCompatibility
|
||||
static fn (): bool => method_exists(DiviLibraryStore::GLOBAL_LAYOUT, 'is_global_layout_template'),
|
||||
'ET_Core_PageResource (CSS-Cache)' => static fn (): bool => class_exists('ET_Core_PageResource'),
|
||||
'Block-Typ divi/global-layout (Instanzen globaler Module)' =>
|
||||
static fn (): bool => self::knowsGlobalLayout(),
|
||||
static fn (): bool => DiviModules::knowsBlock(GlobalInstance::BLOCK),
|
||||
'Taxonomien layout_category, layout_tag (Bibliothek)' =>
|
||||
static fn (): bool => taxonomy_exists('layout_category') && taxonomy_exists('layout_tag'),
|
||||
// Includes et_theme_builder_clear_wp_cache (Theme Builder cache of every site-wide clear, review M-2).
|
||||
@@ -72,32 +72,4 @@ final class DiviCompatibility
|
||||
) === [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether Divi still has the block type of global instances (GlobalInstance::BLOCK): registered
|
||||
* with WordPress, or in Divi's core module metadata (Divi renders instances itself, BlockParser,
|
||||
* and does not always register the type with WordPress).
|
||||
*/
|
||||
private static function knowsGlobalLayout(): bool
|
||||
{
|
||||
if (
|
||||
class_exists('WP_Block_Type_Registry')
|
||||
&& \WP_Block_Type_Registry::get_instance()->is_registered(GlobalInstance::BLOCK)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$registration = 'ET\Builder\Packages\ModuleLibrary\ModuleRegistration';
|
||||
if (! method_exists($registration, 'get_all_core_modules_metadata')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ((array) $registration::get_all_core_modules_metadata() as $module) {
|
||||
if (is_array($module) && ($module['name'] ?? null) === GlobalInstance::BLOCK) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,16 @@ namespace LIT\MCP\Integrations\Divi\Pages;
|
||||
use Closure;
|
||||
use LIT\MCP\Integrations\Divi\Compose\Placeholders;
|
||||
use LIT\MCP\Integrations\Divi\Compose\DynamicContentRules;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Log;
|
||||
use Throwable;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* DynamicContentRules' dynamic content allow map (ruling S22) from Divi's live registry
|
||||
* Adapter "Katalog" (spec §3): DynamicContentRules' dynamic content allow map (ruling S22) from Divi's live registry
|
||||
* DynamicContentOptions::get_options($postId, 'edit') – the options the Visual Builder offers
|
||||
* for this entry (filter divi_module_dynamic_content_options; the list depends on the post:
|
||||
* post_categories/post_tags only for types with those taxonomies). Shape:
|
||||
@@ -29,9 +32,9 @@ defined('ABSPATH') || exit;
|
||||
*
|
||||
* Not final so abilities can be tested with a fake registry.
|
||||
*/
|
||||
class DynamicContentMap
|
||||
class DynamicContentMap implements DiviAdapter
|
||||
{
|
||||
/** Divi's dynamic-content registry class; also checked by DiviCompatibility. */
|
||||
/** Divi's dynamic-content registry class; listed in manifest(). */
|
||||
public const REGISTRY = 'ET\Builder\Packages\Module\Layout\Components\DynamicContent\DynamicContentOptions';
|
||||
|
||||
/**
|
||||
@@ -41,6 +44,11 @@ class DynamicContentMap
|
||||
{
|
||||
}
|
||||
|
||||
public static function manifest(): Manifest
|
||||
{
|
||||
return new Manifest(Manifest::CATALOG, calls: [new Call(self::REGISTRY . '::get_options', 2)]);
|
||||
}
|
||||
|
||||
/** @return array<string, array<string, string>>|null Null = use DynamicContentRules' default map. */
|
||||
public function forPost(int $postId): ?array
|
||||
{
|
||||
|
||||
@@ -4,13 +4,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace LIT\MCP\Integrations\Divi\Release;
|
||||
|
||||
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
||||
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/** The Divi boundary (spec §3): the only classes that touch Divi, in the order reports list them. */
|
||||
final class DiviAdapters
|
||||
{
|
||||
/** @var list<class-string<DiviAdapter>> */
|
||||
public const CLASSES = [];
|
||||
public const CLASSES = [
|
||||
DiviModules::class,
|
||||
DynamicContentMap::class,
|
||||
];
|
||||
|
||||
/** @return array<class-string<DiviAdapter>, Manifest> */
|
||||
public static function manifests(): array
|
||||
|
||||
@@ -5,17 +5,51 @@ declare(strict_types=1);
|
||||
namespace LIT\MCP\Integrations\Divi\Schema;
|
||||
|
||||
use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
|
||||
use LIT\MCP\Integrations\Divi\BlockTree\GlobalInstance;
|
||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* Reads Divi's module metadata once per request (Divi 5 only). Not final so abilities can be
|
||||
* unit-tested with a mock.
|
||||
* Adapter "Katalog" (spec §3): Divi's module metadata once per request (Divi 5 only), Divi's own post types and
|
||||
* its per-type builder switch for the content tools, and whether Divi knows a block type. Not final so abilities
|
||||
* can be unit-tested with a mock.
|
||||
*/
|
||||
class DiviModules
|
||||
class DiviModules implements DiviAdapter
|
||||
{
|
||||
/** Divi's own post types the content tools leave alone (library, Theme Builder, canvases, speculation). */
|
||||
public const INTERNAL_POST_TYPES = [
|
||||
DiviLibraryStore::POST_TYPE,
|
||||
DiviThemeBuilder::THEME_BUILDER,
|
||||
DiviThemeBuilder::TEMPLATE,
|
||||
DiviThemeBuilder::LAYOUT_TYPES['header'],
|
||||
DiviThemeBuilder::LAYOUT_TYPES['body'],
|
||||
DiviThemeBuilder::LAYOUT_TYPES['footer'],
|
||||
'et_pb_canvas',
|
||||
'_et_pb_speculation',
|
||||
];
|
||||
|
||||
private ?ModuleCatalog $catalog = null;
|
||||
|
||||
public static function manifest(): Manifest
|
||||
{
|
||||
return new Manifest(
|
||||
Manifest::CATALOG,
|
||||
calls: [
|
||||
new Call(ModuleRegistration::class . '::get_all_core_modules_metadata', 0),
|
||||
new Call(ModuleRegistration::class . '::get_default_attrs', 2),
|
||||
new Call('et_builder_enabled_for_post_type', 1),
|
||||
],
|
||||
constants: ['ET_BUILDER_PRODUCT_VERSION'],
|
||||
blockTypes: [GlobalInstance::BLOCK],
|
||||
keys: ['et_pb_canvas', '_et_pb_speculation']
|
||||
);
|
||||
}
|
||||
|
||||
public static function isAvailable(): bool
|
||||
{
|
||||
return class_exists(ModuleRegistration::class);
|
||||
@@ -43,4 +77,35 @@ class DiviModules
|
||||
{
|
||||
return defined('ET_BUILDER_PRODUCT_VERSION') ? (string) ET_BUILDER_PRODUCT_VERSION : '5.2.1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether Divi's builder is switched on for $postType (Divi → Theme-Optionen → Builder); false without Divi.
|
||||
*/
|
||||
public static function builderEnabledFor(string $postType): bool
|
||||
{
|
||||
return function_exists('et_builder_enabled_for_post_type')
|
||||
&& (bool) et_builder_enabled_for_post_type($postType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether Divi still has block type $name: registered with WordPress, or in Divi's core module metadata (Divi
|
||||
* renders global instances itself and does not always register the type with WordPress).
|
||||
*/
|
||||
public static function knowsBlock(string $name): bool
|
||||
{
|
||||
if (class_exists('WP_Block_Type_Registry') && \WP_Block_Type_Registry::get_instance()->is_registered($name)) {
|
||||
return true;
|
||||
}
|
||||
if (! self::isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ((array) ModuleRegistration::get_all_core_modules_metadata() as $module) {
|
||||
if (is_array($module) && ($module['name'] ?? null) === $name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user