// Import framework stuff
use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
-use Org\Mxchange\CoreFramework\Configuration\FrameworkConfiguration;
+use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
// Import SPL stuff
use \InvalidArgumentException;
* This class loads class include files with a specific prefix and suffix
*
* @author Roland Haeder <webmaster@shipsimu.org>
- * @version 1.5.0
- * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
+ * @version 1.6.0
+ * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2022 Core Developer Team
* @license GNU GPL 3.0 or any newer version
* @link http://www.shipsimu.org
*
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ----------------------------------
- * 1.5
+ * 1.6.0
+ * - This class loader is now 100% singleton, no other instance is really
+ * required, therefore the factory method can be removed safely
+ * - renamed initLoader() to initClassLoader()
+ * - An instance of a FrameworkConfiguration is no longer set here as this
+ * violated the rule that there shall be no instance set of that class
+ * - .htaccess is marked as deprecated as this should be no longer done
+ * - scanClassPath() is now protected, please use other scan*() methods
+ * 1.5.0
* - Namespace scheme Project\Package[\SubPackage...] is fully supported and
* throws an InvalidArgumentException if not present. The last part will be
* always the class' name.
- * 1.4
+ * 1.4.0
* - Some comments improved, other minor improvements
- * 1.3
+ * 1.3.0
* - Constructor is now empty and factory method 'createClassLoader' is created
* - renamed loadClasses to scanClassPath
* - Added initLoader()
- * 1.2
+ * 1.2.0
* - ClassLoader rewritten to PHP SPL's own RecursiveIteratorIterator class
- * 1.1
+ * 1.1.0
* - loadClasses rewritten to fix some notices
- * 1.0
+ * 1.0.0
* - Initial release
* ----------------------------------
*/
-class ClassLoader {
+final class ClassLoader {
/**
* Instance of this class
*/
private static $selfInstance = NULL;
/**
- * Array with all found classes
+ * Cached configuration entry 'developer_mode_enabled'
*/
- private $foundClasses = array();
+ private static $developerModeEnabled = false;
+
+ /**
+ * Array with all valid but pending for loading file names (class,
+ * interfaces, traits must start with below prefix).
+ */
+ private $pendingFiles = [];
/**
* List of loaded classes
*/
- private $loadedClasses = array();
+ private $loadedClasses = [];
/**
* Suffix with extension for all class files
* A list for directory names (no leading/trailing slashes!) which not be scanned by the path scanner
* @see scanLocalPath
*/
- private $ignoreList = array();
+ private $ignoreList = [];
/**
* Debug this class loader? (true = yes, false = no)
/**
* Framework/application paths for classes, etc.
*/
- private static $frameworkPaths = array(
+ private static $frameworkPaths = [
+ 'classes', // Classes
'exceptions', // Exceptions
'interfaces', // Interfaces
- 'classes', // Classes
- 'middleware' // The middleware
- );
+ 'middleware', // The middleware
+ 'traits', // Traits
+ ];
/**
* Registered paths where test classes can be found. These are all relative
* to base_path .
*/
- private static $testPaths = array();
+ private static $testPaths = [];
/**
* The protected constructor. Please use the factory method below, or use
*
* @return void
*/
- protected function __construct () {
- // This is empty for now
+ private function __construct () {
+ // Cache config entry
+ self::$developerModeEnabled = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('developer_mode_enabled');
}
/**
*/
public function __destruct () {
// Skip here if dev-mode
- if (defined('DEVELOPER')) {
+ if (self::$developerModeEnabled) {
return;
- } // END - if
+ }
// 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');
// And write whole list
$fileObject->fwrite($cacheContent);
- } // END - if
+ }
// Skip here if already cached
if ($this->classesCached === false) {
// Load the file
// @TODO Add some uglifying code (compress) here
$cacheContent .= $fileObject->fread($fileInstance->getSize());
- } // END - foreach
+ }
// Open file
$fileObject = $this->classCacheFile->openFile('w');
// And write it away
$fileObject->fwrite($cacheContent);
- } // END - if
- }
-
- /**
- * Creates an instance of this class loader for given configuration instance
- *
- * @param $configInstance Configuration class instance
- * @return void
- */
- public static final function createClassLoader (FrameworkConfiguration $configInstance) {
- // Get a new instance
- $loaderInstance = new ClassLoader();
-
- // Init the instance
- $loaderInstance->initLoader($configInstance);
-
- // Return the prepared instance
- return $loaderInstance;
+ }
}
/**
* @return void
*/
public static function scanFrameworkClasses () {
- // Trace message
- //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
-
// Get loader instance
+ //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
$loaderInstance = self::getSelfInstance();
- // Get config 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) {
- // Debug message
- //* NOISY-DEBUG: */ printf('[%s:%d]: shortPath=%s' . PHP_EOL, __METHOD__, __LINE__, $shortPath);
-
// Generate full path from it
+ //* 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
));
- // Debug message
- //* NOISY-DEBUG: */ printf('[%s:%d]: realPathName=%s' . PHP_EOL, __METHOD__, __LINE__, $realPathName);
-
// Is it not false and accessible?
+ //* 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
// Try to load the framework classes
$loaderInstance->scanClassPath($realPathName);
- } // END - foreach
+ }
// Trace message
//* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__);
* @return void
*/
public static function scanApplicationClasses () {
- // Trace message
- //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
-
// Get loader instance
+ //* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
$loaderInstance = self::getSelfInstance();
- // Get config instance
+ // "Cache" configuration instance
$configInstance = FrameworkBootstrap::getConfigurationInstance();
// Load all classes for the application
foreach (self::$frameworkPaths as $shortPath) {
- // Debug message
- //* NOISY-DEBUG: */ printf('[%s:%d]: shortPath=%s' . PHP_EOL, __METHOD__, __LINE__, $shortPath);
-
// Create path name
+ //* NOISY-DEBUG: */ printf('[%s:%d]: shortPath=%s' . PHP_EOL, __METHOD__, __LINE__, $shortPath);
$pathName = realpath(sprintf(
'%s%s%s%s%s',
$configInstance->getConfigEntry('application_base_path'),
DIRECTORY_SEPARATOR,
- $configInstance->getConfigEntry('detected_app_name'),
+ FrameworkBootstrap::getDetectedApplicationName(),
DIRECTORY_SEPARATOR,
$shortPath
));
- // Debug message
- //* NOISY-DEBUG: */ printf('[%s:%d]: pathName[%s]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($pathName), $pathName);
-
// Is the path readable?
+ //* NOISY-DEBUG: */ printf('[%s:%d]: pathName[%s]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($pathName), $pathName);
if (is_dir($pathName)) {
// Try to load the application classes
$loaderInstance->scanClassPath($pathName);
- } // END - if
- } // END - foreach
+ }
+ }
// Trace message
//* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__);
* @return void
*/
public static function scanTestsClasses () {
- // Trace message
+ // "Cache" configuration instance
//* NOISY-DEBUG: */ printf('[%s:%d]: CALLED!' . PHP_EOL, __METHOD__, __LINE__);
-
- // Get config instance
$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'),
$shortPath
);
- // Debug message
- //* NOISY-DEBUG: */ printf('[%s:%d]: pathName[%s]=%s - BEFORE!' . PHP_EOL, __METHOD__, __LINE__, gettype($pathName), $pathName);
-
// Try to find it
+ //* NOISY-DEBUG: */ printf('[%s:%d]: pathName[%s]=%s - BEFORE!' . PHP_EOL, __METHOD__, __LINE__, gettype($pathName), $pathName);
$realPathName = realpath($pathName);
- // Debug message
- //* NOISY-DEBUG: */ printf('[%s:%d]: realPathName[%s]=%s - AFTER!' . PHP_EOL, __METHOD__, __LINE__, gettype($realPathName), $realPathName);
-
// Is the path readable?
+ //* NOISY-DEBUG: */ printf('[%s:%d]: realPathName[%s]=%s - AFTER!' . PHP_EOL, __METHOD__, __LINE__, gettype($realPathName), $realPathName);
if ((is_dir($realPathName)) && (is_readable($realPathName))) {
// Try to load the application classes
ClassLoader::getSelfInstance()->scanClassPath($realPathName);
- } // END - if
- } // END - foreach
+ }
+ }
// Trace message
//* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__);
* @param $strictNamingConvention Whether to strictly check naming-convention
* @return void
*/
- public static function enableStrictNamingConventionCheck ($strictNamingConvention = true) {
+ public static function enableStrictNamingConventionCheck (bool $strictNamingConvention = true) {
self::$strictNamingConvention = $strictNamingConvention;
}
*
* @param $relativePath Relative path to test classes
* @return void
+ * @throws InvalidArgumentException If a parameter is invalid or path not found
*/
- public static function registerTestsPath ($relativePath) {
- // Trace message
+ public static function registerTestsPath (string $relativePath) {
+ // Validate parameter
//* NOISY-DEBUG: */ printf('[%s:%d]: relativePath=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $relativePath);
+ if (empty($relativePath)) {
+ // Should not be empty
+ throw new InvalidArgumentException('Parameter "relativePath" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ }
+
+ // Get real path from it
+ $fullQualifiedPath = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('root_base_path') . $relativePath;
+
+ // Is it there?
+ //* NOISY-DEBUG: */ printf('[%s:%d]: fullQualifiedPath=%s' . PHP_EOL, __METHOD__, __LINE__, $fullQualifiedPath);
+ if (!is_dir($fullQualifiedPath)) {
+ // Not there
+ throw new InvalidArgumentException(sprintf('fullQualifiedPath=%s cannot be found', $fullQualifiedPath));
+ } elseif (!is_readable($fullQualifiedPath)) {
+ // Not readable
+ throw new InvalidArgumentException(sprintf('fullQualifiedPath=%s is not readable', $fullQualifiedPath));
+ }
// "Register" it
+ //* NOISY-DEBUG: */ printf('[%s:%d]: Adding relativePath=%s ...' . PHP_EOL, __METHOD__, __LINE__, $relativePath);
self::$testPaths[$relativePath] = $relativePath;
// Trace message
*
* @param $className Name of the class to load
* @return void
+ * @throws InvalidArgumentException If the class' name does not contain a namespace: Tld\Domain\Project is AT LEAST recommended!
*/
- public static function autoLoad ($className) {
- // Trace message
- //* NOISY-DEBUG: */ printf('[%s:%d]: className=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $className);
+ public static function autoLoad (string $className) {
+ // 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', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ }
+
+ // 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
+ //* NOISY-DEBUG: */ printf('[%s:%d]: self::strictNamingConvention=%d,classNameParts()=%d' . PHP_EOL, __METHOD__, __LINE__, intval(self::$strictNamingConvention), count($classNameParts));
+ if ((self::$strictNamingConvention === true) && (count($classNameParts) < 5)) {
+ // 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
public static final function getSelfInstance () {
// Is the instance there?
if (is_null(self::$selfInstance)) {
- // Get a new one
- self::$selfInstance = ClassLoader::createClassLoader(FrameworkBootstrap::getConfigurationInstance());
- } // END - if
+ // Get a new one and initialize it
+ self::$selfInstance = new ClassLoader();
+ self::$selfInstance->initClassLoader();
+ }
// Return the instance
return self::$selfInstance;
}
+ /**
+ * Getter for total include counter
+ *
+ * @return $total Total loaded include files
+ */
+ public final function getTotal () {
+ return $this->total;
+ }
+
+ /**
+ * Getter for a printable list of included main/interfaces/exceptions
+ *
+ * @param $includeList A printable include list
+ */
+ public function getPrintableIncludeList () {
+ // Prepare the list
+ $includeList = '';
+ foreach ($this->loadedClasses as $classFile) {
+ $includeList .= basename($classFile) . '<br />' . PHP_EOL;
+ }
+
+ // And return it
+ return $includeList;
+ }
+
/**
* Scans recursively a local path for class files which must have a prefix and a suffix as given by $this->suffix and $this->prefix
*
* @param $basePath The relative base path to 'framework_base_path' constant for all classes
* @param $ignoreList An optional list (array forced) of directory and file names which shall be ignored
* @return void
+ * @throws InvalidArgumentException If a parameter is invalid
*/
- public function scanClassPath ($basePath, array $ignoreList = array() ) {
+ protected function scanClassPath (string $basePath, array $ignoreList = [] ) {
// Is a list has been restored from cache, don't read it again
- if ($this->listCached === true) {
+ //* NOISY-DEBUG: */ printf('[%s:%d] basePath=%s,ignoreList()=%d - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $basePath, count($ignoreList));
+ if (empty($basePath)) {
+ // Throw IAE
+ throw new InvalidArgumentException('Parameter "basePath" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
+ } elseif ($this->listCached === true) {
// Abort here
+ //* NOISY-DEBUG: */ printf('[%s:%d] this->listCache=true - EXIT!' . PHP_EOL, __METHOD__, __LINE__);
return;
- } // END - if
-
- // Keep it in class for later usage
- $this->ignoreList = $ignoreList;
+ }
- /*
- * Ignore .htaccess by default as it is for protection of directories
- * on Apache servers.
- */
- array_push($ignoreList, '.htaccess');
+ // Keep it in class for later usage, but flip index<->value
+ $this->ignoreList = array_flip($ignoreList);
/*
* Set base directory which holds all our classes, an absolute path
$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);
$currentEntry = $iteratorInstance->current();
// Get filename from iterator which is the class' name (according naming-convention)
- $fileName = $currentEntry->getFileName();
+ $fileName = $currentEntry->getFilename();
// Current entry must be a file, not smaller than 100 bytes and not on ignore list
- if ((!$currentEntry->isFile()) || (in_array($fileName, $this->ignoreList)) || ($currentEntry->getSize() < 100)) {
+ if (!$currentEntry->isFile() || isset($this->ignoreList[$fileName]) || $currentEntry->getSize() < 100) {
// Advance to next entry
$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;
- } // END - if
+ }
// 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();
- } // END - while
+ }
+
+ // Trace message
+ //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__);
}
/**
* Initializes our loader class
*
- * @param $configInstance Configuration class instance
* @return void
*/
- private function initLoader (FrameworkConfiguration $configInstance) {
- // Set configuration instance
- $this->configInstance = $configInstance;
-
+ private function initClassLoader () {
// Construct the FQFN for the cache
- if (!defined('DEVELOPER')) {
- $this->listCacheFile = new SplFileInfo($this->configInstance->getConfigEntry('local_database_path') . 'list-' . $this->configInstance->getConfigEntry('detected_app_name') . '.cache');
- $this->classCacheFile = new SplFileInfo($this->configInstance->getConfigEntry('local_database_path') . 'class-' . $this->configInstance->getConfigEntry('detected_app_name') . '.cache');
- } // END - if
+ if (!self::$developerModeEnabled) {
+ // Init cache instances
+ $this->listCacheFile = new SplFileInfo(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('local_database_path') . 'list-' . FrameworkBootstrap::getDetectedApplicationName() . '.cache');
+ $this->classCacheFile = new SplFileInfo(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('local_database_path') . 'class-' . FrameworkBootstrap::getDetectedApplicationName() . '.cache');
+ }
// Set suffix and prefix from configuration
- $this->suffix = $configInstance->getConfigEntry('class_suffix');
- $this->prefix = $configInstance->getConfigEntry('class_prefix');
+ $this->suffix = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('class_suffix');
+ $this->prefix = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('class_prefix');
// Set own instance
self::$selfInstance = $this;
// Skip here if no dev-mode
- if (defined('DEVELOPER')) {
+ if (self::$developerModeEnabled) {
return;
- } // END - if
+ }
// 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;
- } // END - if
+ }
// Does the class cache exist?
if (FrameworkBootstrap::isReadableFile($this->classCacheFile)) {
// Mark the class cache as loaded
$this->classesCached = true;
- } // END - if
+ }
}
/**
- * 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
- * @throws InvalidArgumentException If strict-checking is enabled and class name is not following naming-convention
*/
- private function loadClassFile ($className) {
- // Trace message
- //* NOISY-DEBUG: */ printf('[%s:%d] className=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $className);
-
+ private function loadClassFile (string $className) {
// The class name should contain at least 2 back-slashes, so split at them
+ //* NOISY-DEBUG: */ printf('[%s:%d] className=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $className);
$classNameParts = explode("\\", $className);
- // At least 3 parts should be there
- if ((self::$strictNamingConvention === true) && (count($classNameParts) < 5)) {
- // Namespace scheme is: Project\Package[\SubPackage...]
- throw new InvalidArgumentException(sprintf('Class name "%s" is not conform to naming-convention: Tld\Domain\Project\Package[\SubPackage...]\SomeFooBar', $className));
- } // END - if
-
// Get last element
$shortClassName = array_pop($classNameParts);
$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 (!defined('DEVELOPER')) {
+ if (!self::$developerModeEnabled) {
// Reset cache
//* NOISY-DEBUG: */ printf('[%s:%d] classesCached=false' . PHP_EOL, __METHOD__, __LINE__);
$this->classesCached = false;
- } // END - if
+ }
} 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);
}
- }
-
- /**
- * Getter for total include counter
- *
- * @return $total Total loaded include files
- */
- public final function getTotal () {
- return $this->total;
- }
- /**
- * Getter for a printable list of included main/interfaces/exceptions
- *
- * @param $includeList A printable include list
- */
- public function getPrintableIncludeList () {
- // Prepare the list
- $includeList = '';
- foreach ($this->loadedClasses as $classFile) {
- $includeList .= basename($classFile) . '<br />' . PHP_EOL;
- } // END - foreach
-
- // And return it
- return $includeList;
+ // Trace message
+ //* NOISY-DEBUG: */ printf('[%s:%d] EXIT!' . PHP_EOL, __METHOD__, __LINE__);
}
}