1
0
Files
breadcrumb-the-shire/tests/Architecture/ModuleSessionKeyPrefixContractTest.php

65 lines
2.2 KiB
PHP
Raw Normal View History

<?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)
);
}
}