Split module structure contracts

This commit is contained in:
2026-03-19 18:30:14 +01:00
parent 1e993e470c
commit ee5fdaaff7
8 changed files with 683 additions and 711 deletions

View File

@@ -0,0 +1,83 @@
<?php
namespace MintyPHP\Tests\Architecture;
final class ModuleBoundaryContractTest extends AbstractModuleStructureContractTestCase
{
public function testModuleClassesUseModuleNamespace(): void
{
$coreNamespacePrefixes = [
'MintyPHP\\Service\\',
'MintyPHP\\Repository\\',
'MintyPHP\\Support\\',
'MintyPHP\\Http\\',
'MintyPHP\\App\\Container\\',
];
foreach (self::$modules as $module) {
$libDir = $module['path'] . '/lib';
if (!is_dir($libDir)) {
continue;
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($libDir, \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
if ($file->getExtension() !== 'php') {
continue;
}
$content = file_get_contents($file->getPathname());
if ($content === false) {
continue;
}
if (preg_match('/^namespace\s+(.+?);/m', $content, $match)) {
$namespace = $match[1];
foreach ($coreNamespacePrefixes as $corePrefix) {
self::assertFalse(
str_starts_with($namespace . '\\', $corePrefix),
"Module '{$module['id']}' class in {$file->getFilename()} uses core namespace '{$namespace}'. "
. "Module classes must use MintyPHP\\Module\\* namespace."
);
}
}
}
}
}
public function testModulePagesDoNotImportCoreAbilityConstants(): void
{
foreach (self::$modules as $module) {
$pagesDir = $module['path'] . '/pages';
if (!is_dir($pagesDir)) {
continue;
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($pagesDir)
);
foreach ($iterator as $file) {
if (!$file->isFile() || $file->getExtension() !== 'php') {
continue;
}
$content = file_get_contents($file->getPathname());
if ($content === false) {
continue;
}
self::assertStringNotContainsString(
'OperationsAuthorizationPolicy::ABILITY_',
$content,
"Module '{$module['id']}' page '{$file->getFilename()}' imports Core OperationsAuthorizationPolicy ability. "
. "Use the module's own AuthorizationPolicy instead."
);
}
}
}
}