Skip to content

Commit b5b14d6

Browse files
committed
feat(phar): phar-safe realpath(), configurable internalStorage
1 parent c760b2d commit b5b14d6

File tree

13 files changed

+57
-16
lines changed

13 files changed

+57
-16
lines changed

packages/console/src/Highlight/TempestConsoleLanguage/Injections/FileInjection.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Tempest\Highlight\Themes\TerminalStyle;
1111

1212
use function Tempest\root_path;
13+
use function Tempest\Support\Filesystem\real_path;
1314
use function Tempest\Support\str;
1415

1516
final readonly class FileInjection implements Injection
@@ -21,9 +22,9 @@ public function parse(string $content, Highlighter $highlighter): ParsedInjectio
2122
pattern: '/(?<match>\<file=(?<quote>[\"\'])(?<file>.+)\k<quote>\s*\/?>)/',
2223
callback: function (array $matches) {
2324
$href = $matches['file'];
24-
$exists = realpath($href) !== false;
25+
$exists = real_path($href) !== null;
2526
$file = $exists
26-
? str(realpath($href))->replace('\\', '/')->stripStart(root_path())->stripStart('/')
27+
? str(real_path($href))->replace('\\', '/')->stripStart(root_path())->stripStart('/')
2728
: $href;
2829

2930
return TerminalStyle::UNDERLINE((string) $file);

packages/core/src/Commands/DiscoveryStatusCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Tempest\Core\Kernel;
1313

1414
use function Tempest\root_path;
15+
use function Tempest\Support\Filesystem\real_path;
1516
use function Tempest\Support\str;
1617

1718
if (class_exists(\Tempest\Console\ConsoleCommand::class, false)) {
@@ -62,7 +63,7 @@ public function __invoke(
6263
$this->console->writeln();
6364

6465
foreach ($this->kernel->discoveryLocations as $discoveryLocation) {
65-
$path = str(realpath($discoveryLocation->path))
66+
$path = str(real_path($discoveryLocation->path))
6667
->replaceStart(root_path(), '.')
6768
->toString();
6869

packages/core/src/DiscoveryConfig.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Tempest\Core;
44

5+
use function Tempest\Support\Filesystem\real_path;
6+
57
final class DiscoveryConfig
68
{
79
private array $skipDiscovery = [];
@@ -25,9 +27,9 @@ public function skipPaths(string ...$paths): self
2527
foreach ($paths as $path) {
2628
$path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $path);
2729

28-
$realpath = realpath($path);
30+
$realpath = real_path($path);
2931

30-
if ($realpath === false) {
32+
if ($realpath === null) {
3133
continue;
3234
}
3335

packages/core/src/FrameworkKernel.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
use Tempest\Process\GenericProcessExecutor;
2020
use Tempest\Router\Exceptions\HttpExceptionHandler;
2121

22+
use function Tempest\Support\Filesystem\real_path;
23+
2224
final class FrameworkKernel implements Kernel
2325
{
2426
public readonly Container $container;
@@ -34,14 +36,20 @@ public function __construct(
3436
/** @var \Tempest\Discovery\DiscoveryLocation[] $discoveryLocations */
3537
public array $discoveryLocations = [],
3638
?Container $container = null,
39+
?string $internalStorage = null,
3740
) {
3841
$this->container = $container ?? $this->createContainer();
42+
43+
if ($internalStorage !== null) {
44+
$this->internalStorage = $internalStorage;
45+
}
3946
}
4047

4148
public static function boot(
4249
string $root,
4350
array $discoveryLocations = [],
4451
?Container $container = null,
52+
?string $internalStorage = null,
4553
): self {
4654
if (! defined('TEMPEST_START')) {
4755
define('TEMPEST_START', value: hrtime(true));
@@ -51,6 +59,7 @@ public static function boot(
5159
root: $root,
5260
discoveryLocations: $discoveryLocations,
5361
container: $container,
62+
internalStorage: $internalStorage,
5463
)
5564
->validateRoot()
5665
->loadEnv()
@@ -68,7 +77,7 @@ public static function boot(
6877

6978
public function validateRoot(): self
7079
{
71-
$root = realpath($this->root);
80+
$root = real_path($this->root);
7281

7382
if (! is_dir($root)) {
7483
throw new RuntimeException('The specified root directory is not valid.');
@@ -175,7 +184,7 @@ public function loadConfig(): self
175184

176185
public function registerInternalStorage(): self
177186
{
178-
$path = $this->root . '/.tempest';
187+
$path = isset($this->internalStorage) ? $this->internalStorage : $this->root . '/.tempest';
179188

180189
if (! is_dir($path)) {
181190
if (file_exists($path)) {
@@ -189,7 +198,7 @@ public function registerInternalStorage(): self
189198
throw CouldNotRegisterInternalStorage::noPermission($path);
190199
}
191200

192-
$this->internalStorage = realpath($path);
201+
$this->internalStorage = real_path($path);
193202

194203
return $this;
195204
}

packages/core/src/Kernel/LoadConfig.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Tempest\Support\Arr\MutableArray;
1111
use Tempest\Support\Str;
1212

13+
use function Tempest\Support\Filesystem\real_path;
14+
1315
/** @internal */
1416
final readonly class LoadConfig
1517
{
@@ -85,10 +87,10 @@ public function find(): array
8587
*/
8688
private function scan(string $path, MutableArray $configPaths): void
8789
{
88-
$input = realpath($path);
90+
$input = real_path($path);
8991

9092
// Make sure the path is valid
91-
if ($input === false) {
93+
if ($input === null) {
9294
return;
9395
}
9496

packages/core/src/Kernel/LoadDiscoveryClasses.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use Tempest\Reflection\ClassReflector;
1919
use Throwable;
2020

21+
use function Tempest\Support\Filesystem\real_path;
22+
2123
/** @internal */
2224
final class LoadDiscoveryClasses
2325
{
@@ -105,10 +107,10 @@ private function discover(array $discoveries): void
105107
*/
106108
private function scan(DiscoveryLocation $location, array $discoveries, string $path): void
107109
{
108-
$input = realpath($path);
110+
$input = real_path($path);
109111

110112
// Make sure the path is valid
111-
if ($input === false) {
113+
if ($input === null) {
112114
return;
113115
}
114116

packages/core/src/Tempest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ public static function boot(
1212
?string $root = null,
1313
/** @var \Tempest\Discovery\DiscoveryLocation[] $discoveryLocations */
1414
array $discoveryLocations = [],
15+
?string $internalStorage = null,
1516
): Container {
1617
$root ??= getcwd();
1718

1819
// Kernel
1920
return FrameworkKernel::boot(
2021
root: $root,
2122
discoveryLocations: $discoveryLocations,
23+
internalStorage: $internalStorage,
2224
)->container;
2325
}
2426
}

packages/discovery/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"minimum-stability": "dev",
66
"require": {
77
"php": "^8.4",
8-
"tempest/reflection": "dev-main"
8+
"tempest/reflection": "dev-main",
9+
"tempest/support": "dev-main"
910
},
1011
"autoload": {
1112
"psr-4": {

packages/discovery/src/DiscoveryLocation.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Tempest\Discovery;
66

7+
use function Tempest\Support\Filesystem\real_path;
8+
79
final class DiscoveryLocation
810
{
911
public readonly string $namespace;
@@ -18,7 +20,7 @@ public function __construct(
1820
string $path,
1921
) {
2022
$this->namespace = $namespace;
21-
$this->path = realpath(rtrim($path, '\\/'));
23+
$this->path = real_path(rtrim($path, '\\/'));
2224
}
2325

2426
public function isVendor(): bool

packages/support/src/Filesystem/functions.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,3 +503,15 @@ function read_symbolic_link(string $path): string
503503

504504
return $result;
505505
}
506+
507+
/**
508+
* Returns the real path for the specified $path or null if it doesn't exist.
509+
*/
510+
function real_path(string $path): ?string
511+
{
512+
if (\class_exists(\Phar::class) && \Phar::running(false) !== '' && \str_starts_with($path, 'phar:')) {
513+
return $path;
514+
}
515+
516+
return realpath($path) ?: null;
517+
}

0 commit comments

Comments
 (0)