diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php
index 620010494..0c62075e9 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 5191d8558..7c252c5b0 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());
+ }
+}