Browse Source

Add PRE_POOL_CREATE event, fixes #8348

Jordi Boggiano 5 years ago
parent
commit
835a91532d

+ 2 - 0
doc/articles/scripts.md

@@ -66,6 +66,8 @@ Composer fires the following named events during its execution process:
 - **pre-command-run**: occurs before a command is executed and allows you to
   manipulate the `InputInterface` object's options and arguments to tweak
   a command's behavior.
+- **pre-pool-create**: occurs before the Pool of packages is created, and lets
+  you filter the list of packages which is going to enter the Solver.
 
 > **Note:** Composer makes no assumptions about the state of your dependencies
 > prior to `install` or `update`. Therefore, you should not specify scripts

+ 23 - 1
src/Composer/DependencyResolver/PoolBuilder.php

@@ -21,6 +21,9 @@ use Composer\Repository\PlatformRepository;
 use Composer\Repository\RootPackageRepository;
 use Composer\Semver\Constraint\Constraint;
 use Composer\Semver\Constraint\MultiConstraint;
+use Composer\EventDispatcher\EventDispatcher;
+use Composer\Plugin\PrePoolCreateEvent;
+use Composer\Plugin\PluginEvents;
 
 /**
  * @author Nils Adermann <naderman@naderman.de>
@@ -31,6 +34,7 @@ class PoolBuilder
     private $stabilityFlags;
     private $rootAliases;
     private $rootReferences;
+    private $eventDispatcher;
 
     private $aliasMap = array();
     private $nameConstraints = array();
@@ -38,12 +42,13 @@ class PoolBuilder
     private $packages = array();
     private $unacceptableFixedPackages = array();
 
-    public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences)
+    public function __construct(array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, EventDispatcher $eventDispatcher = null)
     {
         $this->acceptableStabilities = $acceptableStabilities;
         $this->stabilityFlags = $stabilityFlags;
         $this->rootAliases = $rootAliases;
         $this->rootReferences = $rootReferences;
+        $this->eventDispatcher = $eventDispatcher;
     }
 
     public function buildPool(array $repositories, Request $request)
@@ -132,6 +137,23 @@ class PoolBuilder
             }
         }
 
+        if ($this->eventDispatcher) {
+            $prePoolCreateEvent = new PrePoolCreateEvent(
+                PluginEvents::PRE_POOL_CREATE,
+                $repositories,
+                $request,
+                $this->acceptableStabilities,
+                $this->stabilityFlags,
+                $this->rootAliases,
+                $this->rootReferences,
+                $this->packages,
+                $this->unacceptableFixedPackages
+            );
+            $this->eventDispatcher->dispatch($prePoolCreateEvent->getName(), $prePoolCreateEvent);
+            $this->packages = $prePoolCreateEvent->getPackages();
+            $this->unacceptableFixedPackages = $prePoolCreateEvent->getUnacceptableFixedPackages();
+        }
+
         $pool = new Pool($this->packages, $this->unacceptableFixedPackages);
 
         $this->aliasMap = array();

+ 3 - 3
src/Composer/Installer.php

@@ -381,7 +381,7 @@ class Installer
             }
         }
 
-        $pool = $repositorySet->createPool($request);
+        $pool = $repositorySet->createPool($request, $this->eventDispatcher);
         $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $repositorySet, $pool, $request, $policy);
 
         // solve dependencies
@@ -522,7 +522,7 @@ class Installer
             $request->requireName($link->getTarget(), $link->getConstraint());
         }
 
-        $pool = $repositorySet->createPool($request);
+        $pool = $repositorySet->createPool($request, $this->eventDispatcher);
 
         $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $repositorySet, $pool, $request, $policy);
         $solver = new Solver($policy, $pool, $this->io, $repositorySet);
@@ -578,7 +578,7 @@ class Installer
                 $request->requireName($link->getTarget(), $link->getConstraint());
             }
 
-            $pool = $repositorySet->createPool($request);
+            $pool = $repositorySet->createPool($request, $this->eventDispatcher);
             $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $repositorySet, $pool, $request, $policy);
 
             // solve dependencies

+ 11 - 0
src/Composer/Plugin/PluginEvents.php

@@ -58,4 +58,15 @@ class PluginEvents
      * @var string
      */
     const PRE_COMMAND_RUN = 'pre-command-run';
+
+    /**
+     * The PRE_POOL_CREATE event occurs before the Pool of packages is created, and lets
+     * you filter the list of packages which is going to enter the Solver
+     *
+     * The event listener method receives a
+     * Composer\Plugin\PrePoolCreateEvent instance.
+     *
+     * @var string
+     */
+    const PRE_POOL_CREATE = 'pre-pool-create';
 }

