projectRootPath(); $violations = []; foreach (['lib', 'pages'] as $dir) { $basePath = $root . '/' . $dir; $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($basePath)); /** @var \SplFileInfo $file */ foreach ($iterator as $file) { if (!$file->isFile() || $file->getExtension() !== 'php') { continue; } $content = (string) file_get_contents($file->getPathname()); $relativePath = str_replace($root . '/', '', $file->getPathname()); if (preg_match_all('/^.*\berror_log\s*\(.*$/m', $content, $matches)) { foreach ($matches[0] as $line) { foreach (self::PII_VARIABLE_PATTERNS as $piiPattern) { if (preg_match($piiPattern, $line)) { $violations[] = $relativePath . ': ' . trim($line); break; } } } } } } sort($violations); $this->assertSame( [], $violations, "error_log() calls with potential PII variables (GR-SEC-002):\n" . implode("\n", $violations) ); } public function testErrorLogUsageIsMinimal(): void { $violations = array_merge( $this->findPatternMatchesInPhpFiles('lib', '/\berror_log\s*\(/'), $this->findPatternMatchesInPhpFiles('pages', '/\berror_log\s*\(/') ); $violations = array_values(array_unique($violations)); sort($violations); $this->assertLessThanOrEqual( 3, count($violations), "error_log() usage growing — consider structured logging (GR-SEC-002). Found in:\n" . implode("\n", $violations) ); } }