فهرست منبع

Suggest which providers could be required to fulfill a virtual package requirement, fixes #2811

Jordi Boggiano 5 سال پیش
والد
کامیت
29efc473a1

+ 11 - 0
src/Composer/DependencyResolver/Problem.php

@@ -250,6 +250,17 @@ class Problem
             return array("- Root composer.json requires $packageName, it ", 'could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.');
         }
 
+        if ($providers = $repositorySet->getProviders($packageName)) {
+            $maxProviders = 20;
+            $providersStr = implode(array_map(function ($p) {
+                return "      - ${p['name']} ".substr($p['description'], 0, 100)."\n";
+            }, count($providers) > $maxProviders+1 ? array_slice($providers, 0, $maxProviders) : $providers));
+            if (count($providers) > $maxProviders+1) {
+                $providersStr .= '      ... and '.(count($providers)-$maxProviders).' more.'."\n";
+            }
+            return array("- Root composer.json requires $packageName".self::constraintToText($constraint).", it ", "could not be found in any version, but the following packages provide it: \n".$providersStr."      Consider requiring one of these to satisfy the $packageName requirement.");
+        }
+
         return array("- Root composer.json requires $packageName, it ", "could not be found in any version, there may be a typo in the package name.");
     }
 

+ 17 - 0
src/Composer/Repository/ComposerRepository.php

@@ -52,6 +52,8 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
     protected $cache;
     protected $notifyUrl;
     protected $searchUrl;
+    /** @var string|null a URL containing %package% which can be queried to get providers of a given name */
+    protected $providersApiUrl;
     protected $hasProviders = false;
     protected $providersUrl;
     protected $availablePackages;
@@ -416,6 +418,17 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
         return parent::search($query, $mode);
     }
 
+    public function getProviders($packageName)
+    {
+        if (!$this->providersApiUrl) {
+            return array();
+        }
+
+        $result = $this->httpDownloader->get(str_replace('%package%', $packageName, $this->providersApiUrl), $this->options)->decodeJson();
+
+        return $result['providers'];
+    }
+
     private function getProviderNames()
     {
         $this->loadRootServerFile();
@@ -810,6 +823,10 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
             $this->hasProviders = true;
         }
 
+        if (!empty($data['providers-api'])) {
+            $this->providersApiUrl = $data['providers-api'];
+        }
+
         return $this->rootData = $data;
     }
 

+ 13 - 0
src/Composer/Repository/RepositorySet.php

@@ -158,6 +158,19 @@ class RepositorySet
         return $candidates;
     }
 
+    public function getProviders($packageName)
+    {
+        foreach ($this->repositories as $repository) {
+            if ($repository instanceof ComposerRepository) {
+                if ($providers = $repository->getProviders($packageName)) {
+                    return $providers;
+                }
+            }
+        }
+
+        return array();
+    }
+
     public function isPackageAcceptable($names, $stability)
     {
         return StabilityFilter::isPackageAcceptable($this->acceptableStabilities, $this->stabilityFlags, $names, $stability);