]> git.mxchange.org Git - core.git/blobdiff - framework/loader/class_ClassLoader.php
Continued:
[core.git] / framework / loader / class_ClassLoader.php
index 3f5271a012315e2b3aace499a437b026c149c7bc..f29e6b63b8a3efd7b6c542754dbc9ff45e6b875f 100644 (file)
@@ -60,16 +60,17 @@ use \SplFileInfo;
  *  - Initial release
  * ----------------------------------
  */
-class ClassLoader {
+final class ClassLoader {
        /**
         * Instance of this class
         */
        private static $selfInstance = NULL;
 
        /**
-        * Array with all found classes
+        * Array with all valid but pending for loading file names (class,
+        * interfaces, traits must start with below prefix).
         */
-       private $foundClasses = [];
+       private $pendingFiles = [];
 
        /**
         * List of loaded classes
@@ -168,7 +169,7 @@ class ClassLoader {
                // Skip here if already cached
                if ($this->listCached === false) {
                        // Writes the cache file of our list away
-                       $cacheContent = json_encode($this->foundClasses);
+                       $cacheContent = json_encode($this->pendingFiles);
 
                        // Open cache instance
                        $fileObject = $this->listCacheFile->openFile('w');
@@ -208,25 +209,27 @@ class ClassLoader {
                //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
                $loaderInstance = self::getSelfInstance();
 
-               // "Cache" configuration instance
+               // "Cache" configuration instance and framework base path
                $configInstance = FrameworkBootstrap::getConfigurationInstance();
+               $frameworkBasePath = $configInstance->getConfigEntry('framework_base_path');
 
                // Load all classes
+               //* NOISY-DEBUG: */ printf('[%s:%d]: frameworkBasePath=%s,self::$frameworkPaths()=%d,' . PHP_EOL, __METHOD__, __LINE__, $frameworkBasePath, count(self::$frameworkPaths));
                foreach (self::$frameworkPaths as $shortPath) {
                        // Generate full path from it
-                       //* NOISY-DEBUG: */ printf('[%s:%d]: shortPath=%s' . PHP_EOL, __METHOD__, __LINE__, $shortPath);
+                       //* NOISY-DEBUG: */ printf('[%s:%d]: shortPath[%s]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($shortPath), $shortPath);
                        $realPathName = realpath(sprintf(
                                '%smain%s%s%s',
-                               $configInstance->getConfigEntry('framework_base_path'),
+                               $frameworkBasePath,
                                DIRECTORY_SEPARATOR,
                                $shortPath,
                                DIRECTORY_SEPARATOR
                        ));
 
                        // Is it not false and accessible?
-                       //* NOISY-DEBUG: */ printf('[%s:%d]: realPathName=%s' . PHP_EOL, __METHOD__, __LINE__, $realPathName);
+                       //* NOISY-DEBUG: */ printf('[%s:%d]: realPathName[%s]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($realPathName), $realPathName);
                        if (is_bool($realPathName)) {
-                               // Skip this
+                               // Skip this, it is not accessible
                                continue;
                        } elseif (!is_readable($realPathName)) {
                                // @TODO Throw exception instead of break
@@ -285,18 +288,14 @@ class ClassLoader {
         * @return      void
         */
        public static function scanTestsClasses () {
-               // Trace message
-               //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
-
                // "Cache" configuration instance
+               //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
                $configInstance = FrameworkBootstrap::getConfigurationInstance();
 
                // Load all classes for the application
                foreach (self::$testPaths as $shortPath) {
-                       // Debug message
-                       //* NOISY-DEBUG: */ printf('[%s:%d]: shortPath=%s' . PHP_EOL, __METHOD__, __LINE__, $shortPath);
-
                        // Construct path name
+                       //* NOISY-DEBUG: */ printf('[%s:%d]: shortPath=%s' . PHP_EOL, __METHOD__, __LINE__, $shortPath);
                        $pathName = sprintf(
                                '%s%s%s',
                                $configInstance->getConfigEntry('root_base_path'),
@@ -354,17 +353,24 @@ class ClassLoader {
         * @throws      InvalidArgumentException        If the class' name does not contain a namespace: Tld\Domain\Project is AT LEAST recommended!
         */
        public static function autoLoad (string $className) {
-               // The class name should contain at least 2 back-slashes, so split at them
+               // Validate parameter
                //* NOISY-DEBUG: */ printf('[%s:%d] className=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $className);
+               if (empty($className)) {
+                       // Should not be empty
+                       throw new InvalidArgumentException('Parameter "className" is empty');
+               }
+
+               // The class name MUST be at least Tld\Domain\Project\Package\SomeFooBar so split at them
                $classNameParts = explode("\\", $className);
 
                // At least 3 parts should be there
                if ((self::$strictNamingConvention === true) && (count($classNameParts) < 5)) {
-                       // Namespace scheme is: Project\Package[\SubPackage...]
+                       // Namespace scheme is: Tld\Domain\Project\Package[\SubPackage...]
                        throw new InvalidArgumentException(sprintf('Class name "%s" is not conform to naming-convention: Tld\Domain\Project\Package[\SubPackage...]\SomeFooBar', $className));
                }
 
                // Try to include this class
+               //* NOISY-DEBUG: */ printf('[%s:%d]: Calling self->loadClassFile(%s) ...' . PHP_EOL, __METHOD__, __LINE__, $className);
                self::getSelfInstance()->loadClassFile($className);
 
                // Trace message
@@ -422,22 +428,16 @@ class ClassLoader {
         */
        protected function scanClassPath (string $basePath, array $ignoreList = [] ) {
                // Is a list has been restored from cache, don't read it again
+               /* NOISY-DEBUG: */ printf('[%s:%d] basePath=%s,ignoreList()=%d - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $basePath, count($ignoreList));
                if ($this->listCached === true) {
                        // Abort here
+                       /* NOISY-DEBUG: */ printf('[%s:%d] this->listCache=true - EXIT!' . PHP_EOL, __METHOD__, __LINE__);
                        return;
                }
 
                // Keep it in class for later usage
                $this->ignoreList = $ignoreList;
 
-               /*
-                * Ignore .htaccess by default as it is for protection of directories
-                * on Apache servers.
-                *
-                * @deprecated
-                */
-               array_push($ignoreList, '.htaccess');
-
                /*
                 * Set base directory which holds all our classes, an absolute path
                 * should be used here so is_dir(), is_file() and so on will always
@@ -446,6 +446,7 @@ class ClassLoader {
                $basePath2 = realpath($basePath);
 
                // If the basePath is false it is invalid
+               /* NOISY-DEBUG: */ printf('[%s:%d] basePath2[%s]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($basePath2), $basePath2);
                if ($basePath2 === false) {
                        /* @TODO: Do not exit here. */
                        exit(__METHOD__ . ': Cannot read ' . $basePath . ' !' . PHP_EOL);
@@ -472,23 +473,23 @@ class ClassLoader {
                                $iteratorInstance->next();
 
                                // Skip non-file entries
-                               //* NOISY-DEBUG: */ printf('[%s:%d] SKIP: %s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+                               //* NOISY-DEBUG: */ printf('[%s:%d] SKIP: fileName=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
                                continue;
                        }
 
                        // Is this file wanted?
-                       //* NOISY-DEBUG: */ printf('[%s:%d] FOUND: %s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+                       //* NOISY-DEBUG: */ printf('[%s:%d] FOUND: fileName=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
                        if ((substr($fileName, 0, strlen($this->prefix)) == $this->prefix) && (substr($fileName, -strlen($this->suffix), strlen($this->suffix)) == $this->suffix)) {
                                // Add it to the list
-                               //* NOISY-DEBUG: */ printf('[%s:%d] ADD: %s,currentEntry=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName, $currentEntry);
-                               $this->foundClasses[$fileName] = $currentEntry;
+                               //* NOISY-DEBUG: */ printf('[%s:%d] ADD: fileName=%s,currentEntry=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName, $currentEntry);
+                               $this->pendingFiles[$fileName] = $currentEntry;
                        } else {
                                // Not added
-                               //* NOISY-DEBUG: */ printf('[%s:%d] NOT ADDED: %s,currentEntry=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName, $currentEntry);
+                               //* NOISY-DEBUG: */ printf('[%s:%d] NOT ADDED: fileName=%s,currentEntry=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName, $currentEntry);
                        }
 
                        // Advance to next entry
-                       //* NOISY-DEBUG: */ printf('[%s:%d] NEXT: %s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+                       //* NOISY-DEBUG: */ printf('[%s:%d] NEXT: fileName=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
                        $iteratorInstance->next();
                }
        }
@@ -521,7 +522,7 @@ class ClassLoader {
                // Is the cache there?
                if (FrameworkBootstrap::isReadableFile($this->listCacheFile)) {
                        // Load and convert it
-                       $this->foundClasses = json_decode(file_get_contents($this->listCacheFile->getPathname()));
+                       $this->pendingFiles = json_decode(file_get_contents($this->listCacheFile->getPathname()));
 
                        // List has been restored from cache!
                        $this->listCached = true;
@@ -538,9 +539,10 @@ class ClassLoader {
        }
 
        /**
-        * Tries to find the given class in our list. This method ignores silently
-        * missing classes or interfaces. So if you use class_exists() this method
-        * does not interrupt your program.
+        * Tries to find the given class in our list. It will ignore already loaded 
+        * (to the program available) class/interface/trait files. But you SHOULD
+        * save below "expensive" code by pre-checking this->loadedClasses[], if
+        * possible.
         *
         * @param       $className      The class that shall be loaded
         * @return      void
@@ -557,22 +559,22 @@ class ClassLoader {
                $fileName = sprintf('%s%s%s', $this->prefix, $shortClassName, $this->suffix);
 
                // Now look it up in our index
-               //* NOISY-DEBUG: */ printf('[%s:%d] ISSET: %s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
-               if ((isset($this->foundClasses[$fileName])) && (!isset($this->loadedClasses[$this->foundClasses[$fileName]->getPathname()]))) {
+               //* NOISY-DEBUG: */ printf('[%s:%d] ISSET: fileName=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+               if ((isset($this->pendingFiles[$fileName])) && (!isset($this->loadedClasses[$this->pendingFiles[$fileName]->getPathname()]))) {
                        // File is found and not loaded so load it only once
-                       //* NOISY-DEBUG: */ printf('[%s:%d] LOAD: %s - START' . PHP_EOL, __METHOD__, __LINE__, $fileName);
-                       FrameworkBootstrap::loadInclude($this->foundClasses[$fileName]);
-                       //* NOISY-DEBUG: */ printf('[%s:%d] LOAD: %s - END' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+                       //* NOISY-DEBUG: */ printf('[%s:%d] LOAD: fileName=%s - START' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+                       FrameworkBootstrap::loadInclude($this->pendingFiles[$fileName]);
+                       //* NOISY-DEBUG: */ printf('[%s:%d] LOAD: fileName=%s - END' . PHP_EOL, __METHOD__, __LINE__, $fileName);
 
                        // Count this loaded class/interface/exception
                        $this->total++;
 
                        // Mark this class as loaded for other purposes than loading it.
-                       $this->loadedClasses[$this->foundClasses[$fileName]->getPathname()] = true;
+                       $this->loadedClasses[$this->pendingFiles[$fileName]->getPathname()] = true;
 
                        // Remove it from classes list so it won't be found twice.
-                       //* NOISY-DEBUG: */ printf('[%s:%d] UNSET: %s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
-                       unset($this->foundClasses[$fileName]);
+                       //* NOISY-DEBUG: */ printf('[%s:%d] UNSET: fileName=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+                       unset($this->pendingFiles[$fileName]);
 
                        // Developer mode excludes caching (better debugging)
                        if (!FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('developer_mode_enabled')) {
@@ -582,8 +584,11 @@ class ClassLoader {
                        }
                } else {
                        // Not found
-                       //* NOISY-DEBUG: */ printf('[%s:%d] 404: %s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
+                       //* NOISY-DEBUG: */ printf('[%s:%d] 404: fileName=%s' . PHP_EOL, __METHOD__, __LINE__, $fileName);
                }
+
+               // Trace message
+               //* NOISY-DEBUG: */ printf('[%s:%d] EXIT!' . PHP_EOL, __METHOD__, __LINE__);
        }
 
 }