+ 158 - 0
src/Composer/Plugin/PrePoolCreateEvent.php

@@ -0,0 +1,158 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Plugin;
+
+use Composer\EventDispatcher\Event;
+use Symfony\Component\Console\Input\InputInterface;
+use Composer\Repository\RepositoryInterface;
+use Composer\DependencyResolver\Request;
+use Composer\Package\PackageInterface;
+
+/**
+ * The pre command run event.
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class PrePoolCreateEvent extends Event
+{
+    /**
+     * @var RepositoryInterface[]
+     */
+    private $repositories;
+    /**
+     * @var Request
+     */
+    private $request;
+    /**
+     * @var array
+     */
+    private $acceptableStabilities;
+    /**
+     * @var array
+     */
+    private $stabilityFlags;
+    /**
+     * @var array
+     */
+    private $rootAliases;
+    /**
+     * @var array
+     */
+    private $rootReferences;
+    /**
+     * @var PackageInterface[]
+     */
+    private $packages;
+    /**
+     * @var PackageInterface[]
+     */
+    private $unacceptableFixedPackages;
+
+    /**
+     * @param string                $name         The event name
+     * @param RepositoryInterface[] $repositories
+     */
+    public function __construct($name, array $repositories, Request $request, array $acceptableStabilities, array $stabilityFlags, array $rootAliases, array $rootReferences, array $packages, array $unacceptableFixedPackages)
+    {
+        parent::__construct($name);
+
+        $this->repositories = $repositories;
+        $this->request = $request;
+        $this->acceptableStabilities = $acceptableStabilities;
+        $this->stabilityFlags = $stabilityFlags;
+        $this->rootAliases = $rootAliases;
+        $this->rootReferences = $rootReferences;
+        $this->packages = $packages;
+        $this->unacceptableFixedPackages = $unacceptableFixedPackages;
+    }
+
+    /**
+     * @return RepositoryInterface[]
+     */
+    public function getRepositories()
+    {
+        return $this->repositories;
+    }
+
+    /**
+     * @return Request
+     */
+    public function getRequest()
+    {
+        return $this->request;
+    }
+
+    /**
+     * @return array
+     */
+    public function getAcceptableStabilities()
+    {
+        return $this->acceptableStabilities;
+    }
+
+    /**
+     * @return array
+     */
+    public function getStabilityFlags()
+    {
+        return $this->stabilityFlags;
+    }
+
+    /**
+     * @return array
+     */
+    public function getRootAliases()
+    {
+        return $this->rootAliases;
+    }
+
+    /**
+     * @return array
+     */
+    public function getRootReferences()
+    {
+        return $this->rootReferences;
+    }
+
+    /**
+     * @return PackageInterface[]
+     */
+    public function getPackages()
+    {
+        return $this->packages;
+    }
+
+    /**
+     * @return PackageInterface[]
+     */
+    public function getUnacceptableFixedPackages()
+    {
+        return $this->unacceptableFixedPackages;
+    }
+
+    /**
+     * @param PackageInterface[] $packages
+     */
+    public function setPackages(array $packages)
+    {
+        $this->packages = $packages;
+    }
+
+    /**
+     * @param PackageInterface[] $packages
+     */
+    public function setUnacceptableFixedPackages(array $packages)
+    {
+        $this->unacceptableFixedPackages = $packages;
+    }
+}

+ 3 - 2
src/Composer/Repository/RepositorySet.php

@@ -15,6 +15,7 @@ namespace Composer\Repository;
 use Composer\DependencyResolver\Pool;
 use Composer\DependencyResolver\PoolBuilder;
 use Composer\DependencyResolver\Request;
+use Composer\EventDispatcher\EventDispatcher;
 use Composer\Package\BasePackage;
 use Composer\Package\Version\VersionParser;
 use Composer\Repository\CompositeRepository;
@@ -188,9 +189,9 @@ class RepositorySet
      *
      * @return Pool
      */
-    public function createPool(Request $request)
+    public function createPool(Request $request, EventDispatcher $eventDispatcher = null)
     {
-        $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences);
+        $poolBuilder = new PoolBuilder($this->acceptableStabilities, $this->stabilityFlags, $this->rootAliases, $this->rootReferences, $eventDispatcher);
 
         foreach ($this->repositories as $repo) {
             if ($repo instanceof InstalledRepositoryInterface && !$this->allowInstalledRepositories) {