Browse Source

Lazy load version details to reduce ORM insanity

Jordi Boggiano 12 years ago
parent
commit
c7ada8a31b

+ 31 - 4
src/Packagist/WebBundle/Controller/WebController.php

@@ -280,11 +280,11 @@ class WebController extends Controller
      */
     public function viewPackageAction(Request $req, $name)
     {
+        $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Package');
+
         try {
             /** @var $package Package */
-            $package = $this->getDoctrine()
-                ->getRepository('PackagistWebBundle:Package')
-                ->getFullPackageByName($name);
+            $package = $repo->findOneByName($name);
         } catch (NoResultException $e) {
             if ('json' === $req->getRequestFormat()) {
                 return new JsonResponse(array('status' => 'error', 'message' => 'Package not found'), 404);
@@ -294,10 +294,18 @@ class WebController extends Controller
         }
 
         if ('json' === $req->getRequestFormat()) {
+            $package = $repo->getFullPackageByName($name);
+
             return new Response(json_encode(array('package' => $package->toArray())), 200);
         }
 
-        $data = array('package' => $package);
+        $version = null;
+        if (count($package->getVersions())) {
+            $versionRepo = $this->getDoctrine()->getRepository('PackagistWebBundle:Version');
+            $version = $versionRepo->getFullVersion($package->getVersions()->first()->getId());
+        }
+
+        $data = array('package' => $package, 'version' => $version);
 
         $id = $package->getId();
 
@@ -329,6 +337,25 @@ class WebController extends Controller
         return $data;
     }
 
+    /**
+     * @Template()
+     * @Route(
+     *     "/versions/{versionId}.{_format}",
+     *     name="view_version",
+     *     requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+?", "versionId"="[0-9]+", "_format"="(json)"}
+     * )
+     * @Method({"GET"})
+     */
+    public function viewPackageVersionAction(Request $req, $versionId)
+    {
+        $repo = $this->getDoctrine()->getRepository('PackagistWebBundle:Version');
+        $version = $repo->getFullVersion($versionId);
+
+        $html = $this->renderView('PackagistWebBundle:Web:versionDetails.html.twig', array('version' => $version));
+
+        return new JsonResponse(array('content' => $html));
+    }
+
     /**
      * @Template()
      * @Route("/packages/{name}", name="update_package", requirements={"name"="[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+"}, defaults={"_format" = "json"})

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

@@ -192,6 +192,7 @@ class PackageRepository extends EntityRepository
             ->leftJoin('v.tags', 't')
             ->orderBy('v.development', 'DESC')
             ->addOrderBy('v.releasedAt', 'DESC');
+
         return $qb;
     }
 }

+ 19 - 0
src/Packagist/WebBundle/Entity/VersionRepository.php

@@ -54,4 +54,23 @@ class VersionRepository extends EntityRepository
 
         $em->remove($version);
     }
+
+    public function getFullVersion($versionId)
+    {
+        $qb = $this->getEntityManager()->createQueryBuilder();
+        $qb->select('v', 't', 'a', 'req', 'devReq', 'sug', 'rep', 'con', 'pro')
+            ->from('Packagist\WebBundle\Entity\Version', 'v')
+            ->leftJoin('v.tags', 't')
+            ->leftJoin('v.authors', 'a')
+            ->leftJoin('v.require', 'req')
+            ->leftJoin('v.devRequire', 'devReq')
+            ->leftJoin('v.suggest', 'sug')
+            ->leftJoin('v.replace', 'rep')
+            ->leftJoin('v.conflict', 'con')
+            ->leftJoin('v.provide', 'pro')
+            ->where('v.id = :id')
+            ->setParameter('id', $versionId);
+
+        return $qb->getQuery()->getSingleResult();
+    }
 }

+ 12 - 1
src/Packagist/WebBundle/Resources/public/js/view.js

@@ -4,8 +4,19 @@
         e.preventDefault();
     });
     $('.package .details-toggler').click(function (e) {
-        $(this).toggleClass('open')
+        var target = $(this);
+        target.toggleClass('open')
             .prev().toggleClass('open');
+        if (target.attr('data-load-more')) {
+            $.ajax({
+                url: target.attr('data-load-more'),
+                dataType: 'json',
+                success: function (data) {
+                    target.attr('data-load-more', '')
+                        .prev().html(data.content);
+                }
+            });
+        }
     });
     $('.package .force-update').submit(function (e) {
         var submit = $('input[type=submit]', this);

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

@@ -0,0 +1,31 @@
+{% import "PackagistWebBundle::macros.html.twig" as packagist %}
+
+<h2 class="authors">Author{{ version.authors|length > 1 ? 's' : '' }}</h2>
+<ul>
+    {% for author in version.authors %}
+        <li>
+            {%- if author.homepage -%}
+                <a href="{{ author.homepage }}">{{ author.name }}</a>
+            {%- else -%}
+                {{ author.name }}
+            {%- endif -%}
+            {% if author.email %} &lt;<a href="mailto:{{ author.email }}">{{ author.email }}</a>&gt;{% endif -%}
+        </li>
+    {% endfor %}
+</ul>
+<div class="clearfix package-links">
+    {% for type in ["require", "devRequire", "suggest", "provide", "conflict", "replace"] %}
+        <div class="{{ type }}s">
+            <h2>{{ ('link_type.' ~ type)|trans }}</h2>
+            {% 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>
+                    {%- endfor -%}
+                </ul>
+            {% else %}
+                None
+            {% endif %}
+        </div>
+    {% endfor %}
+</div>

+ 6 - 35
src/Packagist/WebBundle/Resources/views/Web/viewPackage.html.twig

@@ -1,15 +1,12 @@
 {% extends "PackagistWebBundle::layout.html.twig" %}
-{% import "PackagistWebBundle::macros.html.twig" as packagist %}
 
 {% block title %}{{ package.name }} - {{ parent() }}{% endblock %}
 
 {% block scripts %}
-    <script src="{{ asset('bundles/packagistweb/js/view.js?v=3')}}"></script>
+    <script src="{{ asset('bundles/packagistweb/js/view.js?v=4')}}"></script>
 {% endblock %}
 
 {% block content %}
-    {% set version = package.versions|length ? package.versions[0] : null %}
-
     <div class="box">
         <div class="package"{% if app.user and package.maintainers.contains(app.user) and package.crawledAt is null %} data-force-crawl="true"{% endif %}>
             {% if is_granted('ROLE_EDIT_PACKAGES') or package.maintainers.contains(app.user) %}
@@ -116,38 +113,12 @@
                                     <span class="license">{{ version.license ? version.license|join(', ') : '' }}</span>
                                 </h1>
 
-                                <div class="details {% if loop.index0 == 0 %} open{% endif %}">
-                                    <h2 class="authors">Author{{ version.authors|length > 1 ? 's' : '' }}</h2>
-                                    <ul>
-                                        {% for author in version.authors %}
-                                            <li>
-                                                {%- if author.homepage -%}
-                                                    <a href="{{ author.homepage }}">{{ author.name }}</a>
-                                                {%- else -%}
-                                                    {{ author.name }}
-                                                {%- endif -%}
-                                                {% if author.email %} &lt;<a href="mailto:{{ author.email }}">{{ author.email }}</a>&gt;{% endif -%}
-                                            </li>
-                                        {% endfor %}
-                                    </ul>
-                                    <div class="clearfix package-links">
-                                        {% for type in ["require", "devRequire", "suggest", "provide", "conflict", "replace"] %}
-                                            <div class="{{ type }}s">
-                                                <h2>{{ ('link_type.' ~ type)|trans }}</h2>
-                                                {% 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>
-                                                        {%- endfor -%}
-                                                    </ul>
-                                                {% else %}
-                                                    None
-                                                {% endif %}
-                                            </div>
-                                        {% endfor %}
-                                    </div>
+                                <div class="details{% if loop.index0 == 0 %} open{% endif %}">
+                                    {% if loop.index0 == 0 %}
+                                        {% include 'PackagistWebBundle:Web:versionDetails.html.twig' with {version: version} %}
+                                    {% endif %}
                                 </div>
-                                <div class="details-toggler{% if loop.index0 == 0 %} open{% endif %}"></div>
+                                <div class="details-toggler{% if loop.index0 == 0 %} open{% endif %}"{% if loop.index0 %} data-load-more="{{ path('view_version', {versionId: version.id, _format: 'json'}) }}"{% endif %}></div>
                             </section>
                         </li>
                     {% endfor %}