diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 4a186e5..76d61cd 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -12,9 +12,6 @@ $class $class - - include __DIR__ . '/../../../autoload.php' - load @@ -31,25 +28,10 @@ $loaded[$class] - - ClassLoader - $namespaces[$check] $namespaces[$check] - - include __DIR__ . '/../../../autoload.php' - include __DIR__ . '/../vendor/autoload.php' - include getenv('COMPOSER_VENDOR_DIR') . '/autoload.php' - - - getenv('COMPOSER_VENDOR_DIR') - getenv('COMPOSER_VENDOR_DIR') - - - include getenv('COMPOSER_VENDOR_DIR') . '/autoload.php' - diff --git a/src/Autoloader.php b/src/Autoloader.php index 261bb88..84f9406 100644 --- a/src/Autoloader.php +++ b/src/Autoloader.php @@ -11,6 +11,7 @@ use function class_exists; use function explode; use function file_exists; +use function getenv; use function interface_exists; use function spl_autoload_register; use function strlen; @@ -23,6 +24,9 @@ */ class Autoloader { + private const UPSTREAM_COMPOSER_VENDOR_DIRECTORY = __DIR__ . '/../../..'; + private const LOCAL_COMPOSER_VENDOR_DIRECTORY = __DIR__ . '/../vendor'; + /** * Attach autoloaders for managing legacy ZF artifacts. * @@ -41,10 +45,15 @@ class Autoloader public static function load() { $loaded = new ArrayObject([]); + $classLoader = self::getClassLoader(); + + if ($classLoader === null) { + return; + } spl_autoload_register(self::createPrependAutoloader( RewriteRules::namespaceReverse(), - self::getClassLoader(), + $classLoader, $loaded ), true, true); @@ -54,25 +63,15 @@ public static function load() )); } - /** - * @return ClassLoader - * @throws RuntimeException - */ - private static function getClassLoader() + private static function getClassLoader(): ?ClassLoader { - if (getenv('COMPOSER_VENDOR_DIR') && file_exists(getenv('COMPOSER_VENDOR_DIR') . '/autoload.php')) { - return include getenv('COMPOSER_VENDOR_DIR') . '/autoload.php'; - } - - if (file_exists(__DIR__ . '/../../../autoload.php')) { - return include __DIR__ . '/../../../autoload.php'; - } - - if (file_exists(__DIR__ . '/../vendor/autoload.php')) { - return include __DIR__ . '/../vendor/autoload.php'; + $composerVendorDirectory = getenv('COMPOSER_VENDOR_DIR'); + if (is_string($composerVendorDirectory)) { + return self::getClassLoaderFromVendorDirectory($composerVendorDirectory); } - throw new RuntimeException('Cannot detect composer autoload. Please run composer install'); + return self::getClassLoaderFromVendorDirectory(self::UPSTREAM_COMPOSER_VENDOR_DIRECTORY) + ?? self::getClassLoaderFromVendorDirectory(self::LOCAL_COMPOSER_VENDOR_DIRECTORY); } /** @@ -163,4 +162,20 @@ class_alias($alias, $class); } }; } + + private static function getClassLoaderFromVendorDirectory(string $composerVendorDirectory): ?ClassLoader + { + $filename = rtrim($composerVendorDirectory, '/') . '/autoload.php'; + if (!file_exists($filename)) { + return null; + } + + /** @psalm-suppress MixedAssignment */ + $loader = include $filename; + if (!$loader instanceof ClassLoader) { + return null; + } + + return $loader; + } } diff --git a/test/AutoloaderTest.php b/test/AutoloaderTest.php index 8292541..ae247d8 100644 --- a/test/AutoloaderTest.php +++ b/test/AutoloaderTest.php @@ -3,14 +3,20 @@ namespace LaminasTest\ZendFrameworkBridge; use Laminas\LegacyTypeHint; +use Laminas\ZendFrameworkBridge\Autoloader; use PHPUnit\Framework\TestCase; use function class_exists; +use function clearstatcache; +use function file_exists; use function get_class; use function interface_exists; +use function rename; class AutoloaderTest extends TestCase { + private const PATH_TO_AUTOLOADER = __DIR__ . '/../vendor/autoload.php'; + /** * @return array[] */ @@ -139,4 +145,22 @@ public function testReverseAliasCreated($actual, $legacy) self::assertTrue(class_exists($actual)); self::assertTrue(class_exists($legacy)); } + + public function testCanHandleNonExistentAutoloadFile(): void + { + self::assertTrue(file_exists(self::PATH_TO_AUTOLOADER)); + $pathToAutoloaderBackup = sprintf('%s.bak', self::PATH_TO_AUTOLOADER); + rename(self::PATH_TO_AUTOLOADER, $pathToAutoloaderBackup); + clearstatcache(); + self::assertFalse(file_exists(self::PATH_TO_AUTOLOADER)); + + try { + Autoloader::load(); + } finally { + rename($pathToAutoloaderBackup, self::PATH_TO_AUTOLOADER); + } + + clearstatcache(); + self::assertTrue(file_exists(self::PATH_TO_AUTOLOADER)); + } }