Last active
July 30, 2023 07:43
-
-
Save AndryG/9325f36a9350f2f7ccdef002c2aa0882 to your computer and use it in GitHub Desktop.
Case insensitive autoload using composer generated classmap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Case insensitive autoload using composer generated classmap | |
* | |
* see problem: | |
* - https://github.com/composer/composer/issues/1803 | |
* - https://stackoverflow.com/questions/20235922/how-to-add-case-insensitive-autoloading-using-composer-generated-classmap | |
* | |
* 1. Add this class to project. (you can set any namespace) | |
* 2. Add to composer.json section "scripts" | |
* "scripts": { | |
* "post-autoload-dump": ["CaseIgnoreAutoloader::onPostAutoloadDump"] | |
* } | |
* 3. run dump-autoload with create classmap | |
* 4. view vendor/autoload.php (append registration addition autoloader) | |
* - addition classmap ignore VENDOR dir | |
* - autoloader not generated when classmap is empty | |
* - for temporary disable function you can use key 'map-case-ignore' in 'extra' section (default true) | |
* "extra": { | |
* "map-case-ignore": true | |
* } | |
* | |
* 5. How to reproduce this as a plugin? Behavioral change is a mystery. | |
* | |
* update 09 jul 2022 | |
* Put an additional autoloader in the beginning. | |
* Now the param "prepend-autoloader" can be used to determine the order in which loaders work. | |
* | |
* @author https://gist.github.com/AndryG | |
* @license MIT | |
*/ | |
use Composer\Script\Event; | |
class CaseIgnoreAutoloader { | |
/** | |
* @param Event $event | |
*/ | |
public static function onPostAutoloadDump(Event $event) { | |
$isActive = $event->getComposer()->getPackage()->getExtra()['map-case-ignore'] ?? true; | |
$vendorDir = $event->getComposer()->getConfig()->get('vendor-dir'); | |
$camelMapFile = $vendorDir.'/composer/autoload_classmap.php'; | |
$lowMapFile = $vendorDir.'/composer/autoload_classmap_case_ignore.php'; | |
$baseDirNameLen = mb_strlen(dirname($vendorDir)) + 1; | |
$lowMap = []; | |
if ($isActive) { // generate low str map | |
foreach (require $camelMapFile as $k => $v) { | |
if (0 !== strpos($v, $vendorDir)) { // except vendor | |
$lowMap[mb_strtolower($k)] = mb_substr($v, $baseDirNameLen); | |
} | |
} | |
$isActive = (bool)$lowMap; // disable of empty low str map | |
} | |
if ($isActive) { // modify autoloader.php and save addition classmap | |
file_put_contents($lowMapFile, sprintf('<?'.'php return %s;', var_export($lowMap, true))); | |
$anchor = 'require_once __DIR__ . \'/composer/autoload_real.php\';'; | |
$script = <<<'AUTOLOADER' | |
// insert by CaseIgnoreAutoloader | |
spl_autoload_register(function($class){ | |
static $lowMap; | |
$lowMap ??= require(__DIR__.'/composer/autoload_classmap_case_ignore.php'); | |
if($file = $lowMap[mb_strtolower($class)] ?? false){ | |
include(__dir__.'/../'.$file); | |
return true; | |
} | |
return null; | |
}); | |
AUTOLOADER; | |
// update autoload.php | |
$fName = $vendorDir.'/autoload.php'; | |
$content = file_get_contents($fName); | |
$content = str_replace($anchor, $script.$anchor, $content); | |
file_put_contents($fName, $content); | |
} | |
if (!$isActive) { | |
unlink($lowMapFile); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment