Explorar el Código

Optimize json package API

Jordi Boggiano hace 8 años
padre
commit
5d5754a939

+ 1 - 1
src/Packagist/WebBundle/Controller/PackageController.php

@@ -322,7 +322,7 @@ class PackageController extends Controller
         }
 
         if ('json' === $req->getRequestFormat()) {
-            $data = $package->toArray();
+            $data = $package->toArray($this->getDoctrine()->getRepository('PackagistWebBundle:Version'));
 
             try {
                 $data['downloads'] = $this->get('packagist.download_manager')->getDownloads($package);

+ 7 - 2
src/Packagist/WebBundle/Entity/Package.php

@@ -178,12 +178,17 @@ class Package
         $this->createdAt = new \DateTime;
     }
 
-    public function toArray()
+    public function toArray(VersionRepository $versionRepo)
     {
         $versions = array();
+        $versionIds = [];
+        foreach ($this->getVersions() as $version) {
+            $versionIds[] = $version->getId();
+        }
+        $versionData = $versionRepo->getVersionData($versionIds);
         foreach ($this->getVersions() as $version) {
             /** @var $version Version */
-            $versions[$version->getVersion()] = $version->toArray();
+            $versions[$version->getVersion()] = $version->toArray($versionData);
         }
         $maintainers = array();
         foreach ($this->getMaintainers() as $maintainer) {

+ 16 - 5
src/Packagist/WebBundle/Entity/Version.php

@@ -206,17 +206,22 @@ class Version
         $this->updatedAt = new \DateTime;
     }
 
-    public function toArray()
+    public function toArray(array $versionData)
     {
         $tags = array();
         foreach ($this->getTags() as $tag) {
             /** @var $tag Tag */
             $tags[] = $tag->getName();
         }
-        $authors = array();
-        foreach ($this->getAuthors() as $author) {
-            /** @var $author Author */
-            $authors[] = $author->toArray();
+
+        if (isset($versionData[$this->id]['authors'])) {
+            $authors = $versionData[$this->id]['authors'];
+        } else {
+            $authors = array();
+            foreach ($this->getAuthors() as $author) {
+                /** @var $author Author */
+                $authors[] = $author->toArray();
+            }
         }
 
         $data = array(
@@ -262,6 +267,12 @@ class Version
         );
 
         foreach ($supportedLinkTypes as $method => $linkType) {
+            if (isset($versionData[$this->id][$method])) {
+                foreach ($versionData[$this->id][$method] as $link) {
+                    $data[$linkType][$link['name']] = $link['version'];
+                }
+                continue;
+            }
             foreach ($this->{'get'.$method}() as $link) {
                 $link = $link->toArray();
                 $data[$linkType][key($link)] = current($link);

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

@@ -13,6 +13,7 @@
 namespace Packagist\WebBundle\Entity;
 
 use Doctrine\ORM\EntityRepository;
+use Doctrine\DBAL\Connection;
 use Predis\Client;
 
 /**
@@ -55,6 +56,54 @@ class VersionRepository extends EntityRepository
         $em->remove($version);
     }
 
+    public function getVersionData(array $versionIds)
+    {
+        $links = [
+            'require' => 'link_require',
+            'devRequire' => 'link_require_dev',
+            'suggest' => 'link_suggest',
+            'conflict' => 'link_conflict',
+            'provide' => 'link_provide',
+            'replace' => 'link_replace',
+        ];
+
+        $result = [];
+        foreach ($versionIds as $id) {
+            $result[$id] = [
+                'require' => [],
+                'devRequire' => [],
+                'suggest' => [],
+                'conflict' => [],
+                'provide' => [],
+                'replace' => [],
+            ];
+        }
+
+        foreach ($links as $link => $table) {
+            $rows = $this->getEntityManager()->getConnection()->fetchAll(
+                'SELECT version_id, packageName name, packageVersion version FROM '.$table.' WHERE version_id IN (:ids)',
+                ['ids' => $versionIds],
+                ['ids' => Connection::PARAM_INT_ARRAY]
+            );
+            foreach ($rows as $row) {
+                $result[$row['version_id']][$link][] = $row;
+            }
+        }
+
+        $rows = $this->getEntityManager()->getConnection()->fetchAll(
+            'SELECT va.version_id, name, email, homepage, role FROM author a JOIN version_author va ON va.author_id = a.id WHERE va.version_id IN (:ids)',
+            ['ids' => $versionIds],
+            ['ids' => Connection::PARAM_INT_ARRAY]
+        );
+        foreach ($rows as $row) {
+            $versionId = $row['version_id'];
+            unset($row['version_id']);
+            $result[$versionId]['authors'][] = array_filter($row);
+        }
+
+        return $result;
+    }
+
     public function getFullVersion($versionId)
     {
         $qb = $this->getEntityManager()->createQueryBuilder();

+ 10 - 3
src/Packagist/WebBundle/Package/SymlinkDumper.php

@@ -186,6 +186,8 @@ class SymlinkDumper
 
         $dumpTimeUpdates = [];
 
+        $versionRepo = $this->doctrine->getRepository('PackagistWebBundle:Version');
+
         try {
             $modifiedIndividualFiles = array();
 
@@ -224,6 +226,11 @@ class SymlinkDumper
                     }
 
                     // (re)write versions in individual files
+                    $versionIds = [];
+                    foreach ($package->getVersions() as $version) {
+                        $versionIds[] = $version->getId();
+                    }
+                    $versionData = $versionRepo->getVersionData($versionIds);
                     foreach ($package->getVersions() as $version) {
                         foreach (array_slice($version->getNames(), 0, 150) as $versionName) {
                             if (!preg_match('{^[A-Za-z0-9_-][A-Za-z0-9_.-]*/[A-Za-z0-9_-][A-Za-z0-9_.-]*$}', $versionName) || strpos($versionName, '..')) {
@@ -232,7 +239,7 @@ class SymlinkDumper
 
                             $file = $buildDir.'/'.$versionName.'.json';
                             $key = $versionName.'.json';
-                            $this->dumpVersionToIndividualFile($version, $file, $key);
+                            $this->dumpVersionToIndividualFile($version, $file, $key, $versionData);
                             $modifiedIndividualFiles[$key] = true;
                             $affectedFiles[$key] = true;
                         }
@@ -602,10 +609,10 @@ class SymlinkDumper
         $this->writeFile($hashedFile, $json);
     }
 
-    private function dumpVersionToIndividualFile(Version $version, $file, $key)
+    private function dumpVersionToIndividualFile(Version $version, $file, $key, $versionData)
     {
         $this->loadIndividualFile($file, $key);
-        $data = $version->toArray();
+        $data = $version->toArray($versionData);
         $data['uid'] = $version->getId();
         $this->individualFiles[$key]['packages'][strtolower($version->getName())][$version->getVersion()] = $data;
         $timestamp = $version->getReleasedAt() ? $version->getReleasedAt()->getTimestamp() : time();