Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manipulate the classmap rather than the generated classmap file #46

Merged
merged 1 commit into from Aug 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/PuliPlugin.php
Expand Up @@ -43,6 +43,7 @@ public static function getSubscribedEvents()
return array(
ScriptEvents::POST_INSTALL_CMD => 'listen',
ScriptEvents::POST_UPDATE_CMD => 'listen',
ScriptEvents::PRE_AUTOLOAD_DUMP => 'listen',
ScriptEvents::POST_AUTOLOAD_DUMP => 'listen',
);
}
Expand Down Expand Up @@ -78,6 +79,9 @@ public function listen(Event $event)
}

switch ($event->getName()) {
case ScriptEvents::PRE_AUTOLOAD_DUMP:
$this->impl->preAutoloadDump();
break;
case ScriptEvents::POST_AUTOLOAD_DUMP:
$this->impl->postAutoloadDump();
break;
Expand Down
117 changes: 75 additions & 42 deletions src/PuliPluginImpl.php
Expand Up @@ -83,6 +83,11 @@ class PuliPluginImpl
*/
private $rootDir;

/**
* @var bool
*/
private $runPreAutoloadDump = true;

/**
* @var bool
*/
Expand All @@ -98,6 +103,11 @@ class PuliPluginImpl
*/
private $initialized = false;

/**
* @var string
*/
private $autoloadFile;

public function __construct(Event $event, PuliRunner $puliRunner = null)
{
$this->composer = $event->getComposer();
Expand All @@ -106,29 +116,28 @@ public function __construct(Event $event, PuliRunner $puliRunner = null)
$this->isDev = $event->isDevMode();
$this->puliRunner = $puliRunner;
$this->rootDir = Path::normalize(getcwd());

$vendorDir = $this->config->get('vendor-dir');

// On TravisCI, $vendorDir is a relative path. Probably an old Composer
// build or something. Usually, $vendorDir should be absolute already.
$vendorDir = Path::makeAbsolute($vendorDir, $this->rootDir);

$this->autoloadFile = $vendorDir.'/autoload.php';
}

public function postAutoloadDump()
public function preAutoloadDump()
{
if (!$this->initialized) {
$this->initialize();
}

// This method is called twice. Run it only once.
if (!$this->runPostAutoloadDump) {
if (!$this->runPreAutoloadDump) {
return;
}

$this->runPostAutoloadDump = false;

$vendorDir = $this->config->get('vendor-dir');

// On TravisCI, $vendorDir is a relative path. Probably an old Composer
// build or something. Usually, $vendorDir should be absolute already.
$vendorDir = Path::makeAbsolute($vendorDir, $this->rootDir);

$autoloadFile = $vendorDir.'/autoload.php';
$classMapFile = $vendorDir.'/composer/autoload_classmap.php';
$this->runPreAutoloadDump = false;

try {
$factoryClass = $this->getConfigKey('factory.in.class');
Expand All @@ -141,9 +150,51 @@ public function postAutoloadDump()

$factoryFile = Path::makeAbsolute($factoryFile, $this->rootDir);

$this->insertFactoryClassConstant($autoloadFile, $factoryClass);
$this->insertFactoryClassMap($classMapFile, $vendorDir, $factoryClass, $factoryFile);
$this->setBootstrapFile($autoloadFile);
$autoload = $this->composer->getPackage()->getAutoload();
$autoload['classmap'][] = $factoryFile;

$this->composer->getPackage()->setAutoload($autoload);

if (!file_exists($factoryFile)) {
$filesystem = new Filesystem();
// Let Composer find the factory class with a temporary stub

$namespace = explode('\\', ltrim($factoryClass, '\\'));
$className = array_pop($namespace);

if (count($namespace)) {
$stub = '<?php namespace '.implode('\\', $namespace).'; class '.$className.' {}';
} else {
$stub = '<?php class '.$className.' {}';
}

$filesystem->dumpFile($factoryFile, $stub);
}
}

public function postAutoloadDump()
{
if (!$this->initialized) {
$this->initialize();
}

// This method is called twice. Run it only once.
if (!$this->runPostAutoloadDump) {
return;
}

$this->runPostAutoloadDump = false;

try {
$factoryClass = $this->getConfigKey('factory.in.class');
} catch (PuliRunnerException $e) {
$this->printWarning('Could not load Puli configuration', $e);

return;
}

$this->insertFactoryClassConstant($this->autoloadFile, $factoryClass);
$this->setBootstrapFile($this->autoloadFile);
}

/**
Expand Down Expand Up @@ -200,6 +251,13 @@ public function postInstall()

private function initialize()
{
if (!file_exists($this->autoloadFile)) {
$filesystem = new Filesystem();
// Avoid problems if using the runner before autoload.php has been
// generated
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Puli CLI, while doing the version check, tries to include it, leading to a warning message.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, can you outline when this exactly happens? I haven't seen any warning during my tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't happen directly in this library. Include your PR branch in another project, make sure the vendor folder doesn't exist and do a composer install.

I get "Warning: Version check failed: PHP Warning: require_once(/path/to/project/vendor/autoload.php): failed to open stream: No such file or directory in phar:///usr/local/bin/puli/vendor/puli/manager/src/Api/Puli.php on line 313
PHP Fatal error: require_once(): Failed opening required '/path/to/project/vendor/autoload.php' (include_path='.:') in phar:///usr/local/bin/puli/vendor/puli/manager/src/Api/Puli.php on line 313".

$filesystem->dumpFile($this->autoloadFile, '');
}

$this->initialized = true;

// Keep the manually set runner
Expand All @@ -210,6 +268,7 @@ private function initialize()
$this->puliRunner = new PuliRunner($this->config->get('bin-dir'));
} catch (RuntimeException $e) {
$this->printWarning('Plugin initialization failed', $e);
$this->runPreAutoloadDump = false;
$this->runPostAutoloadDump = false;
$this->runPostInstall = false;
}
Expand All @@ -220,6 +279,7 @@ private function initialize()
$this->verifyPuliVersion();
} catch (RuntimeException $e) {
$this->printWarning('Version check failed', $e);
$this->runPreAutoloadDump = false;
$this->runPostAutoloadDump = false;
$this->runPostInstall = false;
}
Expand Down Expand Up @@ -439,33 +499,6 @@ private function insertFactoryClassConstant($autoloadFile, $factoryClass)
file_put_contents($autoloadFile, $contents);
}

private function insertFactoryClassMap($classMapFile, $vendorDir, $factoryClass, $factoryFile)
{
if (!file_exists($classMapFile)) {
throw new PuliPluginException(sprintf(
'Could not adjust autoloader: The file %s was not found.',
$classMapFile
));
}

$this->io->write(sprintf('<info>Registering "%s" with the class-map autoloader</info>', $factoryClass));

$relFactoryFile = Path::makeRelative($factoryFile, $vendorDir);
$escFactoryClass = var_export($factoryClass, true);
$escFactoryFile = var_export('/'.$relFactoryFile, true);
$classMap = sprintf("\n %s => \$vendorDir . %s,", $escFactoryClass, $escFactoryFile);

$contents = file_get_contents($classMapFile);

// Regex modifiers:
// "m": \s matches newlines
// "D": $ matches at EOF only
// Translation: insert before the last ");" in the file
$contents = preg_replace('/\n(?=\);\s*$)/mD', "\n".$classMap, $contents);

file_put_contents($classMapFile, $contents);
}

private function setBootstrapFile($autoloadFile)
{
$bootstrapFile = $this->getConfigKey('bootstrap-file');
Expand Down
9 changes: 0 additions & 9 deletions tests/Fixtures/root/the-vendor/composer/autoload_classmap.php

This file was deleted.