refactor: Divi design adapter, logo lookup moves out of media
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,24 +6,45 @@ namespace LIT\MCP\Integrations\Divi\Design;
|
|||||||
|
|
||||||
use ET\Builder\Packages\GlobalData\GlobalData;
|
use ET\Builder\Packages\GlobalData\GlobalData;
|
||||||
use ET\Builder\Packages\GlobalData\GlobalPreset;
|
use ET\Builder\Packages\GlobalData\GlobalPreset;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapter;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the design system from Divi's own APIs once per request (spec §2 principle 2 – no
|
* Adapter "Designsystem" (spec §3): reads the design system from Divi's own APIs
|
||||||
* copy is ever stored). Not final so abilities can be unit-tested with a mock.
|
* once per request (spec §2 principle 2 – no copy is ever stored), and the logo of
|
||||||
|
* Divi's theme options. Not final so abilities can be unit-tested with a mock.
|
||||||
*/
|
*/
|
||||||
class DesignSystemReader
|
class DesignSystemReader implements DiviAdapter
|
||||||
{
|
{
|
||||||
|
/** Divi's theme options (one array option); customizer colors, fonts and
|
||||||
|
* the logo live there. */
|
||||||
|
private const OPTIONS = 'et_divi';
|
||||||
|
|
||||||
private ?DesignSystem $designSystem = null;
|
private ?DesignSystem $designSystem = null;
|
||||||
|
|
||||||
|
public static function manifest(): Manifest
|
||||||
|
{
|
||||||
|
return new Manifest(
|
||||||
|
Manifest::DESIGN,
|
||||||
|
calls: [
|
||||||
|
new Call(GlobalData::class . '::get_global_colors', 0),
|
||||||
|
new Call(GlobalData::class . '::get_global_variables', 0),
|
||||||
|
new Call(GlobalPreset::class . '::get_data', 0),
|
||||||
|
],
|
||||||
|
keys: [self::OPTIONS]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function read(): DesignSystem
|
public function read(): DesignSystem
|
||||||
{
|
{
|
||||||
if ($this->designSystem === null) {
|
if ($this->designSystem === null) {
|
||||||
$colors = GlobalData::get_global_colors();
|
$colors = GlobalData::get_global_colors();
|
||||||
$variables = GlobalData::get_global_variables();
|
$variables = GlobalData::get_global_variables();
|
||||||
$presets = GlobalPreset::get_data();
|
$presets = GlobalPreset::get_data();
|
||||||
$options = get_option('et_divi', []);
|
$options = get_option(self::OPTIONS, []);
|
||||||
$this->designSystem = DesignSystem::fromDivi(
|
$this->designSystem = DesignSystem::fromDivi(
|
||||||
is_array($colors) ? $colors : [],
|
is_array($colors) ? $colors : [],
|
||||||
is_array($variables) ? $variables : [],
|
is_array($variables) ? $variables : [],
|
||||||
@@ -34,4 +55,15 @@ class DesignSystemReader
|
|||||||
|
|
||||||
return $this->designSystem;
|
return $this->designSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The logo URL of Divi's theme options (Divi → Theme-Optionen → Logo),
|
||||||
|
* '' when none is set. */
|
||||||
|
public static function diviLogo(): string
|
||||||
|
{
|
||||||
|
$options = get_option(self::OPTIONS);
|
||||||
|
|
||||||
|
return is_array($options) && is_string($options['divi_logo'] ?? null)
|
||||||
|
? $options['divi_logo']
|
||||||
|
: '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace LIT\MCP\Integrations\Divi\Release;
|
namespace LIT\MCP\Integrations\Divi\Release;
|
||||||
|
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||||
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
use LIT\MCP\Integrations\Divi\Library\DiviLibraryStore;
|
||||||
use LIT\MCP\Integrations\Divi\Library\DiviRoles;
|
use LIT\MCP\Integrations\Divi\Library\DiviRoles;
|
||||||
use LIT\MCP\Integrations\Divi\Pages\DiviPages;
|
use LIT\MCP\Integrations\Divi\Pages\DiviPages;
|
||||||
@@ -13,7 +14,8 @@ use LIT\MCP\Integrations\Divi\ThemeBuilder\DiviThemeBuilder;
|
|||||||
|
|
||||||
defined('ABSPATH') || exit;
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
/** The Divi boundary (spec §3): the only classes that touch Divi, in the order reports list them. */
|
/** The Divi boundary (spec §3): the only classes that touch Divi, in the order
|
||||||
|
* reports list them. */
|
||||||
final class DiviAdapters
|
final class DiviAdapters
|
||||||
{
|
{
|
||||||
/** @var list<class-string<DiviAdapter>> */
|
/** @var list<class-string<DiviAdapter>> */
|
||||||
@@ -22,6 +24,7 @@ final class DiviAdapters
|
|||||||
DiviLibraryStore::class,
|
DiviLibraryStore::class,
|
||||||
DiviRoles::class,
|
DiviRoles::class,
|
||||||
DiviThemeBuilder::class,
|
DiviThemeBuilder::class,
|
||||||
|
DesignSystemReader::class,
|
||||||
DiviModules::class,
|
DiviModules::class,
|
||||||
DynamicContentMap::class,
|
DynamicContentMap::class,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace LIT\MCP\Integrations\Media;
|
namespace LIT\MCP\Integrations\Media;
|
||||||
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||||
use LIT\MCP\Integrations\WordPress\PostStatuses;
|
use LIT\MCP\Integrations\WordPress\PostStatuses;
|
||||||
use LIT\MCP\Log;
|
use LIT\MCP\Log;
|
||||||
|
|
||||||
@@ -256,10 +257,14 @@ class MediaUsageFinder
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$divi = get_option('et_divi');
|
$diviLogo = DesignSystemReader::diviLogo();
|
||||||
$diviLogo = is_array($divi) && is_string($divi['divi_logo'] ?? null) ? $divi['divi_logo'] : '';
|
|
||||||
if ($diviLogo !== '' && ContentMediaReferences::matches($fileRegex, $diviLogo) !== false) {
|
if ($diviLogo !== '' && ContentMediaReferences::matches($fileRegex, $diviLogo) !== false) {
|
||||||
$found['site:divi_logo'] = self::siteUsage('Divi-Logo', 'option', 'divi_logo', self::POSSIBLE);
|
$found['site:divi_logo'] = self::siteUsage(
|
||||||
|
'Divi-Logo',
|
||||||
|
'option',
|
||||||
|
'divi_logo',
|
||||||
|
self::POSSIBLE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addWidgetUsages($found, $attachmentId, $fileRegex);
|
$this->addWidgetUsages($found, $attachmentId, $fileRegex);
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace LIT\MCP\Tests\Unit\Integrations\Divi\Design;
|
||||||
|
|
||||||
|
use Brain\Monkey\Functions;
|
||||||
|
use LIT\MCP\Integrations\Divi\Design\DesignSystemReader;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\Call;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\DiviAdapters;
|
||||||
|
use LIT\MCP\Integrations\Divi\Release\Manifest;
|
||||||
|
use LIT\MCP\Tests\Unit\TestCase;
|
||||||
|
|
||||||
|
final class DesignSystemReaderTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testIsTheRegisteredDesignAdapter(): void
|
||||||
|
{
|
||||||
|
$manifest = DesignSystemReader::manifest();
|
||||||
|
|
||||||
|
self::assertContains(DesignSystemReader::class, DiviAdapters::CLASSES);
|
||||||
|
self::assertSame(Manifest::DESIGN, $manifest->area);
|
||||||
|
self::assertSame(
|
||||||
|
['GlobalData::get_global_colors()', 'GlobalData::get_global_variables()',
|
||||||
|
'GlobalPreset::get_data()'],
|
||||||
|
array_map(static fn (Call $call): string => $call->label(), $manifest->calls)
|
||||||
|
);
|
||||||
|
self::assertSame(['et_divi'], $manifest->keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDiviLogoReadsTheThemeOptions(): void
|
||||||
|
{
|
||||||
|
Functions\when('get_option')->alias(
|
||||||
|
static fn (string $name): mixed => $name === 'et_divi' ?
|
||||||
|
['divi_logo' => 'https://k.de/logo.svg'] : false
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertSame('https://k.de/logo.svg', DesignSystemReader::diviLogo());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDiviLogoIsEmptyWithoutOptions(): void
|
||||||
|
{
|
||||||
|
Functions\when('get_option')->justReturn(false);
|
||||||
|
|
||||||
|
self::assertSame('', DesignSystemReader::diviLogo());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,13 +20,12 @@ use ReflectionClass;
|
|||||||
final class DiviBoundaryTest extends TestCase
|
final class DiviBoundaryTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Files that still touch Divi outside an adapter (paths below src/). Tasks 3–7 shrink this list to
|
* Files that still touch Divi outside an adapter (paths below src/). Tasks 3–7
|
||||||
* DiviCompatibility.php; Task 8 removes it together with testLegacyFilesStillTouchDivi.
|
* shrink this list to DiviCompatibility.php; Task 8 removes it together with
|
||||||
|
* testLegacyFilesStillTouchDivi.
|
||||||
*/
|
*/
|
||||||
private const LEGACY = [
|
private const LEGACY = [
|
||||||
'Integrations/Divi/Design/DesignSystemReader.php',
|
|
||||||
'Integrations/Divi/DiviCompatibility.php',
|
'Integrations/Divi/DiviCompatibility.php',
|
||||||
'Integrations/Media/MediaUsageFinder.php',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public function testOnlyAdaptersTouchDivi(): void
|
public function testOnlyAdaptersTouchDivi(): void
|
||||||
|
|||||||
Reference in New Issue
Block a user