Skip to content

Instantly share code, notes, and snippets.

@forsvunnet
Last active February 3, 2022 07:36
Show Gist options
  • Save forsvunnet/e472e03a23be75cc12f3f71e0dace7e3 to your computer and use it in GitHub Desktop.
Save forsvunnet/e472e03a23be75cc12f3f71e0dace7e3 to your computer and use it in GitHub Desktop.
Module loader script for composer
<?php
namespace App\Support;
class ComposerModuleAutoLoader
{
public static function load($event)
{
$package = $event->getComposer()->getPackage();
$base_path = dirname(__DIR__, 2).'/';
$dirs = glob(
$base_path.'modules/*',
GLOB_ONLYDIR
);
$paths = array_map(
fn($dir) => str_replace($base_path, '', $dir),
$dirs
);
$autoload = $package->getAutoload();
$autoload['psr-4'] = array_merge(
$autoload['psr-4'],
self::generatePsr4($paths, false)
);
$package->setAutoload($autoload);
$autoloadDev = $package->getDevAutoload();
$autoloadDev['psr-4'] = array_merge(
$autoloadDev['psr-4'],
self::generatePsr4($paths, true)
);
$package->setDevAutoload($autoloadDev);
$configSource = $event->getComposer()->getConfig()->getConfigSource();
self::updateComposerJson($configSource, 'autoload', $autoload);
self::updateComposerJson($configSource, 'autoload-dev', $autoloadDev);
self::reformatComposerJson($configSource->getName());
}
private static function generatePsr4(array $paths, bool $dev): array
{
$psr4 = [];
foreach ($paths as $path) {
$namespaces = self::getNamespacesFromPath($path, $dev);
$psr4 = array_merge(
$psr4,
$namespaces
);
}
return $psr4;
}
private static function getNamespacesFromPath(string $path, bool $dev): array
{
// Get the relative path and the namespace name for each module directory.
$name = str_replace("modules/", '', $path);
if (!preg_match('/^[A-Z][\w]*$/', $name)) {
return [];
}
$namespaces = [];
if (! $dev && file_exists("$path/src") && is_dir("$path/src")) {
$namespaces["Modules\\$name\\"] = "$path/src";
}
if ($dev && file_exists("$path/tests") && is_dir("$path/tests")) {
$namespaces["Modules\\$name\\Tests\\"] = "$path/tests";
}
return $namespaces;
}
private static function updateComposerJson($configSource, string $key, array $autoload)
{
// Add a placeholder so that the key "autoload" is not removed when removing psr-4.
$configSource->addLink($key, 'tmp', 'placeholder');
$configSource->removeLink($key, 'psr-4');
// Add back psr-4 after changes and remove the placeholder key.
$configSource->addLink($key, 'psr-4', $autoload['psr-4']);
$configSource->removeLink($key, 'tmp');
}
private static function reformatComposerJson(string $filename)
{
// Read the composer.json and re-format it to fix indentation.
$content = file_get_contents($filename);
$json = json_encode(
json_decode($content, true),
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
);
if (!$json) {
return;
}
file_put_contents(
$filename,
$json
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment