Преглед изворни кода

Add virtual packages to search and split off into new page, fixes #350, refs #400

Jordi Boggiano пре 11 година
родитељ
комит
24d53b1b29

+ 22 - 0
src/Packagist/WebBundle/Command/IndexPackagesCommand.php

@@ -126,6 +126,28 @@ class IndexPackagesCommand extends ContainerAwareCommand
                 } catch (\Exception $e) {
                     $output->writeln('<error>Exception: '.$e->getMessage().', skipping package '.$package->getName().'.</error>');
                 }
+
+                foreach ($package->getVersions() as $version) {
+                    // abort when a non-dev version shows up since dev ones are ordered first
+                    if (!$version->isDevelopment()) {
+                        break;
+                    }
+                    if (count($provide = $version->getProvide())) {
+                        foreach ($version->getProvide() as $provide) {
+                            try {
+                                $document = $update->createDocument();
+                                $document->setField('id', $provide->getPackageName());
+                                $document->setField('name', $provide->getPackageName());
+                                $document->setField('description', '');
+                                $document->setField('type', 'virtual-package');
+                                $document->setField('trendiness', 100);
+                                $update->addDocument($document);
+                            } catch (\Exception $e) {
+                                $output->writeln('<error>Exception: '.$e->getMessage().', skipping package '.$package->getName().':provide:'.$provide->getPackageName().'</error>');
+                            }
+                        }
+                    }
+                }
             }
 
             $doctrine->getManager()->flush();

+ 33 - 8
src/Packagist/WebBundle/Controller/WebController.php

