Skip to content

Commit

Permalink
Merge pull request #90 from boesing/bugfix/handle-not-existing-autolo…
Browse files Browse the repository at this point in the history
…ader

Allow the composer class loader to be absent, for `composer/composer:2.2.0` compatibility
  • Loading branch information
Ocramius authored Dec 21, 2021
2 parents bf180a3 + e71bcbb commit 88bf037
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 35 deletions.
18 changes: 0 additions & 18 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
<code>$class</code>
<code>$class</code>
</MissingClosureParamType>
<MissingFile occurrences="1">
<code>include __DIR__ . '/../../../autoload.php'</code>
</MissingFile>
<MissingReturnType occurrences="1">
<code>load</code>
</MissingReturnType>
Expand All @@ -31,25 +28,10 @@
<MixedArrayOffset occurrences="1">
<code>$loaded[$class]</code>
</MixedArrayOffset>
<MixedInferredReturnType occurrences="1">
<code>ClassLoader</code>
</MixedInferredReturnType>
<MixedOperand occurrences="2">
<code>$namespaces[$check]</code>
<code>$namespaces[$check]</code>
</MixedOperand>
<MixedReturnStatement occurrences="3">
<code>include __DIR__ . '/../../../autoload.php'</code>
<code>include __DIR__ . '/../vendor/autoload.php'</code>
<code>include getenv('COMPOSER_VENDOR_DIR') . '/autoload.php'</code>
</MixedReturnStatement>
<PossiblyFalseOperand occurrences="2">
<code>getenv('COMPOSER_VENDOR_DIR')</code>
<code>getenv('COMPOSER_VENDOR_DIR')</code>
</PossiblyFalseOperand>
<UnresolvableInclude occurrences="1">
<code>include getenv('COMPOSER_VENDOR_DIR') . '/autoload.php'</code>
</UnresolvableInclude>
</file>
<file src="src/ConfigPostProcessor.php">
<InvalidArgument occurrences="1">
Expand Down
49 changes: 32 additions & 17 deletions src/Autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
*
Expand All @@ -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);

Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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;
}
}
24 changes: 24 additions & 0 deletions test/AutoloaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
*/
Expand Down Expand Up @@ -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));
}
}

0 comments on commit 88bf037

Please sign in to comment.