From 73ca38fa83bce927e162fb2afc36ebb855acdc9b Mon Sep 17 00:00:00 2001 From: dave_elmo Date: Fri, 11 Nov 2016 13:31:35 +1100 Subject: [PATCH 1/6] Add the ability to force-load alias classes on start-up, rather than using the AutoLoader to gracefully load classes on request. --- src/ClassAliasLoader.php | 15 +++++++++++++++ src/ClassAliasMapGenerator.php | 14 +++++++++++--- src/Config.php | 35 +++++++++++++++++++++------------- tests/Unit/ConfigTest.php | 1 + 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/ClassAliasLoader.php b/src/ClassAliasLoader.php index df4bbd5..39ea299 100644 --- a/src/ClassAliasLoader.php +++ b/src/ClassAliasLoader.php @@ -108,6 +108,21 @@ public function unregister() spl_autoload_unregister(array($this, 'loadClassWithAlias')); } + /** + * Alternative to using as an autoloader, which pre-loads all aliases. + * This does NOT perform any checks against the RealClassName, as classes are not auto-loaded with this function. + */ + public function registerAllAliases() + { + foreach($this->aliasMap['classNameToAliasMapping'] as $originalClassName) { + foreach ($this->aliasMap['classNameToAliasMapping'][$originalClassName] as $aliasClassName) { + if (!$this->classOrInterfaceExists($aliasClassName)) { + class_alias($originalClassName, $aliasClassName); + } + } + } + } + /** * Main class loading method registered with spl_autoload_register() * diff --git a/src/ClassAliasMapGenerator.php b/src/ClassAliasMapGenerator.php index 18113c1..279489a 100644 --- a/src/ClassAliasMapGenerator.php +++ b/src/ClassAliasMapGenerator.php @@ -107,8 +107,8 @@ public function generateAliasMap() } $mainPackageAliasLoaderConfig = new \TYPO3\ClassAliasLoader\Config($mainPackage); - $alwaysAddAliasLoader = $mainPackageAliasLoaderConfig->get('always-add-alias-loader'); - $caseSensitiveClassLoading = $mainPackageAliasLoaderConfig->get('autoload-case-sensitivity'); + $alwaysAddAliasLoader = $mainPackageAliasLoaderConfig->get(\TYPO3\ClassAliasLoader\Config::OPTION_ALWAYS_ADD_ALIAS_LOADER); + $caseSensitiveClassLoading = $mainPackageAliasLoaderConfig->get(\TYPO3\ClassAliasLoader\Config::OPTION_AUTOLOAD_IS_CASE_SENSITIVE); if (!$alwaysAddAliasLoader && !$classAliasMappingFound && $caseSensitiveClassLoading) { // No mapping found in any package and no insensitive class loading active. We return early and skip rewriting @@ -134,6 +134,10 @@ public function generateAliasMap() $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true'; + // Autoloader mode check + $autoloadMode = $mainPackageAliasLoaderConfig->get(\TYPO3\ClassAliasLoader\Config::OPTION_AUTOLOAD_MODE); + $autoloadModeForceAliasLoad = \TYPO3\ClassAliasLoader\Config::AUTOLOAD_MODE_FORCE_ALIAS_LOADING; + $aliasLoaderInitClassContent = <<setAliasMap(\$classAliasMap); \$classAliasLoader->setCaseSensitiveClassLoading($caseSensitiveClassLoadingString); - \$classAliasLoader->register($prependAutoloader); + if ($autoloadMode == $autoloadModeForceAliasLoad) { + \$classAliasLoader->registerAllAliases($prependAutoloader); + } else { + \$classAliasLoader->register($prependAutoloader); + } TYPO3\ClassAliasLoader\ClassAliasMap::setClassAliasLoader(\$classAliasLoader); diff --git a/src/Config.php b/src/Config.php index 0ef37a1..4627727 100644 --- a/src/Config.php +++ b/src/Config.php @@ -19,15 +19,24 @@ */ class Config { + const OPTION_CLASS_ALIAS_MAPS = 'class-alias-maps'; + const OPTION_ALWAYS_ADD_ALIAS_LOADER = 'always-add-alias-loader'; + const OPTION_AUTOLOAD_IS_CASE_SENSITIVE = 'autoload-case-sensitivity'; + const OPTION_AUTOLOAD_MODE = 'autoload-mode'; + + const AUTOLOAD_MODE_NORMAL = 'normal'; + const AUTOLOAD_MODE_FORCE_ALIAS_LOADING = 'force-alias-loading'; + /** * Default values * * @var array */ protected $config = array( - 'class-alias-maps' => null, - 'always-add-alias-loader' => false, - 'autoload-case-sensitivity' => true + self::OPTION_CLASS_ALIAS_MAPS => null, + self::OPTION_ALWAYS_ADD_ALIAS_LOADER => false, + self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE => true, + self::OPTION_AUTOLOAD_MODE => self::AUTOLOAD_MODE_NORMAL, ); /** @@ -76,14 +85,14 @@ public function get($configKey) protected function setAliasLoaderConfigFromPackage(PackageInterface $package) { $extraConfig = $this->handleDeprecatedConfigurationInPackage($package); - if (isset($extraConfig['typo3/class-alias-loader']['class-alias-maps'])) { - $this->config['class-alias-maps'] = (array)$extraConfig['typo3/class-alias-loader']['class-alias-maps']; + if (isset($extraConfig['typo3/class-alias-loader'][self::OPTION_CLASS_ALIAS_MAPS])) { + $this->config[self::OPTION_CLASS_ALIAS_MAPS] = (array)$extraConfig['typo3/class-alias-loader'][self::OPTION_CLASS_ALIAS_MAPS]; } - if (isset($extraConfig['typo3/class-alias-loader']['always-add-alias-loader'])) { - $this->config['always-add-alias-loader'] = (bool)$extraConfig['typo3/class-alias-loader']['always-add-alias-loader']; + if (isset($extraConfig['typo3/class-alias-loader'][self::OPTION_ALWAYS_ADD_ALIAS_LOADER])) { + $this->config[self::OPTION_ALWAYS_ADD_ALIAS_LOADER] = (bool)$extraConfig['typo3/class-alias-loader'][self::OPTION_ALWAYS_ADD_ALIAS_LOADER]; } - if (isset($extraConfig['typo3/class-alias-loader']['autoload-case-sensitivity'])) { - $this->config['autoload-case-sensitivity'] = (bool)$extraConfig['typo3/class-alias-loader']['autoload-case-sensitivity']; + if (isset($extraConfig['typo3/class-alias-loader'][self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE])) { + $this->config[self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE] = (bool)$extraConfig['typo3/class-alias-loader'][self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE]; } } @@ -106,15 +115,15 @@ protected function handleDeprecatedConfigurationInPackage(PackageInterface $pack ); } else { $extraConfig['typo3/class-alias-loader'] = array(); - if (isset($extraConfig['class-alias-maps'])) { - $extraConfig['typo3/class-alias-loader']['class-alias-maps'] = $extraConfig['class-alias-maps']; + if (isset($extraConfig[self::OPTION_CLASS_ALIAS_MAPS])) { + $extraConfig['typo3/class-alias-loader'][self::OPTION_CLASS_ALIAS_MAPS] = $extraConfig[self::OPTION_CLASS_ALIAS_MAPS]; $messages[] = sprintf( 'The package "%s" uses "class-alias-maps" section on top level, which is deprecated. Please move this config below the top level key "typo3/class-alias-loader" instead!', $package->getName() ); } - if (isset($extraConfig['autoload-case-sensitivity'])) { - $extraConfig['typo3/class-alias-loader']['autoload-case-sensitivity'] = $extraConfig['autoload-case-sensitivity']; + if (isset($extraConfig[self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE])) { + $extraConfig['typo3/class-alias-loader'][self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE] = $extraConfig[self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE]; $messages[] = sprintf( 'The package "%s" uses "autoload-case-sensitivity" section on top level, which is deprecated. Please move this config below the top level key "typo3/class-alias-loader" instead!', $package->getName() diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php index ed9d8ef..9343714 100644 --- a/tests/Unit/ConfigTest.php +++ b/tests/Unit/ConfigTest.php @@ -60,6 +60,7 @@ public function defaultConfigIsAppliedWhenNothingIsConfiguredInPackage() $this->assertFalse($this->subject->get('always-add-alias-loader')); $this->assertTrue($this->subject->get('autoload-case-sensitivity')); $this->assertNull($this->subject->get('class-alias-maps')); + $this->assertEquals('normal', $this->subject->get('autoload-mode')); } /** From a7dc80f1065bfe08fd7131977054512d370e2b8a Mon Sep 17 00:00:00 2001 From: dave_elmo Date: Fri, 11 Nov 2016 13:36:20 +1100 Subject: [PATCH 2/6] Updated readme for autoloader mode changes. --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 13bebdc..332f692 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,18 @@ Therefore it is possible to set the following option in your *root* `composer.js }, ``` +In cases where another autoloader conflicts with the alias autoloader, you may find it helpful to bypass the autoloader +entirely, and choose to instead force the loading of all known aliases at boot. + +``` + "extra": { + "typo3/class-alias-loader": { + "autoloader-mode": "force-alias-loading" + } + }, +``` +This method of loading aliases may incur a significant performance hit if you have a large number of classes aliased. +The class aliases are also established without loading the classes themselves. ## Using the API From 0f993c85cf1c3c5a238c91062943c230bb815573 Mon Sep 17 00:00:00 2001 From: dave_elmo Date: Fri, 11 Nov 2016 14:10:28 +1100 Subject: [PATCH 3/6] Changed method of defining if force-alias-loading has been requested. --- src/ClassAliasLoader.php | 21 +++++++++++++++++++-- src/ClassAliasMapGenerator.php | 9 +++------ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/ClassAliasLoader.php b/src/ClassAliasLoader.php index 39ea299..32afff7 100644 --- a/src/ClassAliasLoader.php +++ b/src/ClassAliasLoader.php @@ -36,6 +36,11 @@ class ClassAliasLoader */ protected $caseSensitiveClassLoading = true; + /** + * @var bool + */ + protected $forceAliasLoading = false; + /** * @param ComposerClassLoader $composerClassLoader */ @@ -62,6 +67,14 @@ public function setCaseSensitiveClassLoading($caseSensitiveClassLoading) $this->caseSensitiveClassLoading = $caseSensitiveClassLoading; } + /** + * @param boolean $forceAliasLoading + */ + public function setForceAliasLoading($forceAliasLoading) + { + $this->forceAliasLoading = $forceAliasLoading; + } + /** * Adds an alias map and merges it with already available map * @@ -96,8 +109,12 @@ public function getClassNameForAlias($aliasOrClassName) */ public function register($prepend = false) { - $this->composerClassLoader->unregister(); - spl_autoload_register(array($this, 'loadClassWithAlias'), true, $prepend); + if ($this->forceAliasLoading) { + $this->registerAllAliases(); + } else { + $this->composerClassLoader->unregister(); + spl_autoload_register(array($this, 'loadClassWithAlias'), true, $prepend); + } } /** diff --git a/src/ClassAliasMapGenerator.php b/src/ClassAliasMapGenerator.php index 279489a..8c6fd60 100644 --- a/src/ClassAliasMapGenerator.php +++ b/src/ClassAliasMapGenerator.php @@ -136,7 +136,7 @@ public function generateAliasMap() // Autoloader mode check $autoloadMode = $mainPackageAliasLoaderConfig->get(\TYPO3\ClassAliasLoader\Config::OPTION_AUTOLOAD_MODE); - $autoloadModeForceAliasLoad = \TYPO3\ClassAliasLoader\Config::AUTOLOAD_MODE_FORCE_ALIAS_LOADING; + $forceAliasLoading = ($autoloadMode == \TYPO3\ClassAliasLoader\Config::AUTOLOAD_MODE_FORCE_ALIAS_LOADING); $aliasLoaderInitClassContent = <<setAliasMap(\$classAliasMap); \$classAliasLoader->setCaseSensitiveClassLoading($caseSensitiveClassLoadingString); - if ($autoloadMode == $autoloadModeForceAliasLoad) { - \$classAliasLoader->registerAllAliases($prependAutoloader); - } else { - \$classAliasLoader->register($prependAutoloader); - } + \$classAliasLoader->setForceAliasLoading($forceAliasLoading); + \$classAliasLoader->register($prependAutoloader); TYPO3\ClassAliasLoader\ClassAliasMap::setClassAliasLoader(\$classAliasLoader); From 46944321d5de74c861917b9b93613128d4866e37 Mon Sep 17 00:00:00 2001 From: dave_elmo Date: Fri, 11 Nov 2016 14:15:48 +1100 Subject: [PATCH 4/6] Fixed bad true/false string provision --- src/ClassAliasMapGenerator.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ClassAliasMapGenerator.php b/src/ClassAliasMapGenerator.php index 8c6fd60..482faa2 100644 --- a/src/ClassAliasMapGenerator.php +++ b/src/ClassAliasMapGenerator.php @@ -137,6 +137,7 @@ public function generateAliasMap() // Autoloader mode check $autoloadMode = $mainPackageAliasLoaderConfig->get(\TYPO3\ClassAliasLoader\Config::OPTION_AUTOLOAD_MODE); $forceAliasLoading = ($autoloadMode == \TYPO3\ClassAliasLoader\Config::AUTOLOAD_MODE_FORCE_ALIAS_LOADING); + $forceAliasLoadingString = $forceAliasLoading ? 'true' : 'false'; $aliasLoaderInitClassContent = <<setAliasMap(\$classAliasMap); \$classAliasLoader->setCaseSensitiveClassLoading($caseSensitiveClassLoadingString); - \$classAliasLoader->setForceAliasLoading($forceAliasLoading); + \$classAliasLoader->setForceAliasLoading($forceAliasLoadingString); \$classAliasLoader->register($prependAutoloader); TYPO3\ClassAliasLoader\ClassAliasMap::setClassAliasLoader(\$classAliasLoader); From 6aa6b6b4ad54f5792e4375afa801529b8de1f98c Mon Sep 17 00:00:00 2001 From: dave_elmo Date: Fri, 11 Nov 2016 15:05:46 +1100 Subject: [PATCH 5/6] Fixed Config variable for "autoload-mode" not getting loaded correctly. Added unit tests for "autoload-mode" config variable. Changed how configurations are loaded/cast, to simplify adding additional configuration options. --- src/Config.php | 44 +++++++++++++++++++++++++++++++-------- tests/Unit/ConfigTest.php | 3 +++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/Config.php b/src/Config.php index 4627727..4113bbc 100644 --- a/src/Config.php +++ b/src/Config.php @@ -28,7 +28,7 @@ class Config const AUTOLOAD_MODE_FORCE_ALIAS_LOADING = 'force-alias-loading'; /** - * Default values + * Default config values * * @var array */ @@ -39,6 +39,18 @@ class Config self::OPTION_AUTOLOAD_MODE => self::AUTOLOAD_MODE_NORMAL, ); + /** + * Config cast types + * + * @var array + */ + protected $configCastType = array( + self::OPTION_CLASS_ALIAS_MAPS => 'array', + self::OPTION_ALWAYS_ADD_ALIAS_LOADER => 'bool', + self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE => 'bool', + self::OPTION_AUTOLOAD_MODE => 'string', + ); + /** * @var IOInterface */ @@ -85,14 +97,28 @@ public function get($configKey) protected function setAliasLoaderConfigFromPackage(PackageInterface $package) { $extraConfig = $this->handleDeprecatedConfigurationInPackage($package); - if (isset($extraConfig['typo3/class-alias-loader'][self::OPTION_CLASS_ALIAS_MAPS])) { - $this->config[self::OPTION_CLASS_ALIAS_MAPS] = (array)$extraConfig['typo3/class-alias-loader'][self::OPTION_CLASS_ALIAS_MAPS]; - } - if (isset($extraConfig['typo3/class-alias-loader'][self::OPTION_ALWAYS_ADD_ALIAS_LOADER])) { - $this->config[self::OPTION_ALWAYS_ADD_ALIAS_LOADER] = (bool)$extraConfig['typo3/class-alias-loader'][self::OPTION_ALWAYS_ADD_ALIAS_LOADER]; - } - if (isset($extraConfig['typo3/class-alias-loader'][self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE])) { - $this->config[self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE] = (bool)$extraConfig['typo3/class-alias-loader'][self::OPTION_AUTOLOAD_IS_CASE_SENSITIVE]; + + foreach ($this->configCastType as $key => $type) { + + if (isset($extraConfig['typo3/class-alias-loader'][$key])) { + $value = $extraConfig['typo3/class-alias-loader'][$key]; + + // Cast correct type + switch ($type) { + case 'bool': + $value = (bool) $value; + break; + case 'array': + $value = (array) $value; + break; + case 'string': + $value = (string) $value; + break; + } + + // Save value + $this->config[$key] = $value; + } } } diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php index 9343714..be5b961 100644 --- a/tests/Unit/ConfigTest.php +++ b/tests/Unit/ConfigTest.php @@ -114,6 +114,7 @@ public function otherConfigIsExtracted() 'typo3/class-alias-loader' => array( 'always-add-alias-loader' => true, 'autoload-case-sensitivity' => false, + 'autoload-mode' => 'test', ) ) ); @@ -122,6 +123,7 @@ public function otherConfigIsExtracted() $this->assertTrue($subject->get('always-add-alias-loader')); $this->assertFalse($subject->get('autoload-case-sensitivity')); + $this->assertEquals('test', $subject->get('autoload-mode')); } /** @@ -134,6 +136,7 @@ public function otherConfigIsExtractedFromDeprecatedKey() 'helhum/class-alias-loader' => array( 'always-add-alias-loader' => true, 'autoload-case-sensitivity' => false, + ) ) ); From 84585b8635c8120e845b13c12444e9be5722d07f Mon Sep 17 00:00:00 2001 From: dave_elmo Date: Fri, 11 Nov 2016 15:11:09 +1100 Subject: [PATCH 6/6] Fixed incorrect class loading by key. --- src/ClassAliasLoader.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ClassAliasLoader.php b/src/ClassAliasLoader.php index 32afff7..475fa35 100644 --- a/src/ClassAliasLoader.php +++ b/src/ClassAliasLoader.php @@ -131,8 +131,8 @@ public function unregister() */ public function registerAllAliases() { - foreach($this->aliasMap['classNameToAliasMapping'] as $originalClassName) { - foreach ($this->aliasMap['classNameToAliasMapping'][$originalClassName] as $aliasClassName) { + foreach($this->aliasMap['classNameToAliasMapping'] as $originalClassName => $maps) { + foreach ($maps as $aliasClassName) { if (!$this->classOrInterfaceExists($aliasClassName)) { class_alias($originalClassName, $aliasClassName); }