3535use function substr ;
3636use function trim ;
3737
38+ /**
39+ * @package AdrianSuter\Autoload\Override
40+ */
3841class Override
3942{
4043 /**
4144 * @var array
4245 */
43- private static $ fileFunctionCallMappings ;
46+ private static $ fileFunctionCallMap ;
4447
4548 /**
4649 * @var array
4750 */
48- private static $ dirFunctionCallMappings ;
51+ private static $ dirFunctionCallMap ;
4952
5053 /**
5154 * @var CodeConverter|null
@@ -64,7 +67,7 @@ public static function setCodeConverter(CodeConverter $converter): void
6467 /**
6568 * @return CodeConverter
6669 */
67- public static function getCodeConverter (): CodeConverter
70+ private static function getCodeConverter (): CodeConverter
6871 {
6972 if (self ::$ converter === null ) {
7073 self ::setCodeConverter (new CodeConverter ());
@@ -75,13 +78,13 @@ public static function getCodeConverter(): CodeConverter
7578
7679 /**
7780 * @param ClassLoader $classLoader
78- * @param string[]|Closure[] $functionCallMappings
79- * @param string $namespace
81+ * @param string[]|Closure[] $functionCallMap
82+ * @param string $overrideNamespace
8083 */
8184 public static function apply (
8285 ClassLoader $ classLoader ,
83- array $ functionCallMappings ,
84- string $ namespace = 'PHPAutoloadOverride '
86+ array $ functionCallMap ,
87+ string $ overrideNamespace = 'PHPAutoloadOverride '
8588 ) {
8689 if ($ classLoader ->getApcuPrefix () !== null ) {
8790 throw new RuntimeException ('APC User Cache is not supported. ' );
@@ -92,15 +95,16 @@ public static function apply(
9295 $ classLoader ->loadClass (FileStreamWrapper::class);
9396 }
9497
95- // Reset the function call mappings .
96- self ::$ fileFunctionCallMappings = [];
97- self ::$ dirFunctionCallMappings = [];
98+ // Reset the function call maps .
99+ self ::$ fileFunctionCallMap = [];
100+ self ::$ dirFunctionCallMap = [];
98101
99102 // Initialize the collection of files we would force to load (include).
100103 $ autoloadCollection = new AutoloadCollection ();
101104
102- foreach ($ functionCallMappings as $ fqn => $ mappings ) {
103- $ fqnFunctionCallMappings = self ::buildMappings ($ mappings , $ namespace );
105+ foreach ($ functionCallMap as $ fqn => $ map ) {
106+ // Build the fqn function call map.
107+ $ fqnFunctionCallMap = self ::buildFunctionCallMap ($ map , $ overrideNamespace );
104108
105109 if (substr ($ fqn , -1 , 1 ) === '\\' ) {
106110 // The given fqn is a namespace.
@@ -124,8 +128,7 @@ public static function apply(
124128 if (is_dir ($ dir ) && !isset ($ handled [$ dir ])) {
125129 $ handled [$ dir ] = true ;
126130
127- self ::addNamespaceData ([$ dir ], $ fqnFunctionCallMappings );
128- $ autoloadCollection ->addDirectory ($ dir );
131+ self ::addDirectoryFunctionCallMap ($ autoloadCollection , $ dir , $ fqnFunctionCallMap );
129132 }
130133 }
131134 }
@@ -140,13 +143,13 @@ public static function apply(
140143 continue ;
141144 }
142145
143- if (isset (self ::$ fileFunctionCallMappings [$ p ])) {
144- self ::$ fileFunctionCallMappings [$ p ] = array_merge (
145- $ fqnFunctionCallMappings ,
146- self ::$ fileFunctionCallMappings [$ p ]
146+ if (isset (self ::$ fileFunctionCallMap [$ p ])) {
147+ self ::$ fileFunctionCallMap [$ p ] = array_merge (
148+ $ fqnFunctionCallMap ,
149+ self ::$ fileFunctionCallMap [$ p ]
147150 );
148151 } else {
149- self ::$ fileFunctionCallMappings [$ p ] = $ fqnFunctionCallMappings ;
152+ self ::$ fileFunctionCallMap [$ p ] = $ fqnFunctionCallMap ;
150153 }
151154 $ autoloadCollection ->addFile ($ p );
152155 }
@@ -170,85 +173,107 @@ public static function apply(
170173 continue ;
171174 }
172175
173- self ::$ fileFunctionCallMappings [$ path ] = $ fqnFunctionCallMappings ;
176+ self ::$ fileFunctionCallMap [$ path ] = $ fqnFunctionCallMap ;
174177 $ autoloadCollection ->addFile ($ path );
175178 }
176179
177180 // Load the classes that are affected by the FQFC-override converter.
178181 stream_wrapper_unregister ('file ' );
179182 stream_wrapper_register ('file ' , FileStreamWrapper::class);
180- foreach ($ autoloadCollection ->getFilePaths () as $ file ) {
183+ foreach ($ autoloadCollection ->getFilePaths () as $ filePath ) {
181184 /** @noinspection PhpIncludeInspection */
182- include_once $ file ;
185+ include_once $ filePath ;
183186 }
184187
185188 stream_wrapper_restore ('file ' );
186189 clearstatcache ();
187190 }
188191
189192 /**
190- * @param string[]|Closure[] $mappings
193+ * Build a mapping between root namespaced function calls and their overridden fully qualified name.
194+ *
195+ * @param string[]|Closure[] $map
191196 * @param string $namespace
192197 *
193- * @return array
198+ * @return string[]
194199 */
195- private static function buildMappings (array $ mappings , string $ namespace ): array
200+ private static function buildFunctionCallMap (array $ map , string $ namespace ): array
196201 {
197- $ fcMappings = [];
198- foreach ($ mappings as $ key => $ val ) {
202+ $ functionCallMap = [];
203+ foreach ($ map as $ key => $ val ) {
199204 if (is_numeric ($ key )) {
200- $ fcMappings ['\\' . $ val ] = $ namespace . '\\' . $ val ;
205+ $ functionCallMap ['\\' . $ val ] = $ namespace . '\\' . $ val ;
201206 } elseif (is_string ($ val )) {
202- $ fcMappings ['\\' . $ key ] = $ val . '\\' . $ key ;
207+ $ functionCallMap ['\\' . $ key ] = $ val . '\\' . $ key ;
203208 } elseif ($ val instanceof Closure) {
204209 $ name = $ key . '_ ' . spl_object_hash ($ val );
205210 ClosureHandler::getInstance ()->addClosure ($ name , $ val );
206211
207- $ fcMappings ['\\' . $ key ] = ClosureHandler::class . '::getInstance()-> ' . $ name ;
212+ $ functionCallMap ['\\' . $ key ] = ClosureHandler::class . '::getInstance()-> ' . $ name ;
208213 }
209214 }
210215
211- return $ fcMappings ;
216+ return $ functionCallMap ;
212217 }
213218
214- private static function addNamespaceData (array $ directories , array $ functionMappings ): void
215- {
216- foreach ($ directories as $ dir ) {
217- if (!file_exists ($ dir )) {
218- continue ;
219- }
219+ private static function addDirectoryFunctionCallMap (
220+ AutoloadCollection $ autoloadCollection ,
221+ string $ directory ,
222+ array $ fqnFunctionCallMap
223+ ): void {
224+ $ directory = realpath ($ directory );
225+ if ($ directory === false ) {
226+ return ;
227+ }
220228
221- $ dir = realpath ($ dir );
222- if (isset (self ::$ dirFunctionCallMappings [$ dir ])) {
223- self ::$ dirFunctionCallMappings [$ dir ] = array_merge (
224- self ::$ dirFunctionCallMappings [$ dir ],
225- $ functionMappings
226- );
227- } else {
228- self ::$ dirFunctionCallMappings [$ dir ] = $ functionMappings ;
229- }
229+ if (isset (self ::$ dirFunctionCallMap [$ directory ])) {
230+ self ::$ dirFunctionCallMap [$ directory ] = array_merge (
231+ self ::$ dirFunctionCallMap [$ directory ],
232+ $ fqnFunctionCallMap
233+ );
234+ } else {
235+ self ::$ dirFunctionCallMap [$ directory ] = $ fqnFunctionCallMap ;
230236 }
237+
238+ $ autoloadCollection ->addDirectory ($ directory );
231239 }
232240
233241 /**
234242 * @param string $filePath
235243 *
236244 * @return string[]
237245 */
238- public static function getFunctionMappings (string $ filePath ): array
246+ public static function getFunctionCallMap (string $ filePath ): array
239247 {
240248 $ filePath = realpath ($ filePath );
249+ if ($ filePath === false ) {
250+ return [];
251+ }
252+
241253 $ dirPath = dirname ($ filePath );
242254
243- $ mappings = [];
244- if (isset (self ::$ dirFunctionCallMappings [$ dirPath ])) {
245- $ mappings = array_merge ($ mappings , self ::$ dirFunctionCallMappings [$ dirPath ]);
255+ $ functionCallMap = [];
256+ if (isset (self ::$ dirFunctionCallMap [$ dirPath ])) {
257+ $ functionCallMap = array_merge ($ functionCallMap , self ::$ dirFunctionCallMap [$ dirPath ]);
246258 }
247259
248- if (isset (self ::$ fileFunctionCallMappings [$ filePath ])) {
249- $ mappings = array_merge ($ mappings , self ::$ fileFunctionCallMappings [$ filePath ]);
260+ if (isset (self ::$ fileFunctionCallMap [$ filePath ])) {
261+ $ functionCallMap = array_merge ($ functionCallMap , self ::$ fileFunctionCallMap [$ filePath ]);
250262 }
251263
252- return $ mappings ;
264+ return $ functionCallMap ;
265+ }
266+
267+ /**
268+ * Convert the source code using the fqn function call map.
269+ *
270+ * @param string $source
271+ * @param array $functionCallMap
272+ *
273+ * @return string
274+ */
275+ public static function convert (string $ source , array $ functionCallMap ): string
276+ {
277+ return self ::getCodeConverter ()->convert ($ source , $ functionCallMap );
253278 }
254279}
0 commit comments