1
0
Fork 0

Fix ClassLoader to be serializable (#11237)

* Fix ClassLoader to be serializable

* Fix CI to use the source bin/composer as process for "composer" runs incl within simple-phpunit

* Store the closure statically to avoid serialization issues in a cleaner way
pull/11244/head
Jordi Boggiano 2022-12-22 15:17:04 +01:00 committed by GitHub
parent 7290f5b437
commit cbb7c91223
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 14 deletions

View File

@ -103,6 +103,21 @@ jobs:
- name: "Run install again using composer binary from source"
run: "bin/composer install ${{ env.COMPOSER_FLAGS }}"
- name: "Make source binary the one used by default (Linux / macOS)"
if: "!contains(matrix.os, 'windows')"
run: |
echo -e "$(pwd)/bin\n$(cat $GITHUB_PATH)" > $GITHUB_PATH
echo -e "COMPOSER_BINARY=$(pwd)/bin/composer" >> $GITHUB_ENV
- name: "Make source binary the one used by default (Windows)"
if: "contains(matrix.os, 'windows')"
run: |
$(
(echo "$(Get-Location)\bin")
(Get-Content $env:GITHUB_PATH -Raw)
) | Set-Content $env:GITHUB_PATH
echo "COMPOSER_BINARY=$(Get-Location)\bin\composer" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: "Prepare git environment"
run: "git config --global user.name composer && git config --global user.email composer@example.com"

View File

@ -43,7 +43,7 @@ namespace Composer\Autoload;
class ClassLoader
{
/** @var \Closure(string):void */
private $includeFile;
private static $includeFile;
/** @var ?string */
private $vendorDir;
@ -109,18 +109,7 @@ class ClassLoader
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
$this->includeFile = static function($file) {
include $file;
};
self::initializeIncludeClosure();
}
/**
@ -440,7 +429,7 @@ class ClassLoader
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
($this->includeFile)($file);
(self::$includeFile)($file);
return true;
}
@ -570,4 +559,23 @@ class ClassLoader
return false;
}
private static function initializeIncludeClosure(): void
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = static function($file) {
include $file;
};
}
}

View File

@ -59,4 +59,27 @@ class ClassLoaderTest extends TestCase
$loader = new ClassLoader();
$this->assertEmpty($loader->getPrefixes());
}
public function testSerializability(): void
{
$loader = new ClassLoader();
$loader->add('Pearlike_', __DIR__ . '/Fixtures');
$loader->add('', __DIR__ . '/FALLBACK');
$loader->addPsr4('ShinyVendor\\ShinyPackage\\', __DIR__ . '/Fixtures');
$loader->addPsr4('', __DIR__ . '/FALLBACKPSR4');
$loader->addClassMap(['A' => '', 'B' => 'path']);
$loader->setApcuPrefix('prefix');
$loader->setClassMapAuthoritative(true);
$loader->setUseIncludePath(true);
$loader2 = unserialize(serialize($loader));
self::assertInstanceOf(ClassLoader::class, $loader2);
self::assertSame($loader->getApcuPrefix(), $loader2->getApcuPrefix());
self::assertSame($loader->getClassMap(), $loader2->getClassMap());
self::assertSame($loader->getFallbackDirs(), $loader2->getFallbackDirs());
self::assertSame($loader->getFallbackDirsPsr4(), $loader2->getFallbackDirsPsr4());
self::assertSame($loader->getPrefixes(), $loader2->getPrefixes());
self::assertSame($loader->getPrefixesPsr4(), $loader2->getPrefixesPsr4());
self::assertSame($loader->getUseIncludePath(), $loader2->getUseIncludePath());
}
}