diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index 7e882ddb3..d5dad92ca 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -12,9 +12,14 @@ namespace Composer\EventDispatcher; +use Composer\DependencyResolver\PolicyInterface; +use Composer\DependencyResolver\Pool; +use Composer\DependencyResolver\Request; +use Composer\Installer\InstallerEvent; use Composer\IO\IOInterface; use Composer\Composer; use Composer\DependencyResolver\Operation\OperationInterface; +use Composer\Repository\CompositeRepository; use Composer\Script; use Composer\Script\CommandEvent; use Composer\Script\PackageEvent; @@ -113,6 +118,25 @@ class EventDispatcher return $this->doDispatch(new CommandEvent($eventName, $this->composer, $this->io, $devMode, $additionalArgs)); } + + /** + * Dispatch a installer event. + * + * @param string $eventName The constant in InstallerEvents + * @param PolicyInterface $policy The policy + * @param Pool $pool The pool + * @param CompositeRepository $installedRepo The installed repository + * @param Request $request The request + * @param array $operations The list of operations + * + * @return int return code of the executed script if any, for php scripts a false return + * value is changed to 1, anything else to 0 + */ + public function dispatchInstallerEvent($eventName, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array()) + { + return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $policy, $pool, $installedRepo, $request, $operations)); + } + /** * Triggers the listeners of an event. * diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 3176ece17..a71dec8ac 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -26,6 +26,7 @@ use Composer\DependencyResolver\SolverProblemsException; use Composer\Downloader\DownloadManager; use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallationManager; +use Composer\Installer\InstallerEvents; use Composer\Installer\NoopInstaller; use Composer\IO\IOInterface; use Composer\Json\JsonFile; @@ -260,8 +261,10 @@ class Installer $request->install($link->getTarget(), $link->getConstraint()); } + $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_SOLVE_DEPENDENCIES, $policy, $pool, $installedRepo, $request); $solver = new Solver($policy, $pool, $installedRepo); $ops = $solver->solve($request); + $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_SOLVE_DEPENDENCIES, $policy, $pool, $installedRepo, $request, $ops); foreach ($ops as $op) { if ($op->getJobType() === 'uninstall') { $devPackages[] = $op->getPackage(); @@ -464,9 +467,11 @@ class Installer $this->processDevPackages($localRepo, $pool, $policy, $repositories, $lockedRepository, $installFromLock, 'force-links'); // solve dependencies + $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_SOLVE_DEPENDENCIES, $policy, $pool, $installedRepo, $request); $solver = new Solver($policy, $pool, $installedRepo); try { $operations = $solver->solve($request); + $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_SOLVE_DEPENDENCIES, $policy, $pool, $installedRepo, $request, $operations); } catch (SolverProblemsException $e) { $this->io->write('Your requirements could not be resolved to an installable set of packages.'); $this->io->write($e->getMessage()); diff --git a/src/Composer/Installer/InstallerEvent.php b/src/Composer/Installer/InstallerEvent.php new file mode 100644 index 000000000..a9f5a728a --- /dev/null +++ b/src/Composer/Installer/InstallerEvent.php @@ -0,0 +1,146 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Installer; + +use Composer\Composer; +use Composer\DependencyResolver\PolicyInterface; +use Composer\DependencyResolver\Operation\OperationInterface; +use Composer\DependencyResolver\Pool; +use Composer\DependencyResolver\Request; +use Composer\EventDispatcher\Event; +use Composer\IO\IOInterface; +use Composer\Repository\CompositeRepository; + +/** + * An event for all installer. + * + * @author François Pluchino + */ +class InstallerEvent extends Event +{ + /** + * @var Composer + */ + private $composer; + + /** + * @var IOInterface + */ + private $io; + + /** + * @var PolicyInterface + */ + private $policy; + + /** + * @var Pool + */ + private $pool; + + /** + * @var CompositeRepository + */ + private $installedRepo; + + /** + * @var Request + */ + private $request; + + /** + * @var OperationInterface[] + */ + private $operations; + + /** + * Constructor. + * + * @param string $eventName + * @param Composer $composer + * @param IOInterface $io + * @param PolicyInterface $policy + * @param Pool $pool + * @param CompositeRepository $installedRepo + * @param Request $request + * @param OperationInterface[] $operations + */ + public function __construct($eventName, Composer $composer, IOInterface $io, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array()) + { + parent::__construct($eventName); + + $this->composer = $composer; + $this->io = $io; + $this->policy = $policy; + $this->pool = $pool; + $this->installedRepo = $installedRepo; + $this->request = $request; + $this->operations = $operations; + } + + /** + * @return Composer + */ + public function getComposer() + { + return $this->composer; + } + + /** + * @return IOInterface + */ + public function getIO() + { + return $this->io; + } + + /** + * @return PolicyInterface + */ + public function getPolicy() + { + return $this->policy; + } + + /** + * @return Pool + */ + public function getPool() + { + return $this->pool; + } + + /** + * @return CompositeRepository + */ + public function getInstalledRepo() + { + return $this->installedRepo; + } + + /** + * @return Request + */ + public function getRequest() + { + return $this->request; + } + + /** + * @return OperationInterface[] + */ + public function getOperations() + { + return $this->operations; + } +} diff --git a/src/Composer/Installer/InstallerEvents.php b/src/Composer/Installer/InstallerEvents.php new file mode 100644 index 000000000..5929b0964 --- /dev/null +++ b/src/Composer/Installer/InstallerEvents.php @@ -0,0 +1,43 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Installer; + +/** + * The Installer Events. + * + * @author François Pluchino + */ +class InstallerEvents +{ + /** + * The PRE_SOLVE_DEPENDENCIES event occurs as a installer begins + * resolve operations. + * + * The event listener method receives a + * Composer\Installer\InstallerEvent instance. + * + * @var string + */ + const PRE_SOLVE_DEPENDENCIES = 'pre-solve-dependencies'; + + /** + * The POST_SOLVE_DEPENDENCIES event occurs as a installer after + * resolve operations. + * + * The event listener method receives a + * Composer\Installer\InstallerEvent instance. + * + * @var string + */ + const POST_SOLVE_DEPENDENCIES = 'post-solve-dependencies'; +} diff --git a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php index fd26b0a3c..a6cad7602 100644 --- a/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php +++ b/tests/Composer/Test/EventDispatcher/EventDispatcherTest.php @@ -174,6 +174,31 @@ class EventDispatcherTest extends TestCase $dispatcher->dispatchCommandEvent("post-install-cmd", false); } + public function testDispatcherInstallerEvents() + { + $process = $this->getMock('Composer\Util\ProcessExecutor'); + $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher') + ->setConstructorArgs(array( + $this->getMock('Composer\Composer'), + $this->getMock('Composer\IO\IOInterface'), + $process, + )) + ->setMethods(array('getListeners')) + ->getMock(); + + $dispatcher->expects($this->atLeastOnce()) + ->method('getListeners') + ->will($this->returnValue(array())); + + $policy = $this->getMock('Composer\DependencyResolver\PolicyInterface'); + $pool = $this->getMockBuilder('Composer\DependencyResolver\Pool')->disableOriginalConstructor()->getMock(); + $installedRepo = $this->getMockBuilder('Composer\Repository\CompositeRepository')->disableOriginalConstructor()->getMock(); + $request = $this->getMockBuilder('Composer\DependencyResolver\Request')->disableOriginalConstructor()->getMock(); + + $dispatcher->dispatchInstallerEvent("pre-solve-dependencies", $policy, $pool, $installedRepo, $request); + $dispatcher->dispatchInstallerEvent("post-solve-dependencies", $policy, $pool, $installedRepo, $request, array()); + } + public static function call() { throw new \RuntimeException(); diff --git a/tests/Composer/Test/Installer/InstallerEventTest.php b/tests/Composer/Test/Installer/InstallerEventTest.php new file mode 100644 index 000000000..7cd63f6b5 --- /dev/null +++ b/tests/Composer/Test/Installer/InstallerEventTest.php @@ -0,0 +1,39 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Test\Installer; + +use Composer\Installer\InstallerEvent; + +class InstallerEventTest extends \PHPUnit_Framework_TestCase +{ + public function testGetter() + { + $composer = $this->getMock('Composer\Composer'); + $io = $this->getMock('Composer\IO\IOInterface'); + $policy = $this->getMock('Composer\DependencyResolver\PolicyInterface'); + $pool = $this->getMockBuilder('Composer\DependencyResolver\Pool')->disableOriginalConstructor()->getMock(); + $installedRepo = $this->getMockBuilder('Composer\Repository\CompositeRepository')->disableOriginalConstructor()->getMock(); + $request = $this->getMockBuilder('Composer\DependencyResolver\Request')->disableOriginalConstructor()->getMock(); + $operations = array($this->getMock('Composer\DependencyResolver\Operation\OperationInterface')); + $event = new InstallerEvent('EVENT_NAME', $composer, $io, $policy, $pool, $installedRepo, $request, $operations); + + $this->assertSame('EVENT_NAME', $event->getName()); + $this->assertInstanceOf('Composer\Composer', $event->getComposer()); + $this->assertInstanceOf('Composer\IO\IOInterface', $event->getIO()); + $this->assertInstanceOf('Composer\DependencyResolver\PolicyInterface', $event->getPolicy()); + $this->assertInstanceOf('Composer\DependencyResolver\Pool', $event->getPool()); + $this->assertInstanceOf('Composer\Repository\CompositeRepository', $event->getInstalledRepo()); + $this->assertInstanceOf('Composer\DependencyResolver\Request', $event->getRequest()); + $this->assertCount(1, $event->getOperations()); + } +}