From 6228bd392564f2e8bc3faed69b4be451b282038b Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Fri, 23 Apr 2021 23:16:02 +0800 Subject: [PATCH] Optimizations for Autoloader --- system/Autoloader/Autoloader.php | 84 +++++++++++++++----------------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 845790bb7f88..097c581ab4d5 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -11,6 +11,7 @@ namespace CodeIgniter\Autoloader; +use Composer\Autoload\ClassLoader; use Config\Autoload; use Config\Modules; use InvalidArgumentException; @@ -21,17 +22,17 @@ * An autoloader that uses both PSR4 autoloading, and traditional classmaps. * * Given a foo-bar package of classes in the file system at the following paths: - * + *``` * /path/to/packages/foo-bar/ * /src * Baz.php # Foo\Bar\Baz * Qux/ * Quux.php # Foo\Bar\Qux\Quux - * + *``` * you can add the path to the configuration array that is passed in the constructor. * The Config array consists of 2 primary keys, both of which are associative arrays: * 'psr4', and 'classmap'. - * + *``` * $Config = [ * 'psr4' => [ * 'Foo\Bar' => '/path/to/packages/foo-bar' @@ -40,9 +41,9 @@ * 'MyClass' => '/path/to/class/file.php' * ] * ]; - * + *``` * Example: - * + *``` * register(); + *``` */ class Autoloader { /** * Stores namespaces as key, and path as values. * - * @var array + * @var array> */ protected $prefixes = []; /** * Stores class name as key, and path as values. * - * @var array + * @var array */ protected $classmap = []; - //-------------------------------------------------------------------- - /** * Reads in the configuration array (described above) and stores * the valid parts that we'll need. @@ -106,8 +106,6 @@ public function initialize(Autoload $config, Modules $modules) return $this; } - //-------------------------------------------------------------------- - /** * Register the loader with the SPL autoloader stack. */ @@ -117,22 +115,9 @@ public function register() spl_autoload_register([$this, 'loadClass'], true, true); // @phpstan-ignore-line // Now prepend another loader for the files in our class map. - - // @phpstan-ignore-next-line - spl_autoload_register(function ($class) { - if (empty($this->classmap[$class])) - { - return false; - } - - include_once $this->classmap[$class]; - }, true, // Throw exception - true // Prepend - ); + spl_autoload_register([$this, 'loadClassmap'], true, true); // @phpstan-ignore-line } - //-------------------------------------------------------------------- - /** * Registers namespaces with the autoloader. * @@ -170,8 +155,6 @@ public function addNamespace($namespace, string $path = null) return $this; } - //-------------------------------------------------------------------- - /** * Get namespaces with prefixes as keys and paths as values. * @@ -191,8 +174,6 @@ public function getNamespace(string $prefix = null) return $this->prefixes[trim($prefix, '\\')] ?? []; } - //-------------------------------------------------------------------- - /** * Removes a single namespace from the psr4 settings. * @@ -210,7 +191,24 @@ public function removeNamespace(string $namespace) return $this; } - //-------------------------------------------------------------------- + /** + * Load a class using available class mapping. + * + * @param string $class + * + * @return string|false + */ + public function loadClassmap(string $class) + { + $file = $this->classmap[$class] ?? ''; + + if ($file !== '') + { + return $this->includeFile($file); + } + + return false; + } /** * Loads the class file for a given class name. @@ -228,8 +226,6 @@ public function loadClass(string $class) return $this->loadInNamespace($class); } - //-------------------------------------------------------------------- - /** * Loads the class file for a given class name. * @@ -276,8 +272,6 @@ protected function loadInNamespace(string $class) return false; } - //-------------------------------------------------------------------- - /** * A central way to include a file. Split out primarily for testing purposes. * @@ -299,8 +293,6 @@ protected function includeFile(string $file) return false; } - //-------------------------------------------------------------------- - /** * Sanitizes a filename, replacing spaces with dashes. * @@ -312,13 +304,12 @@ protected function includeFile(string $file) * * @param string $filename * - * @return string The sanitized filename + * @return string The sanitized filename */ public function sanitizeFilename(string $filename): string { // Only allow characters deemed safe for POSIX portable filenames. - // Plus the forward slash for directory separators since this might - // be a path. + // Plus the forward slash for directory separators since this might be a path. // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_278 // Modified to allow backslash and colons for on Windows machines. $filename = preg_replace('/[^0-9\p{L}\s\/\-\_\.\:\\\\]/u', '', $filename); @@ -329,21 +320,23 @@ public function sanitizeFilename(string $filename): string return $filename; } - //-------------------------------------------------------------------- - /** - * Locates all PSR4 compatible namespaces from Composer. + * Locates autoload information from Composer, if available. + * + * @return void */ protected function discoverComposerNamespaces() { if (! is_file(COMPOSER_PATH)) { - return false; + return; } + /** @var ClassLoader $composer */ $composer = include COMPOSER_PATH; + $paths = $composer->getPrefixesPsr4(); + $classes = $composer->getClassMap(); - $paths = $composer->getPrefixesPsr4(); unset($composer); // Get rid of CodeIgniter so we don't have duplicates @@ -352,13 +345,14 @@ protected function discoverComposerNamespaces() unset($paths['CodeIgniter\\']); } - // Composer stores namespaces with trailing slash. We don't. $newPaths = []; foreach ($paths as $key => $value) { + // Composer stores namespaces with trailing slash. We don't. $newPaths[rtrim($key, '\\ ')] = $value; } $this->prefixes = array_merge($this->prefixes, $newPaths); + $this->classmap = array_merge($this->classmap, $classes); } }