Load installed plugins at appropriate time and adapt tests accordingly
parent
3e41977be7
commit
2f43e9aefb
|
@ -55,7 +55,7 @@ class Composer
|
||||||
private $installationManager;
|
private $installationManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @var Plugin\PluginManager
|
||||||
*/
|
*/
|
||||||
private $pluginManager;
|
private $pluginManager;
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,9 @@ class Factory
|
||||||
$generator = new AutoloadGenerator($dispatcher);
|
$generator = new AutoloadGenerator($dispatcher);
|
||||||
$composer->setAutoloadGenerator($generator);
|
$composer->setAutoloadGenerator($generator);
|
||||||
|
|
||||||
|
$pm = $this->createPluginManager($composer, $io);
|
||||||
|
$composer->setPluginManager($pm);
|
||||||
|
|
||||||
// add installers to the manager
|
// add installers to the manager
|
||||||
$this->createDefaultInstallers($im, $composer, $io);
|
$this->createDefaultInstallers($im, $composer, $io);
|
||||||
|
|
||||||
|
@ -264,9 +267,7 @@ class Factory
|
||||||
$composer->setLocker($locker);
|
$composer->setLocker($locker);
|
||||||
}
|
}
|
||||||
|
|
||||||
$pm = $this->createPluginManager($composer);
|
$pm->loadInstalledPlugins();
|
||||||
|
|
||||||
$composer->setPluginManager($pm);
|
|
||||||
|
|
||||||
return $composer;
|
return $composer;
|
||||||
}
|
}
|
||||||
|
@ -360,9 +361,9 @@ class Factory
|
||||||
/**
|
/**
|
||||||
* @return Plugin\PluginManager
|
* @return Plugin\PluginManager
|
||||||
*/
|
*/
|
||||||
protected function createPluginManager(Composer $composer)
|
protected function createPluginManager(Composer $composer, IOInterface $io)
|
||||||
{
|
{
|
||||||
return new Plugin\PluginManager($composer);
|
return new Plugin\PluginManager($composer, $io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -37,15 +37,17 @@ class PluginInstaller extends LibraryInstaller
|
||||||
*/
|
*/
|
||||||
public function __construct(IOInterface $io, Composer $composer, $type = 'library')
|
public function __construct(IOInterface $io, Composer $composer, $type = 'library')
|
||||||
{
|
{
|
||||||
parent::__construct($io, $composer, $type);
|
parent::__construct($io, $composer, 'composer-plugin');
|
||||||
$this->installationManager = $composer->getInstallationManager();
|
$this->installationManager = $composer->getInstallationManager();
|
||||||
|
|
||||||
$repo = $composer->getRepositoryManager()->getLocalRepository();
|
|
||||||
foreach ($repo->getPackages() as $package) {
|
|
||||||
if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) {
|
|
||||||
$this->registerPlugin($package);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function supports($packageType)
|
||||||
|
{
|
||||||
|
return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,7 +61,7 @@ class PluginInstaller extends LibraryInstaller
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::install($repo, $package);
|
parent::install($repo, $package);
|
||||||
$this->registerPlugin($package);
|
$this->composer->getPluginManager()->registerPackage($package);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,39 +75,6 @@ class PluginInstaller extends LibraryInstaller
|
||||||
}
|
}
|
||||||
|
|
||||||
parent::update($repo, $initial, $target);
|
parent::update($repo, $initial, $target);
|
||||||
$this->registerPlugin($target);
|
$this->composer->getPluginManager()->registerPackage($target);
|
||||||
}
|
|
||||||
|
|
||||||
private function registerPlugin(PackageInterface $package)
|
|
||||||
{
|
|
||||||
$oldInstallerPlugin = ($package->getType() === 'composer-installer');
|
|
||||||
|
|
||||||
$downloadPath = $this->getInstallPath($package);
|
|
||||||
|
|
||||||
$extra = $package->getExtra();
|
|
||||||
$classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
|
|
||||||
|
|
||||||
$generator = $this->composer->getAutoloadGenerator();
|
|
||||||
$map = $generator->parseAutoloads(array(array($package, $downloadPath)), new Package('dummy', '1.0.0.0', '1.0.0'));
|
|
||||||
$classLoader = $generator->createLoader($map);
|
|
||||||
$classLoader->register();
|
|
||||||
|
|
||||||
foreach ($classes as $class) {
|
|
||||||
if (class_exists($class, false)) {
|
|
||||||
$code = file_get_contents($classLoader->findFile($class));
|
|
||||||
$code = preg_replace('{^(\s*)class\s+(\S+)}mi', '$1class $2_composer_tmp'.self::$classCounter, $code);
|
|
||||||
eval('?>'.$code);
|
|
||||||
$class .= '_composer_tmp'.self::$classCounter;
|
|
||||||
self::$classCounter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
$plugin = new $class($this->io, $this->composer);
|
|
||||||
|
|
||||||
if ($oldInstallerPlugin) {
|
|
||||||
$this->installationManager->addInstaller($installer);
|
|
||||||
} else {
|
|
||||||
$this->composer->getPluginManager()->addPlugin($plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
namespace Composer\Plugin;
|
namespace Composer\Plugin;
|
||||||
|
|
||||||
use Composer\Composer;
|
use Composer\Composer;
|
||||||
|
use Composer\Package\Package;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,17 +25,34 @@ use Composer\Package\PackageInterface;
|
||||||
class PluginManager
|
class PluginManager
|
||||||
{
|
{
|
||||||
protected $composer;
|
protected $composer;
|
||||||
|
protected $io;
|
||||||
|
|
||||||
protected $plugins = array();
|
protected $plugins = array();
|
||||||
|
|
||||||
|
private static $classCounter = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes plugin manager
|
* Initializes plugin manager
|
||||||
*
|
*
|
||||||
* @param Composer $composer
|
* @param Composer $composer
|
||||||
*/
|
*/
|
||||||
public function __construct(Composer $composer)
|
public function __construct(Composer $composer, IOInterface $io)
|
||||||
{
|
{
|
||||||
$this->composer = $composer;
|
$this->composer = $composer;
|
||||||
|
$this->io = $io;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadInstalledPlugins()
|
||||||
|
{
|
||||||
|
$repo = $this->composer->getRepositoryManager()->getLocalRepository();
|
||||||
|
|
||||||
|
if ($repo) {
|
||||||
|
foreach ($repo->getPackages() as $package) {
|
||||||
|
if ('composer-plugin' === $package->getType() || 'composer-installer' === $package->getType()) {
|
||||||
|
$this->registerPackage($package);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -46,4 +65,58 @@ class PluginManager
|
||||||
$this->plugins[] = $plugin;
|
$this->plugins[] = $plugin;
|
||||||
$plugin->activate($this->composer);
|
$plugin->activate($this->composer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPlugins()
|
||||||
|
{
|
||||||
|
return $this->plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function registerPackage(PackageInterface $package)
|
||||||
|
{
|
||||||
|
$oldInstallerPlugin = ($package->getType() === 'composer-installer');
|
||||||
|
|
||||||
|
$downloadPath = $this->getInstallPath($package);
|
||||||
|
|
||||||
|
$extra = $package->getExtra();
|
||||||
|
if (empty($extra['class'])) {
|
||||||
|
throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
|
||||||
|
}
|
||||||
|
$classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
|
||||||
|
|
||||||
|
$generator = $this->composer->getAutoloadGenerator();
|
||||||
|
$map = $generator->parseAutoloads(array(array($package, $downloadPath)), new Package('dummy', '1.0.0.0', '1.0.0'));
|
||||||
|
$classLoader = $generator->createLoader($map);
|
||||||
|
$classLoader->register();
|
||||||
|
|
||||||
|
foreach ($classes as $class) {
|
||||||
|
if (class_exists($class, false)) {
|
||||||
|
$code = file_get_contents($classLoader->findFile($class));
|
||||||
|
$code = preg_replace('{^(\s*)class\s+(\S+)}mi', '$1class $2_composer_tmp'.self::$classCounter, $code);
|
||||||
|
eval('?>'.$code);
|
||||||
|
$class .= '_composer_tmp'.self::$classCounter;
|
||||||
|
self::$classCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plugin = new $class($this->io, $this->composer);
|
||||||
|
|
||||||
|
if ($oldInstallerPlugin) {
|
||||||
|
$this->composer->getInstallationManager()->addInstaller($installer);
|
||||||
|
} else {
|
||||||
|
$this->addPlugin($plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInstallPath(PackageInterface $package)
|
||||||
|
{
|
||||||
|
$targetDir = $package->getTargetDir();
|
||||||
|
|
||||||
|
return $this->getPackageBasePath($package) . ($targetDir ? '/'.$targetDir : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getPackageBasePath(PackageInterface $package)
|
||||||
|
{
|
||||||
|
$vendorDir = rtrim($this->composer->getConfig()->get('vendor-dir'), '/');
|
||||||
|
return ($vendorDir ? $vendorDir.'/' : '') . $package->getPrettyName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "plugin-v1",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"type": "composer-plugin",
|
"type": "composer-plugin",
|
||||||
"autoload": { "psr-0": { "Installer": "" } },
|
"autoload": { "psr-0": { "Installer": "" } },
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "plugin-v2",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"type": "composer-plugin",
|
"type": "composer-plugin",
|
||||||
"autoload": { "psr-0": { "Installer": "" } },
|
"autoload": { "psr-0": { "Installer": "" } },
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "plugin-v3",
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"type": "composer-plugin",
|
"type": "composer-plugin",
|
||||||
"autoload": { "psr-0": { "Installer": "" } },
|
"autoload": { "psr-0": { "Installer": "" } },
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "",
|
"name": "plugin-v4",
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"type": "composer-plugin",
|
"type": "composer-plugin",
|
||||||
"autoload": { "psr-0": { "Installer": "" } },
|
"autoload": { "psr-0": { "Installer": "" } },
|
||||||
|
|
|
@ -42,14 +42,6 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
|
||||||
->disableOriginalConstructor()
|
->disableOriginalConstructor()
|
||||||
->getMock();
|
->getMock();
|
||||||
|
|
||||||
$this->im = $this->getMockBuilder('Composer\Installer\InstallationManager')
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
|
|
||||||
$this->pm = $this->getMockBuilder('Composer\Plugin\PluginManager')
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
|
|
||||||
$this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface');
|
$this->repository = $this->getMock('Composer\Repository\InstalledRepositoryInterface');
|
||||||
|
|
||||||
$rm = $this->getMockBuilder('Composer\Repository\RepositoryManager')
|
$rm = $this->getMockBuilder('Composer\Repository\RepositoryManager')
|
||||||
|
@ -68,11 +60,12 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
|
||||||
$config = new Config();
|
$config = new Config();
|
||||||
$this->composer->setConfig($config);
|
$this->composer->setConfig($config);
|
||||||
$this->composer->setDownloadManager($dm);
|
$this->composer->setDownloadManager($dm);
|
||||||
$this->composer->setInstallationManager($this->im);
|
|
||||||
$this->composer->setPluginManager($this->pm);
|
|
||||||
$this->composer->setRepositoryManager($rm);
|
$this->composer->setRepositoryManager($rm);
|
||||||
$this->composer->setAutoloadGenerator($this->autoloadGenerator);
|
$this->composer->setAutoloadGenerator($this->autoloadGenerator);
|
||||||
|
|
||||||
|
$this->pm = new \Composer\Plugin\PluginManager($this->composer, $this->io);
|
||||||
|
$this->composer->setPluginManager($this->pm);
|
||||||
|
|
||||||
$config->merge(array(
|
$config->merge(array(
|
||||||
'config' => array(
|
'config' => array(
|
||||||
'vendor-dir' => __DIR__.'/Fixtures/',
|
'vendor-dir' => __DIR__.'/Fixtures/',
|
||||||
|
@ -87,17 +80,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('getPackages')
|
->method('getPackages')
|
||||||
->will($this->returnValue(array()));
|
->will($this->returnValue(array()));
|
||||||
$installer = new PluginInstallerMock($this->io, $this->composer);
|
$installer = new PluginInstaller($this->io, $this->composer);
|
||||||
|
$this->pm->loadInstalledPlugins();
|
||||||
$test = $this;
|
|
||||||
$this->pm
|
|
||||||
->expects($this->once())
|
|
||||||
->method('addPlugin')
|
|
||||||
->will($this->returnCallback(function ($installer) use ($test) {
|
|
||||||
$test->assertEquals('installer-v1', $installer->version);
|
|
||||||
}));
|
|
||||||
|
|
||||||
$installer->install($this->repository, $this->packages[0]);
|
$installer->install($this->repository, $this->packages[0]);
|
||||||
|
|
||||||
|
$plugins = $this->pm->getPlugins();
|
||||||
|
$this->assertEquals('installer-v1', $plugins[0]->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInstallMultiplePlugins()
|
public function testInstallMultiplePlugins()
|
||||||
|
@ -106,28 +95,16 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
|
||||||
->expects($this->once())
|
->expects($this->once())
|
||||||
->method('getPackages')
|
->method('getPackages')
|
||||||
->will($this->returnValue(array()));
|
->will($this->returnValue(array()));
|
||||||
|
$installer = new PluginInstaller($this->io, $this->composer);
|
||||||
$installer = new PluginInstallerMock($this->io, $this->composer);
|
$this->pm->loadInstalledPlugins();
|
||||||
|
|
||||||
$test = $this;
|
|
||||||
|
|
||||||
$this->pm
|
|
||||||
->expects($this->at(0))
|
|
||||||
->method('addPlugin')
|
|
||||||
->will($this->returnCallback(function ($plugin) use ($test) {
|
|
||||||
$test->assertEquals('plugin1', $plugin->name);
|
|
||||||
$test->assertEquals('installer-v4', $plugin->version);
|
|
||||||
}));
|
|
||||||
|
|
||||||
$this->pm
|
|
||||||
->expects($this->at(1))
|
|
||||||
->method('addPlugin')
|
|
||||||
->will($this->returnCallback(function ($plugin) use ($test) {
|
|
||||||
$test->assertEquals('plugin2', $plugin->name);
|
|
||||||
$test->assertEquals('installer-v4', $plugin->version);
|
|
||||||
}));
|
|
||||||
|
|
||||||
$installer->install($this->repository, $this->packages[3]);
|
$installer->install($this->repository, $this->packages[3]);
|
||||||
|
|
||||||
|
$plugins = $this->pm->getPlugins();
|
||||||
|
$this->assertEquals('plugin1', $plugins[0]->name);
|
||||||
|
$this->assertEquals('installer-v4', $plugins[0]->version);
|
||||||
|
$this->assertEquals('plugin2', $plugins[1]->name);
|
||||||
|
$this->assertEquals('installer-v4', $plugins[1]->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpgradeWithNewClassName()
|
public function testUpgradeWithNewClassName()
|
||||||
|
@ -140,17 +117,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
|
||||||
->expects($this->exactly(2))
|
->expects($this->exactly(2))
|
||||||
->method('hasPackage')
|
->method('hasPackage')
|
||||||
->will($this->onConsecutiveCalls(true, false));
|
->will($this->onConsecutiveCalls(true, false));
|
||||||
$installer = new PluginInstallerMock($this->io, $this->composer);
|
$installer = new PluginInstaller($this->io, $this->composer);
|
||||||
|
$this->pm->loadInstalledPlugins();
|
||||||
$test = $this;
|
|
||||||
$this->pm
|
|
||||||
->expects($this->once())
|
|
||||||
->method('addPlugin')
|
|
||||||
->will($this->returnCallback(function ($plugin) use ($test) {
|
|
||||||
$test->assertEquals('installer-v2', $plugin->version);
|
|
||||||
}));
|
|
||||||
|
|
||||||
$installer->update($this->repository, $this->packages[0], $this->packages[1]);
|
$installer->update($this->repository, $this->packages[0], $this->packages[1]);
|
||||||
|
|
||||||
|
$plugins = $this->pm->getPlugins();
|
||||||
|
$this->assertEquals('installer-v2', $plugins[1]->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testUpgradeWithSameClassName()
|
public function testUpgradeWithSameClassName()
|
||||||
|
@ -163,26 +136,13 @@ class PluginInstallerTest extends \PHPUnit_Framework_TestCase
|
||||||
->expects($this->exactly(2))
|
->expects($this->exactly(2))
|
||||||
->method('hasPackage')
|
->method('hasPackage')
|
||||||
->will($this->onConsecutiveCalls(true, false));
|
->will($this->onConsecutiveCalls(true, false));
|
||||||
$installer = new PluginInstallerMock($this->io, $this->composer);
|
$installer = new PluginInstaller($this->io, $this->composer);
|
||||||
|
$this->pm->loadInstalledPlugins();
|
||||||
$test = $this;
|
|
||||||
$this->pm
|
|
||||||
->expects($this->once())
|
|
||||||
->method('addPlugin')
|
|
||||||
->will($this->returnCallback(function ($plugin) use ($test) {
|
|
||||||
$test->assertEquals('installer-v3', $plugin->version);
|
|
||||||
}));
|
|
||||||
|
|
||||||
$installer->update($this->repository, $this->packages[1], $this->packages[2]);
|
$installer->update($this->repository, $this->packages[1], $this->packages[2]);
|
||||||
|
|
||||||
|
$plugins = $this->pm->getPlugins();
|
||||||
|
$this->assertEquals('installer-v3', $plugins[1]->version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PluginInstallerMock extends PluginInstaller
|
|
||||||
{
|
|
||||||
public function getInstallPath(PackageInterface $package)
|
|
||||||
{
|
|
||||||
$version = $package->getVersion();
|
|
||||||
|
|
||||||
return __DIR__.'/Fixtures/plugin-v'.$version[0].'/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue