TenantAtlas/tests/Support/OpsUx/SourceFileScanner.php
2026-02-24 10:15:34 +01:00

104 lines
2.7 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Support\OpsUx;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SplFileInfo;
final class SourceFileScanner
{
/**
* @param list<string> $roots
* @param list<string> $excludedAbsolutePaths
* @return list<string>
*/
public static function phpFiles(array $roots, array $excludedAbsolutePaths = []): array
{
$files = [];
$excluded = array_fill_keys(array_map(self::normalizePath(...), $excludedAbsolutePaths), true);
foreach ($roots as $root) {
$root = self::normalizePath($root);
if (! is_dir($root)) {
continue;
}
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($root, RecursiveDirectoryIterator::SKIP_DOTS)
);
/** @var SplFileInfo $file */
foreach ($iterator as $file) {
if (! $file->isFile()) {
continue;
}
$path = self::normalizePath($file->getPathname());
if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
continue;
}
if (isset($excluded[$path])) {
continue;
}
$files[] = $path;
}
}
sort($files);
return array_values(array_unique($files));
}
public static function projectRoot(): string
{
return self::normalizePath(dirname(__DIR__, 3));
}
public static function relativePath(string $absolutePath): string
{
$absolutePath = self::normalizePath($absolutePath);
$root = self::projectRoot();
if (str_starts_with($absolutePath, $root.'/')) {
return substr($absolutePath, strlen($root) + 1);
}
return $absolutePath;
}
public static function read(string $path): string
{
return (string) file_get_contents($path);
}
public static function snippet(string $source, int $line, int $contextLines = 2): string
{
$allLines = preg_split('/\R/', $source) ?: [];
$line = max(1, $line);
$start = max(1, $line - $contextLines);
$end = min(count($allLines), $line + $contextLines);
$snippet = [];
for ($index = $start; $index <= $end; $index++) {
$prefix = $index === $line ? '>' : ' ';
$snippet[] = sprintf('%s%4d | %s', $prefix, $index, $allLines[$index - 1] ?? '');
}
return implode("\n", $snippet);
}
private static function normalizePath(string $path): string
{
return str_replace('\\', '/', $path);
}
}