@@ -324,7 +324,11 @@ class WebController extends Controller
                 }
 
                 foreach ($paginator as $package) {
-                    $url = $this->generateUrl('view_package', array('name' => $package->name), true);
+                    if (ctype_digit((string) $package->id)) {
+                        $url = $this->generateUrl('view_package', array('name' => $package->name), true);
+                    } else {
+                        $url = $this->generateUrl('view_providers', array('name' => $package->name), true);
+                    }
 
                     $result['results'][] = array(
                         'name' => $package->name,
@@ -523,6 +527,33 @@ class WebController extends Controller
         return $this->redirect($this->generateUrl('view_package', array('name' => trim($name, '/'), '_format' => $req->getRequestFormat())));
     }
 
+    /**
+     * @Template()
+     * @Route(
+     *     "/providers/{name}",
+     *     name="view_providers",
+     *     requirements={"name"="[A-Za-z0-9/_.-]+?"},
+     *     defaults={"_format"="html"}
+     * )
+     * @Method({"GET"})
+     */
+    public function viewProvidersAction(Request $req, $name)
+    {
+        $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Package');
+        $providers = $repo->findProviders($name);
+        if (!$providers) {
+            return $this->redirect($this->generateUrl('search', array('q' => $name, 'reason' => 'package_not_found')));
+        }
+
+        return $this->render('PackagistWebBundle:Web:providers.html.twig', array(
+            'name' => $name,
+            'packages' => $providers,
+            'meta' => $this->getPackagesMetadata($providers),
+            'paginate' => false,
+            'searchForm' => $this->createSearchForm()->createView()
+        ));
+    }
+
     /**
      * @Template()
      * @Route(
@@ -546,13 +577,7 @@ class WebController extends Controller
             }
 
             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('view_providers', array('name' => $name)));
             }
 
             return $this->redirect($this->generateUrl('search', array('q' => $name, 'reason' => 'package_not_found')));

+ 7 - 1
src/Packagist/WebBundle/Model/DownloadManager.php

@@ -65,7 +65,13 @@ class DownloadManager
         $keys = array();
 
         foreach ($packageIds as $id) {
-            $keys[$id] = 'dl:'.$id;
+            if (ctype_digit((string) $id)) {
+                $keys[$id] = 'dl:'.$id;
+            }
+        }
+
+        if (!$keys) {
+            return array();
         }
 
         $res = array_map('intval', $this->redis->mget(array_values($keys)));

+ 3 - 1
src/Packagist/WebBundle/Model/FavoriteManager.php

@@ -77,7 +77,9 @@ class FavoriteManager
         $res = array();
         // TODO should be done with scripting when available
         foreach ($packageIds as $id) {
-            $res[$id] = $this->redis->zcard('pkg:'.$id.':fav');
+            if (ctype_digit((string) $id)) {
+                $res[$id] = $this->redis->zcard('pkg:'.$id.':fav');
+            }
         }
 
         return $res;

+ 5 - 1
src/Packagist/WebBundle/Resources/public/css/main.css

@@ -324,13 +324,17 @@ ul.packages h1 {
   margin: 0;
   padding: 8px 4px 0 0;
   height: 32px;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
 }
 
-ul.packages h1 .metadata {
+ul.packages .metadata {
   float: right;
   color: #555;
   font-size: 18px;
   margin-right: 10px;
+  padding-top: 8px;
 }
 
 ul.packages li {

+ 1 - 1
src/Packagist/WebBundle/Resources/views/Web/versionDetails.html.twig

@@ -22,7 +22,7 @@
             {% if attribute(version, type)|length %}
                 <ul>
                     {%- for link in attribute(version, type) -%}
-                        <li>{{ packagist.packageLink(link.packageName) }}: {{ link.packageVersion == 'self.version' ? version.version : link.packageVersion }}</li>
+                        <li>{{ packagist.packageLink(link.packageName, type) }}: {{ link.packageVersion == 'self.version' ? version.version : link.packageVersion }}</li>
                     {%- endfor -%}
                 </ul>
             {% else %}

+ 1 - 1
src/Packagist/WebBundle/Resources/views/layout.html.twig

@@ -13,7 +13,7 @@
         <link rel="shortcut icon" href="{{ asset('favicon.ico') }}" />
         <link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}" />
 
-        <link rel="stylesheet" href="{{ asset('bundles/packagistweb/css/main.css?v=13') }}" />
+        <link rel="stylesheet" href="{{ asset('bundles/packagistweb/css/main.css?v=14') }}" />
         <link rel="stylesheet" href="{{ asset('css/humane/jackedup.css?v=3') }}" />
         <link rel="stylesheet" href="{{ asset('css/fontawesome/font-awesome.css') }}" />
         <!--[if lt IE 8]>

+ 20 - 10
src/Packagist/WebBundle/Resources/views/macros.html.twig

@@ -1,18 +1,26 @@
 {% macro listPackages(packages, paginate, showAutoUpdateWarning, meta) %}
     <ul class="packages">
         {% for package in packages %}
-            <li data-url="{{ path('view_package', { 'name' : package.name }) }}">
+            {% if package.id is numeric %}
+                {% set packageUrl = path('view_package', { 'name' : package.name }) %}
+            {% else %}
+                {% set packageUrl = path('view_providers', { 'name' : package.name }) %}
+            {% endif %}
+            <li data-url="{{ packageUrl }}">
+                {% if meta and package.id is numeric %}
+                    <span class="metadata">
+                        <i class="icon-download"></i> {{ meta.downloads[package.id]|default(0)|number_format(0, '.', ' ') }}
+                        <i class="icon-star"></i> {{ meta.favers[package.id]|number_format(0, '.', ' ') }}
+                    </span>
+                {% endif %}
                 <h1>
-                    <a href="{{ path('view_package', { 'name' : package.name }) }}">{{ package.name }}</a>
+                    <a href="{{ packageUrl }}">{{ package.name }}</a>
+                    {% if package.id is not numeric %}
+                        (virtual package)
+                    {% endif %}
                     {% if showAutoUpdateWarning and not package.autoUpdated %}
                         [Not auto-updated]
                     {% endif %}
-                    {% if meta %}
-                        <span class="metadata">
-                            <i class="icon-download"></i> {{ meta.downloads[package.id]|default(0)|number_format(0, '.', ' ') }}
-                            <i class="icon-star"></i> {{ meta.favers[package.id]|number_format(0, '.', ' ') }}
-                        </span>
-                    {% endif %}
                 </h1>
                 {% if package.description is defined and package.description %}
                     <p class="package-description">{{ package.description }}</p>
@@ -26,8 +34,10 @@
     </ul>
 {% endmacro %}
 
-{% macro packageLink(packageName) %}
-    {%- if packageName is existing_package -%}
+{% macro packageLink(packageName, type) %}
+    {%- if type == 'provide' and (packageName is existing_provider or packageName is existing_package) -%}
+        <a href="{{ path('view_providers', { 'name': packageName }) }}">{{ packageName }}</a>
+    {%- elseif packageName is existing_package -%}
         <a href="{{ path('view_package', { 'name': packageName }) }}">{{ packageName }}</a>
     {%- else -%}
         {{ packageName }}

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

@@ -19,7 +19,9 @@ class PackagistExtension extends \Twig_Extension
     public function getTests()
     {
         return array(
-            'existing_package' => new \Twig_Test_Method($this, 'packageExistsTest')
+            'existing_package' => new \Twig_Test_Method($this, 'packageExistsTest'),
+            'existing_provider' => new \Twig_Test_Method($this, 'providerExistsTest'),
+            'numeric' => new \Twig_Test_Method($this, 'numericTest'),
         );
     }
 
@@ -35,6 +37,11 @@ class PackagistExtension extends \Twig_Extension
         return 'packagist';
     }
 
+    public function numericTest($val)
+    {
+        return ctype_digit((string) $val);
+    }
+
     public function packageExistsTest($package)
     {
         if (!preg_match('/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/', $package)) {
@@ -43,7 +50,14 @@ class PackagistExtension extends \Twig_Extension
 
         $repo = $this->doctrine->getRepository('PackagistWebBundle:Package');
 
-        return $repo->packageExists($package) || $repo->packageIsProvided($package);
+        return $repo->packageExists($package);
+    }
+
+    public function providerExistsTest($package)
+    {
+        $repo = $this->doctrine->getRepository('PackagistWebBundle:Package');
+
+        return $repo->packageIsProvided($package);
     }
 
     public function prettifySourceReference($sourceReference)