fix: TB dry runs hide uneditable live templates, off-switch despite draft (rulings Q20, Q21)

- ThemeBuilderAccess::editableLiveTemplates() shared by tb-list and the tb-assign/tb-activate dry runs;
  uneditable live templates only as a count (hidden_overlaps, hidden_live)
- tb-activate enabled:false works while the Theme Builder has a draft, with a warning
- possible_overlaps skips identical conditions; reattach records the previous enabled state;
  exclude_from must be a list; tb-activate live from the read-back

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-27 20:55:53 +02:00
co-authored by Claude Opus 5.5
parent 64fc439cb2
commit a31d4340f9
11 changed files with 355 additions and 37 deletions
@@ -129,4 +129,39 @@ final class TemplateTest extends TestCase
'a static front page is a page'
);
}
/** Fix round 1: a condition the template shares exactly is in overlaps() only, never twice. */
public function testPossibleOverlapsSkipIdenticalConditions(): void
{
$other = ThemeBuilderFixtures::template(1070, [
'enabled' => true,
'title' => 'Seiten',
'use_on' => ['homepage', 'singular:post_type:page:all'],
]);
$useOn = ['homepage', 'singular:post_type:page:id:1053'];
self::assertSame(['homepage'], Template::overlaps([$other], 1066, $useOn)[0]['conditions']);
self::assertSame(['singular:post_type:page:all'], Template::possibleOverlaps([$other], 1066, $useOn)[0]['conditions']);
}
/** Ruling Q21: overlapping templates the user may not edit only as a number. */
public function testOverlapDetailsCountHiddenTemplatesOnly(): void
{
$mine = ThemeBuilderFixtures::template(1070, ['enabled' => true, 'title' => 'Meine', 'use_on' => ['search']]);
$hiddenExact = ThemeBuilderFixtures::template(1071, ['enabled' => true, 'use_on' => ['search', 'homepage']]);
$hiddenPossible = ThemeBuilderFixtures::template(1072, ['enabled' => true, 'use_on' => ['singular:post_type:page:all']]);
$hiddenOther = ThemeBuilderFixtures::template(1073, ['enabled' => true, 'use_on' => ['404']]);
$details = Template::overlapDetails(
['templates' => [$mine], 'hidden' => [$hiddenExact, $hiddenPossible, $hiddenOther]],
1066,
['search', 'homepage']
);
self::assertSame([['id' => 1070, 'title' => 'Meine', 'conditions' => ['search']]], $details['overlaps']);
self::assertSame([], $details['possible_overlaps']);
self::assertSame(2, $details['hidden_overlaps']);
self::assertStringContainsString('ohne Berechtigung', Template::hiddenOverlapsNote(2));
self::assertSame('', Template::hiddenOverlapsNote(0));
}
}