99
1010declare (strict_types=1 );
1111
12- namespace Serafim \Contracts \Internal ;
12+ namespace Serafim \Contracts \Boot ;
1313
14- use Composer \Autoload \ClassLoader ;
15- use function Composer \Autoload \includeFile ;
14+ use Serafim \Contracts \Boot \Loader \ComposerLoader ;
15+ use Serafim \Contracts \Boot \Loader \LoaderInterface ;
16+ use Serafim \Contracts \Compiler \Compiler ;
17+ use Serafim \Contracts \Runtime \Exception ;
1618
17- /**
18- * @internal Interceptor is an internal library class, please do not use it in your code.
19- * @psalm-internal Serafim\Contracts
20- */
2119final class Interceptor
2220{
2321 /**
24- * @var array<string|class-string>
25- */
26- private $ namespaces = [];
27-
28- /**
29- * @var ClassLoader
22+ * @var list<non-empty-string|class-string>
3023 */
31- private $ loader ;
24+ private array $ namespaces = [] ;
3225
3326 /**
3427 * @var Storage
3528 */
36- private $ storage ;
29+ private Storage $ storage ;
3730
3831 /**
3932 * @var Compiler
4033 */
41- private $ compiler ;
34+ private readonly Compiler $ compiler ;
4235
4336 /**
44- * @param ClassLoader $loader
45- * @param string|null $storage
37+ * @psalm-taint-sink file $storage
38+ * @param LoaderInterface $loader
39+ * @param non-empty-string|null $storage
4640 */
47- public function __construct (ClassLoader $ loader , string $ storage = null )
41+ public function __construct (private readonly LoaderInterface $ loader , string $ storage = null )
4842 {
49- $ this ->loader = $ loader ;
50- $ this ->storage = new Storage ($ storage ?? \sys_get_temp_dir ());
5143 $ this ->compiler = new Compiler ();
44+ $ this ->storage = new Storage ($ storage ?? \sys_get_temp_dir ());
45+ }
46+
47+ /**
48+ * @psalm-taint-sink file $storage
49+ * @param non-empty-string|null $storage
50+ * @return static
51+ */
52+ public static function fromComposer (string $ storage = null ): self
53+ {
54+ return new self (ComposerLoader::create (), $ storage );
5255 }
5356
5457 /**
55- * @param string $directory
58+ * @psalm-taint-sink file $directory
59+ * @param non-empty-string $directory
5660 * @return $this
5761 */
5862 public function cache (string $ directory ): self
@@ -63,9 +67,10 @@ public function cache(string $directory): self
6367 }
6468
6569 /**
66- * @param array<string|class-string> $namespaces
70+ * @param non-empty-string|class-string ...$namespaces
71+ * @return void
6772 */
68- public function allow (array $ namespaces ): void
73+ public function allow (string ... $ namespaces ): void
6974 {
7075 foreach ($ namespaces as $ namespace ) {
7176 $ this ->namespaces [] = \trim ($ namespace , '\\' );
@@ -74,24 +79,22 @@ public function allow(array $namespaces): void
7479
7580 /**
7681 * @return void
77- * @psalm-suppress ArgumentTypeCoercion
7882 */
7983 public function enable (): void
8084 {
81- \spl_autoload_register ([ $ this , ' loadClass ' ] , true , true );
85+ \spl_autoload_register ($ this -> loadClass (...) , true , true );
8286 }
8387
8488 /**
8589 * @return void
86- * @psalm-suppress UnusedFunctionCall
8790 */
8891 public function disable (): void
8992 {
90- \spl_autoload_unregister ([ $ this , ' loadClass ' ] );
93+ \spl_autoload_unregister ($ this -> loadClass (...) );
9194 }
9295
9396 /**
94- * @param string $class
97+ * @param class- string $class
9598 * @return bool
9699 */
97100 public function isAllowed (string $ class ): bool
@@ -119,32 +122,26 @@ public function loadClass(string $class): bool
119122 try {
120123 return $ this ->findAndInclude ($ class );
121124 } catch (\Throwable $ e ) {
122- $ class = \get_class ($ e );
123-
124- $ instance = new $ class ($ e ->getMessage (), $ e ->getCode (), $ e ->getPrevious ());
125-
126- throw Exception::withLocation ($ instance , $ e ->getFile (), $ e ->getLine ());
125+ throw Exception::decorate ($ e );
127126 }
128127 }
129128
130129 /**
131- * @param string $class
130+ * @param class- string $class
132131 * @return bool
133132 */
134133 private function findAndInclude (string $ class ): bool
135134 {
136- $ file = $ this ->loader ->findFile ($ class );
135+ $ file = $ this ->loader ->getPathname ($ class );
137136
138137 if ($ file === false ) {
139138 return false ;
140139 }
141140
142- $ compiled = $ this ->storage ->cached ($ class , $ file , function () use ($ file ) {
141+ require $ this ->storage ->cached ($ class , $ file , function () use ($ file ) {
143142 return $ this ->compiler ->compile ($ file );
144143 });
145144
146- includeFile ($ compiled );
147-
148145 return true ;
149146 }
150- }
147+ }
0 commit comments