DiviThemeBuilder wraps Divi's Theme Builder: reads through Divi's functions, writes layouts/templates through insert_layout/store_template behind a wp_die guard (edit_others_posts and function checks first, every handler filter and output buffer restored in finally), list/conditions/enabled mirrored from Divi's own save. Template: live = attached and enabled, whatever the post status (ruling Q8/B8). ThemeBuilderAccess: edit_others_posts plus Divi's theme_builder role, hidden IDs answer like missing ones, canEditTemplate (B11) and layoutsRefusal (B10). DiviCompatibility checks the Theme Builder functions and post types (E15). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
108 lines
4.4 KiB
PHP
108 lines
4.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace LIT\MCP\Integrations\Divi;
|
|
|
|
use LIT\MCP\Integrations\Divi\BlockTree\GlobalInstance;
|
|
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
|
use LIT\MCP\Integrations\Divi\Pages\DynamicContentMap;
|
|
use LIT\MCP\Integrations\Divi\Schema\DiviModules;
|
|
use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
|
use Throwable;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
/**
|
|
* Live check of the Divi internals LIT MCP relies on (decisions note §5, E15): classes,
|
|
* functions, the library post type and taxonomies, the instance block type. lit-site-status shows
|
|
* the failed checks, so a Divi update that moves one of them is visible before a tool reports
|
|
* "unsupported".
|
|
*/
|
|
final class DiviCompatibility
|
|
{
|
|
/** @param array<string, callable(): bool>|null $checks Label => check; null = defaults(). */
|
|
public function __construct(private ?array $checks = null)
|
|
{
|
|
}
|
|
|
|
/** @return list<string> Labels of the checks that failed or threw. */
|
|
public function problems(): array
|
|
{
|
|
$problems = [];
|
|
foreach ($this->checks ?? self::defaults() as $label => $check) {
|
|
try {
|
|
$ok = (bool) $check();
|
|
} catch (Throwable) {
|
|
$ok = false;
|
|
}
|
|
if (! $ok) {
|
|
$problems[] = (string) $label;
|
|
}
|
|
}
|
|
|
|
return $problems;
|
|
}
|
|
|
|
/** @return array<string, callable(): bool> */
|
|
public static function defaults(): array
|
|
{
|
|
return [
|
|
'ModuleRegistration (Modul-Katalog)' => static fn (): bool => DiviModules::isAvailable(),
|
|
'DynamicContentOptions (Dynamic Content)' =>
|
|
static fn (): bool => class_exists(DynamicContentMap::REGISTRY),
|
|
'et_pb_is_allowed (Divi-Rollen)' => static fn (): bool => function_exists('et_pb_is_allowed'),
|
|
'Post-Typ et_pb_layout (Bibliothek)' =>
|
|
static fn (): bool => post_type_exists(DiviLibraryStore::POST_TYPE),
|
|
'Taxonomien scope, layout_type, module_width (Bibliothek)' =>
|
|
static fn (): bool => (new DiviLibraryStore())->missingTaxonomies() === [],
|
|
'GlobalLayout::is_global_layout_template (globale Module)' =>
|
|
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'),
|
|
'et_theme_builder_clear_wp_cache (Theme-Builder-Cache)' =>
|
|
static fn (): bool => function_exists('et_theme_builder_clear_wp_cache'),
|
|
'Block-Typ divi/global-layout (Instanzen globaler Module)' =>
|
|
static fn (): bool => self::knowsGlobalLayout(),
|
|
'Taxonomien layout_category, layout_tag (Bibliothek)' =>
|
|
static fn (): bool => taxonomy_exists('layout_category') && taxonomy_exists('layout_tag'),
|
|
'Theme Builder: Funktionen et_theme_builder_* und et_()' =>
|
|
static fn (): bool => (new DiviThemeBuilder())->missing() === [],
|
|
'Theme Builder: Post-Typen et_template und Layouts' => static fn (): bool => array_filter(
|
|
array_merge(
|
|
[DiviThemeBuilder::THEME_BUILDER, DiviThemeBuilder::TEMPLATE],
|
|
array_values(DiviThemeBuilder::LAYOUT_TYPES)
|
|
),
|
|
static fn (string $type): bool => ! post_type_exists($type)
|
|
) === [],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|