- ThemeBuilderAccess::changeableTemplate(): rights (Q18 not_found), group gate, no TB draft, never the default template, current template_rev - omitted exclude_from stays, [] clears (Q3); live dry run shows use_on and exclude_from before/after, overlaps and possible overlaps (B9) - reattach only with published layouts (B10) and a live TB post; always disabled, unmarks template and layouts; failure restores everything Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
133 lines
6.3 KiB
PHP
133 lines
6.3 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace LIT\MCP\Tests\Unit\Integrations\Divi\ThemeBuilder;
|
||
|
||
use LIT\MCP\Integrations\Divi\ThemeBuilder\Template;
|
||
use LIT\MCP\Tests\Support\ThemeBuilderFixtures;
|
||
use PHPUnit\Framework\TestCase;
|
||
|
||
final class TemplateTest extends TestCase
|
||
{
|
||
public function testReadsDivisTemplateArray(): void
|
||
{
|
||
$template = ThemeBuilderFixtures::template();
|
||
|
||
self::assertSame(1066, $template->id);
|
||
self::assertFalse($template->enabled);
|
||
self::assertSame(['id' => 1062, 'enabled' => true], $template->layouts['body']);
|
||
self::assertSame(['singular:post_type:page:id:1053'], $template->useOn);
|
||
self::assertSame(['page'], $template->postTypes());
|
||
self::assertFalse($template->isLive());
|
||
}
|
||
|
||
/** Ruling Q8/B8: Divi renders every listed, enabled template whatever its post status – fail closed. */
|
||
public function testLiveMeansAttachedAndEnabledWhateverThePostStatus(): void
|
||
{
|
||
self::assertTrue(ThemeBuilderFixtures::template(1066, ['enabled' => true])->isLive());
|
||
self::assertFalse(ThemeBuilderFixtures::template(1066, ['enabled' => true, 'attached' => false])->isLive());
|
||
self::assertFalse(ThemeBuilderFixtures::template(1066, ['attached' => true])->isLive());
|
||
self::assertTrue(ThemeBuilderFixtures::template(1066, ['enabled' => true, 'status' => 'trash'])->isLive());
|
||
self::assertTrue(ThemeBuilderFixtures::template(1066, ['enabled' => true, 'status' => 'draft'])->isLive());
|
||
self::assertTrue(ThemeBuilderFixtures::template(1066, ['enabled' => true])->showsLayout('body', 1062));
|
||
$hiddenBody = ThemeBuilderFixtures::template(1066, [
|
||
'enabled' => true,
|
||
'layouts' => [
|
||
'header' => ['id' => 1061, 'enabled' => true],
|
||
'body' => ['id' => 1062, 'enabled' => false],
|
||
'footer' => ['id' => 1063, 'enabled' => true],
|
||
],
|
||
]);
|
||
self::assertFalse($hiddenBody->showsLayout('body', 1062));
|
||
self::assertFalse(ThemeBuilderFixtures::template()->showsLayout('body', 1062), 'disabled template');
|
||
}
|
||
|
||
/** Stored as Divi stores it (stage3b/tb-template--person.json): layout IDs and flags as strings. */
|
||
public function testReadsDivisStorageTypes(): void
|
||
{
|
||
$template = Template::fromDivi([
|
||
'id' => '2394',
|
||
'title' => '[Fixture 3b] Person',
|
||
'default' => false,
|
||
'enabled' => false,
|
||
'layouts' => [
|
||
'header' => ['id' => '1061', 'enabled' => true, 'override' => true, 'global' => false],
|
||
'body' => ['id' => '2391', 'enabled' => true],
|
||
'footer' => ['id' => '0', 'enabled' => true],
|
||
],
|
||
'use_on' => ['singular:post_type:lit_fixture_person:all'],
|
||
'exclude_from' => [],
|
||
], 'publish', true, '2026-09-27 12:47:02');
|
||
|
||
self::assertSame(2394, $template->id);
|
||
self::assertSame(['id' => 1061, 'enabled' => true], $template->layouts['header']);
|
||
self::assertSame(['id' => 0, 'enabled' => true], $template->layouts['footer']);
|
||
self::assertSame(['lit_fixture_person'], $template->postTypes());
|
||
self::assertSame('2026-09-27 12:47:02', $template->toArray()['marked_unused']);
|
||
}
|
||
|
||
public function testRevChangesWithEveryField(): void
|
||
{
|
||
$rev = ThemeBuilderFixtures::template()->rev();
|
||
|
||
self::assertSame($rev, ThemeBuilderFixtures::template()->rev());
|
||
self::assertNotSame($rev, ThemeBuilderFixtures::template(1066, ['enabled' => true])->rev());
|
||
self::assertNotSame($rev, ThemeBuilderFixtures::template(1066, ['use_on' => ['homepage']])->rev());
|
||
self::assertNotSame($rev, ThemeBuilderFixtures::template(1066, ['attached' => false])->rev());
|
||
}
|
||
|
||
public function testOverlapsNameOtherLiveTemplatesWithSharedConditions(): void
|
||
{
|
||
$other = ThemeBuilderFixtures::template(1070, [
|
||
'enabled' => true,
|
||
'title' => 'Seiten',
|
||
'use_on' => ['singular:post_type:page:all', 'homepage'],
|
||
]);
|
||
$disabled = ThemeBuilderFixtures::template(1071, ['use_on' => ['homepage']]);
|
||
|
||
self::assertSame(
|
||
[['id' => 1070, 'title' => 'Seiten', 'conditions' => ['homepage']]],
|
||
Template::overlaps([$other, $disabled], 1066, ['homepage', 'search'])
|
||
);
|
||
self::assertSame([], Template::overlaps([$other], 1070, ['homepage']));
|
||
}
|
||
|
||
/** Ruling Q8/B9: conditions of the same family may overlap (Divi then picks one template). */
|
||
public function testPossibleOverlapsNameOtherLiveTemplatesOfTheSameFamily(): void
|
||
{
|
||
$pages = ThemeBuilderFixtures::template(1070, [
|
||
'enabled' => true,
|
||
'title' => 'Seiten',
|
||
'use_on' => ['singular:post_type:page:all', 'search'],
|
||
]);
|
||
$archives = ThemeBuilderFixtures::template(1071, ['enabled' => true, 'title' => 'Archive', 'use_on' => ['archive:all']]);
|
||
$inTerm = ThemeBuilderFixtures::template(1072, [
|
||
'enabled' => true,
|
||
'title' => 'Beiträge einer Kategorie',
|
||
'use_on' => ['singular:taxonomy:category:term:id:5'],
|
||
]);
|
||
$disabled = ThemeBuilderFixtures::template(1073, ['use_on' => ['singular:post_type:page:all']]);
|
||
$live = [$pages, $archives, $inTerm, $disabled];
|
||
|
||
self::assertSame(
|
||
[
|
||
['id' => 1070, 'title' => 'Seiten', 'conditions' => ['singular:post_type:page:all']],
|
||
['id' => 1072, 'title' => 'Beiträge einer Kategorie', 'conditions' => ['singular:taxonomy:category:term:id:5']],
|
||
],
|
||
Template::possibleOverlaps($live, 1066, ['singular:post_type:page:id:1053'])
|
||
);
|
||
self::assertSame(
|
||
[['id' => 1071, 'title' => 'Archive', 'conditions' => ['archive:all']]],
|
||
Template::possibleOverlaps($live, 1066, ['archive:taxonomy:category:term:id:5'])
|
||
);
|
||
self::assertSame([], Template::possibleOverlaps($live, 1066, ['search']), 'identical ones are overlaps()');
|
||
self::assertSame([], Template::possibleOverlaps($live, 1066, ['404']));
|
||
self::assertSame(
|
||
['id' => 1070, 'title' => 'Seiten', 'conditions' => ['singular:post_type:page:all']],
|
||
Template::possibleOverlaps($live, 1066, ['homepage'])[0],
|
||
'a static front page is a page'
|
||
);
|
||
}
|
||
}
|