1+ <?php declare (strict_types=1 );
2+
3+ namespace Dbalabka \StaticConstructorLoader ;
4+
5+ use Composer \Autoload \ClassLoader ;
6+ use Dbalabka \StaticConstructorLoader \Exception \StaticConstructorLoaderException ;
7+
8+ class DebugStaticConstructorLoader extends ClassLoader /* extending for an contract */
9+ {
10+ /**
11+ * @var ClassLoader
12+ */
13+ private $ classLoader ;
14+
15+ public function __construct (ClassLoader $ classLoader )
16+ {
17+ $ this ->classLoader = $ classLoader ;
18+
19+ // find Composer autoloader
20+ $ loaders = spl_autoload_functions ();
21+ $ otherLoaders = [];
22+ $ composerLoader = null ;
23+ foreach ($ loaders as $ loader ) {
24+ if (is_array ($ loader )) {
25+ if ($ loader [0 ] === $ classLoader ) {
26+ $ composerLoader = $ loader ;
27+ break ;
28+ }
29+ if ($ loader [0 ] instanceof self) {
30+ throw new StaticConstructorLoaderException (sprintf ('%s already registered ' , self ::class));
31+ }
32+ }
33+ $ otherLoaders [] = $ loader ;
34+ }
35+
36+ if (!$ composerLoader ) {
37+ throw new StaticConstructorLoaderException (sprintf ('%s was not found in registered autoloaders ' , ClassLoader::class));
38+ }
39+
40+ // unregister Composer autoloader and all preceding autoloaders
41+ array_map ('spl_autoload_unregister ' , array_merge ($ otherLoaders , [$ composerLoader ]));
42+
43+ // restore the original queue order
44+ $ loadersToRestore = array_merge ([[$ this , 'loadClass ' ]], array_reverse ($ otherLoaders ));
45+ $ flagTrue = array_fill (0 , count ($ loadersToRestore ), true );
46+ array_map ('spl_autoload_register ' , $ loadersToRestore , $ flagTrue , $ flagTrue );
47+ }
48+
49+ public function loadClass ($ className ): ?bool
50+ {
51+ return $ this ->classLoader ->loadClass ($ className );
52+ }
53+
54+ public function getPrefixes ()
55+ {
56+ return $ this ->classLoader ->getPrefixes ();
57+ }
58+
59+ public function getPrefixesPsr4 ()
60+ {
61+ return $ this ->classLoader ->getPrefixesPsr4 ();
62+ }
63+
64+ public function getFallbackDirs ()
65+ {
66+ return $ this ->classLoader ->getFallbackDirs ();
67+ }
68+
69+ public function getFallbackDirsPsr4 ()
70+ {
71+ return $ this ->classLoader ->getFallbackDirsPsr4 ();
72+ }
73+
74+ public function getClassMap ()
75+ {
76+ return $ this ->classLoader ->getClassMap ();
77+ }
78+
79+ public function addClassMap (array $ classMap )
80+ {
81+ $ this ->classLoader ->addClassMap ($ classMap );
82+ }
83+
84+ public function add ($ prefix , $ paths , $ prepend = false )
85+ {
86+ $ this ->classLoader ->add ($ prefix , $ paths , $ prepend );
87+ }
88+
89+ public function addPsr4 ($ prefix , $ paths , $ prepend = false )
90+ {
91+ $ this ->classLoader ->addPsr4 ($ prefix , $ paths , $ prepend );
92+ }
93+
94+ public function set ($ prefix , $ paths )
95+ {
96+ $ this ->classLoader ->set ($ prefix , $ paths );
97+ }
98+
99+ public function setPsr4 ($ prefix , $ paths )
100+ {
101+ $ this ->classLoader ->setPsr4 ($ prefix , $ paths );
102+ }
103+
104+ public function setUseIncludePath ($ useIncludePath )
105+ {
106+ $ this ->classLoader ->setUseIncludePath ($ useIncludePath );
107+ }
108+
109+ public function getUseIncludePath ()
110+ {
111+ return $ this ->classLoader ->getUseIncludePath ();
112+ }
113+
114+ public function setClassMapAuthoritative ($ classMapAuthoritative )
115+ {
116+ $ this ->classLoader ->setClassMapAuthoritative ($ classMapAuthoritative );
117+ }
118+
119+ public function isClassMapAuthoritative ()
120+ {
121+ return $ this ->classLoader ->isClassMapAuthoritative ();
122+ }
123+
124+ public function setApcuPrefix ($ apcuPrefix )
125+ {
126+ $ this ->classLoader ->setApcuPrefix ($ apcuPrefix );
127+ }
128+
129+ public function getApcuPrefix ()
130+ {
131+ return $ this ->classLoader ->getApcuPrefix ();
132+ }
133+
134+ public function register ($ prepend = false )
135+ {
136+ $ this ->classLoader ->register ($ prepend );
137+ }
138+
139+ public function unregister ()
140+ {
141+ $ this ->classLoader ->unregister ();
142+ }
143+
144+ public function findFile ($ class )
145+ {
146+ $ path = $ this ->classLoader ->findFile ($ class );
147+
148+ if (
149+ class_exists (\Symfony \Component \ErrorHandler \DebugClassLoader::class, false )
150+ || class_exists (\Symfony \Component \Debug \DebugClassLoader::class, false )
151+ ) {
152+ return $ this ->handleDebugClassLoader ($ class , $ path );
153+ }
154+
155+ return $ path ;
156+ }
157+
158+ private function handleDebugClassLoader ($ class , $ path )
159+ {
160+ $ backtrace = debug_backtrace (DEBUG_BACKTRACE_IGNORE_ARGS , 3 );
161+ $ debugClassLoader = ($ backtrace [2 ] ?? null );
162+
163+ if ($ path
164+ && is_file ($ path )
165+ && \in_array (
166+ $ debugClassLoader ['class ' ] ?? null ,
167+ [
168+ \Symfony \Component \Debug \DebugClassLoader::class,
169+ \Symfony \Component \ErrorHandler \DebugClassLoader::class
170+ ],
171+ true
172+ )
173+ ) {
174+ include $ path ;
175+
176+ if (
177+ $ class !== StaticConstructorInterface::class
178+ && is_a ($ class , StaticConstructorInterface::class, true )
179+ ) {
180+ $ class ::__constructStatic ();
181+ }
182+
183+ return false ;
184+ }
185+
186+ return $ path ;
187+ }
188+ }
0 commit comments