1: <?php declare(strict_types = 1);
2:
3: namespace ApiGen;
4:
5: use ReflectionClass;
6:
7: use function array_map;
8: use function array_shift;
9: use function assert;
10: use function count;
11: use function realpath;
12: use function str_starts_with;
13: use function strlen;
14: use function substr;
15:
16: use const DIRECTORY_SEPARATOR;
17:
18:
19: class Helpers
20: {
21: /**
22: * @param string[] $paths indexed by [], non-empty
23: */
24: public static function baseDir(array $paths): string
25: {
26: assert(count($paths) > 0);
27:
28: $paths = array_map(self::realPath(...), $paths);
29: $first = array_shift($paths);
30: $j = 0;
31:
32: for ($i = 0; $i < strlen($first); $i++) {
33: foreach ($paths as $path) {
34: if (!isset($path[$i]) || $path[$i] !== $first[$i]) {
35: return substr($first, 0, $j);
36:
37: } elseif ($first[$i] === DIRECTORY_SEPARATOR) {
38: $j = $i;
39: }
40: }
41: }
42:
43: return $first;
44: }
45:
46:
47: public static function realPath(string $path): string
48: {
49: if (str_starts_with($path, 'phar://')) {
50: return $path;
51: }
52:
53: $realPath = realpath($path);
54:
55: if ($realPath === false) {
56: throw new \RuntimeException("File $path does not exist.");
57: }
58:
59: return $realPath;
60: }
61:
62:
63: /**
64: * @param class-string $name
65: */
66: public static function classLikePath(string $name): string
67: {
68: $reflection = new ReflectionClass($name);
69: $path = $reflection->getFileName();
70:
71: if ($path === false) {
72: throw new \RuntimeException("Class-like $name has no path.");
73: }
74:
75: return $path;
76: }
77: }
78: