forked from fa/breadcrumb-the-shire
refactor: simplify module platform — drop custom autoloader, layout_capabilities indirection, and absolute template paths
- Replace ModuleAutoloader with Composer ClassLoader (addPsr4 via spl_autoload_functions) - Eliminate layout_capabilities mapping; UI slots reference ability strings directly - Resolve relative template paths in ModuleRegistry instead of baking __DIR__ into manifests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -229,38 +229,21 @@ final class ModuleStructureContractTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Layout capabilities ─────────────────────────────────────────
|
||||
// ─── UI slot abilities ──────────────────────────────────────────
|
||||
|
||||
public function testLayoutCapabilitiesHaveNonEmptyKeysAndAbilities(): void
|
||||
/**
|
||||
* Every 'permission' value in a module's UI slots must reference an ability
|
||||
* declared as a constant on one of the module's authorization policies.
|
||||
*/
|
||||
public function testUiSlotAbilitiesMatchPolicySupports(): void
|
||||
{
|
||||
foreach (self::$modules as $module) {
|
||||
foreach ($module['manifest']->layoutCapabilities as $uiKey => $ability) {
|
||||
self::assertNotEmpty(
|
||||
trim((string) $uiKey),
|
||||
"Module '{$module['id']}' has empty layout_capabilities key"
|
||||
);
|
||||
self::assertNotEmpty(
|
||||
trim((string) $ability),
|
||||
"Module '{$module['id']}' layout_capabilities key '{$uiKey}' has empty ability"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testLayoutCapabilityAbilitiesMatchPolicySupports(): void
|
||||
{
|
||||
foreach (self::$modules as $module) {
|
||||
if (empty($module['manifest']->layoutCapabilities)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Collect all abilities supported by this module's policies
|
||||
$supportedAbilities = [];
|
||||
foreach ($module['manifest']->authorizationPolicies as $policyClass) {
|
||||
if (!class_exists($policyClass)) {
|
||||
continue;
|
||||
}
|
||||
// Check each layout capability ability against this policy
|
||||
$reflection = new \ReflectionClass($policyClass);
|
||||
foreach ($reflection->getConstants() as $constValue) {
|
||||
if (is_string($constValue)) {
|
||||
@@ -269,13 +252,28 @@ final class ModuleStructureContractTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($module['manifest']->layoutCapabilities as $uiKey => $ability) {
|
||||
self::assertContains(
|
||||
$ability,
|
||||
$supportedAbilities,
|
||||
"Module '{$module['id']}' layout_capabilities['{$uiKey}'] references ability '{$ability}' "
|
||||
. "but no module authorization policy declares it as a constant"
|
||||
);
|
||||
if ($supportedAbilities === []) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check every permission value from UI slots
|
||||
foreach ($module['manifest']->uiSlots as $slotName => $contributions) {
|
||||
$contributionList = is_array($contributions) ? $contributions : [$contributions];
|
||||
foreach ($contributionList as $idx => $contribution) {
|
||||
if (!is_array($contribution)) {
|
||||
continue;
|
||||
}
|
||||
$ability = trim((string) ($contribution['permission'] ?? ''));
|
||||
if ($ability === '') {
|
||||
continue;
|
||||
}
|
||||
self::assertContains(
|
||||
$ability,
|
||||
$supportedAbilities,
|
||||
"Module '{$module['id']}' ui_slots['{$slotName}'][{$idx}] permission '{$ability}' "
|
||||
. "is not declared as a constant on any module authorization policy"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,9 +408,14 @@ final class ModuleStructureContractTest extends TestCase
|
||||
if ($template === null) {
|
||||
continue;
|
||||
}
|
||||
// Resolve relative paths against module basePath
|
||||
$templatePath = (string) $template;
|
||||
if (!str_starts_with($templatePath, '/')) {
|
||||
$templatePath = $module['manifest']->basePath . '/' . $templatePath;
|
||||
}
|
||||
self::assertFileExists(
|
||||
(string) $template,
|
||||
"Module '{$module['id']}' {$slotName} {$templateKey} does not exist: {$template}"
|
||||
$templatePath,
|
||||
"Module '{$module['id']}' {$slotName} {$templateKey} does not exist: {$templatePath}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user