Browse Source

Add virtual package provider listing page, fixes #400

Jordi Boggiano 10 years ago
parent
commit
277f42a1cb

+ 10 - 0
src/Packagist/WebBundle/Controller/WebController.php

@@ -501,6 +501,16 @@ class WebController extends Controller
                 return new JsonResponse(array('status' => 'error', 'message' => 'Package not found'), 404);
             }
 
+            if ($providers = $repo->findProviders($name)) {
+                return $this->render('PackagistWebBundle:Web:providers.html.twig', array(
+                    'name' => $name,
+                    'packages' => $providers,
+                    'meta' => $this->getPackagesMetadata($providers),
+                    'paginate' => false,
+                    'searchForm' => $this->createSearchForm()->createView()
+                ));
+            }
+
             return $this->redirect($this->generateUrl('search', array('q' => $name, 'reason' => 'package_not_found')));
         }
 

+ 57 - 0
src/Packagist/WebBundle/Entity/PackageRepository.php

@@ -27,6 +27,13 @@ class PackageRepository extends EntityRepository
      */
     private $packageNames;
 
+    /**
+     * Lists all provided names array(name => true)
+     *
+     * @var array
+     */
+    private $providedNames;
+
     public function packageExists($name)
     {
         $packages = $this->getPackageNames();
@@ -34,6 +41,13 @@ class PackageRepository extends EntityRepository
         return isset($packages[$name]) || in_array(strtolower($name), $packages, true);
     }
 
+    public function packageIsProvided($name)
+    {
+        $packages = $this->getProvidedNames();
+
+        return isset($packages[$name]) || in_array(strtolower($name), $packages, true);
+    }
+
     public function getPackageNames()
     {
         if (null !== $this->packageNames) {
@@ -62,6 +76,49 @@ class PackageRepository extends EntityRepository
         return $this->packageNames = $names;
     }
 
+    public function getProvidedNames()
+    {
+        if (null !== $this->providedNames) {
+            return $this->providedNames;
+        }
+
+        $names = null;
+        $apc = extension_loaded('apc');
+
+        // TODO use container to set caching key and ttl
+        if ($apc) {
+            $names = apc_fetch('packagist_provided_names');
+        }
+
+        if (!is_array($names)) {
+            $query = $this->getEntityManager()
+                ->createQuery("SELECT p.packageName AS name FROM Packagist\WebBundle\Entity\ProvideLink p GROUP BY p.packageName");
+
+            $names = $this->getPackageNamesForQuery($query);
+            $names = array_combine($names, array_map('strtolower', $names));
+            if ($apc) {
+                apc_store('packagist_provided_names', $names, 3600);
+            }
+        }
+
+        return $this->providedNames = $names;
+    }
+
+    public function findProviders($name)
+    {
+        $query = $this->createQueryBuilder('p')
+            ->select('p')
+            ->leftJoin('p.versions', 'pv')
+            ->leftJoin('pv.provide', 'pr')
+            ->where('pv.development = true')
+            ->andWhere('pr.packageName = :name')
+            ->groupBy('p.name')
+            ->getQuery()
+            ->setParameters(array('name' => $name));
+
+        return $query->getResult();
+    }
+
     public function getPackageNamesByType($type)
     {
         $query = $this->getEntityManager()

+ 3 - 0
src/Packagist/WebBundle/Resources/views/Web/providers.html.twig

@@ -0,0 +1,3 @@
+{% extends "PackagistWebBundle:Web:list.html.twig" %}
+
+{% block content_title %}<h1>The following packages provide {{ name }}</h1>{% endblock %}

+ 3 - 2
src/Packagist/WebBundle/Twig/PackagistExtension.php

@@ -41,8 +41,9 @@ class PackagistExtension extends \Twig_Extension
             return false;
         }
 
-        return $this->doctrine->getRepository('PackagistWebBundle:Package')
-            ->packageExists($package);
+        $repo = $this->doctrine->getRepository('PackagistWebBundle:Package');
+
+        return $repo->packageExists($package) || $repo->packageIsProvided($package);
     }
 
     public function prettifySourceReference($sourceReference)