*/ private const EXCLUDED_FILES = [ 'core/Service/User/UserAccessPdfService.php', ]; /** * Matches opening HTML tags that indicate rendering logic. * Ignores comments and string literals containing tag descriptions. */ private const HTML_TAG_PATTERN = '/<(?:div|span|table|form|input|button|select|textarea|label|ul|ol|li|h[1-6]|thead|tbody|tr|td|th|section|article|nav|header|footer|main|aside)\b/'; public function testServicesContainNoHtmlTags(): void { $violations = $this->findHtmlViolations('core/Service'); $violations = array_merge($violations, $this->findHtmlViolations('core/Http')); self::assertSame( [], $violations, "Service layer must not contain HTML tags. Violations found:\n" . implode("\n", $violations) ); } public function testModuleServicesContainNoHtmlTags(): void { $root = $this->projectRootPath(); $modulesDir = $root . '/modules'; if (!is_dir($modulesDir)) { self::markTestSkipped('modules/ directory missing.'); } $violations = []; foreach (scandir($modulesDir) ?: [] as $entry) { if ($entry === '.' || $entry === '..' || !is_dir($modulesDir . '/' . $entry)) { continue; } $libRel = 'modules/' . $entry . '/lib'; if (is_dir($root . '/' . $libRel)) { $violations = array_merge($violations, $this->findHtmlViolations($libRel)); } } self::assertSame( [], $violations, "Module service layer must not contain HTML tags. Violations found:\n" . implode("\n", $violations) ); } /** * @return list */ private function findHtmlViolations(string $relativeDirectory): array { $root = $this->projectRootPath(); $basePath = $root . '/' . $relativeDirectory; if (!is_dir($basePath)) { return []; } $hits = $this->findPatternMatchesInPhpFiles($relativeDirectory, self::HTML_TAG_PATTERN); return array_values(array_filter( $hits, static function (string $path): bool { // Exclude files that legitimately build HTML (PDF rendering) foreach (self::EXCLUDED_FILES as $excluded) { if ($path === $excluded) { return false; } } // Only flag Service/Gateway/Policy/Factory files, not generic helpers return (bool) preg_match('/(Service|Gateway|Policy|Factory)\.php$/', $path); } )); } }