New contracts enforce repository layer isolation, no HTML in services, no DB calls in views, module session key prefixes, and asset versioning. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
65 lines
2.2 KiB
PHP
65 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace MintyPHP\Tests\Architecture;
|
|
|
|
/**
|
|
* Module code must prefix session keys with "module.<id>." to prevent
|
|
* collisions between modules and with core session state.
|
|
*/
|
|
final class ModuleSessionKeyPrefixContractTest extends AbstractModuleStructureContractTestCase
|
|
{
|
|
/**
|
|
* Pattern matches direct $_SESSION access with a string key that does NOT
|
|
* start with "module.".
|
|
*/
|
|
private const SESSION_ACCESS_PATTERN = '/\$_SESSION\s*\[\s*[\'"](?!module\.)/';
|
|
|
|
public function testModulePhpFilesUseSessionPrefix(): void
|
|
{
|
|
$modulesDir = realpath(__DIR__ . '/../../modules');
|
|
self::assertNotFalse($modulesDir);
|
|
|
|
$violations = [];
|
|
|
|
foreach (self::$modules as $module) {
|
|
$moduleId = $module['id'];
|
|
|
|
foreach (['lib', 'pages'] as $subdir) {
|
|
$dir = $module['path'] . '/' . $subdir;
|
|
if (!is_dir($dir)) {
|
|
continue;
|
|
}
|
|
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS),
|
|
\RecursiveIteratorIterator::LEAVES_ONLY
|
|
);
|
|
|
|
foreach ($iterator as $file) {
|
|
/** @var \SplFileInfo $file */
|
|
$ext = $file->getExtension();
|
|
if ($ext !== 'php' && $ext !== 'phtml') {
|
|
continue;
|
|
}
|
|
|
|
$content = file_get_contents($file->getPathname());
|
|
if ($content === false) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match(self::SESSION_ACCESS_PATTERN, $content)) {
|
|
$relativePath = 'modules/' . $moduleId . '/' . $subdir . '/' . str_replace($dir . '/', '', $file->getPathname());
|
|
$violations[] = $relativePath . " (module '{$moduleId}') — session keys must start with 'module.{$moduleId}.'";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self::assertSame(
|
|
[],
|
|
$violations,
|
|
"Module session keys must be prefixed with 'module.<id>.':\n" . implode("\n", $violations)
|
|
);
|
|
}
|
|
}
|