feat: lit/tb-assign – conditions with dry run on live templates, reattach

- 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>
This commit is contained in:
2026-09-27 16:28:27 +02:00
co-authored by Claude Opus 5.5
parent 2827fd4bd8
commit 0975b2f69b
8 changed files with 837 additions and 1 deletions
@@ -92,4 +92,41 @@ final class TemplateTest extends TestCase
);
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'
);
}
}