ソースを参照

Migrate authors from relation to json field, fixes #997

Jordi Boggiano 5 年 前
コミット
146c9b03aa

+ 3 - 4
src/Packagist/WebBundle/Controller/FeedController.php

@@ -264,11 +264,10 @@ class FeedController extends Controller
         $entry->setDateModified($version->getReleasedAt());
         $entry->setDateCreated($version->getReleasedAt());
 
-        foreach ($version->getAuthors() as $author) {
-            /** @var $author \Packagist\WebBundle\Entity\Author */
-            if ($author->getName()) {
+        foreach ($version->getAuthorData() as $author) {
+            if (!empty($author['name'])) {
                 $entry->addAuthor(array(
-                    'name' => $author->getName()
+                    'name' => $author['name']
                 ));
             }
         }

+ 1 - 1
src/Packagist/WebBundle/Entity/Author.php

@@ -57,7 +57,7 @@ class Author
     private $versions;
 
     /**
-     * @ORM\ManyToOne(targetEntity="Packagist\WebBundle\Entity\User", inversedBy="authors")
+     * @ORM\ManyToOne(targetEntity="Packagist\WebBundle\Entity\User")
      */
     private $owner;
 

+ 0 - 26
src/Packagist/WebBundle/Entity/User.php

@@ -85,11 +85,6 @@ class User extends BaseUser
      */
     private $packages;
 
-    /**
-     * @ORM\OneToMany(targetEntity="Packagist\WebBundle\Entity\Author", mappedBy="owner")
-     */
-    private $authors;
-
     /**
      * @ORM\Column(type="datetime")
      */
@@ -128,7 +123,6 @@ class User extends BaseUser
     public function __construct()
     {
         $this->packages = new ArrayCollection();
-        $this->authors = new ArrayCollection();
         $this->createdAt = new \DateTime();
         parent::__construct();
     }
@@ -161,26 +155,6 @@ class User extends BaseUser
         return $this->packages;
     }
 
-    /**
-     * Add authors
-     *
-     * @param Author $authors
-     */
-    public function addAuthors(Author $authors)
-    {
-        $this->authors[] = $authors;
-    }
-
-    /**
-     * Get authors
-     *
-     * @return Author[]
-     */
-    public function getAuthors()
-    {
-        return $this->authors;
-    }
-
     /**
      * Set createdAt
      *

+ 51 - 6
src/Packagist/WebBundle/Entity/Version.php

@@ -109,6 +109,8 @@ class Version
     private $license;
 
     /**
+     * Deprecated relation table, use the authorJson property instead
+     *
      * @ORM\ManyToMany(targetEntity="Packagist\WebBundle\Entity\Author", inversedBy="versions")
      * @ORM\JoinTable(name="version_author",
      *     joinColumns={@ORM\JoinColumn(name="version_id", referencedColumnName="id")},
@@ -177,6 +179,11 @@ class Version
      */
     private $support;
 
+    /**
+     * @ORM\Column(name="authors", type="json", nullable=true)
+     */
+    private $authorJson;
+
     /**
      * @ORM\Column(type="datetime")
      */
@@ -223,13 +230,17 @@ class Version
             }
         }
 
-        if (isset($versionData[$this->id]['authors'])) {
-            $authors = $versionData[$this->id]['authors'];
+        if (!is_null($this->getAuthorJson())) {
+            $authors = $this->getAuthorJson();
         } else {
-            $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();
+                }
             }
         }
 
@@ -715,6 +726,40 @@ class Version
         return $this->authors;
     }
 
+    public function getAuthorJson(): ?array
+    {
+        return $this->authorJson;
+    }
+
+    public function setAuthorJson(?array $authors): void
+    {
+        $this->authorJson = $authors ?: [];
+    }
+
+    /**
+     * Get authors
+     *
+     * @return array[]
+     */
+    public function getAuthorData(): array
+    {
+        if (!is_null($this->getAuthorJson())) {
+            return $this->getAuthorJson();
+        }
+
+        $authors = [];
+        foreach ($this->getAuthors() as $author) {
+            $authors[] = array_filter([
+                'name' => $author->getName(),
+                'homepage' => $author->getHomepage(),
+                'email' => $author->getEmail(),
+                'role' => $author->getRole(),
+            ]);
+        }
+
+        return $authors;
+    }
+
     /**
      * Set type
      *

+ 2 - 1
src/Packagist/WebBundle/Entity/VersionRepository.php

@@ -157,7 +157,7 @@ class VersionRepository extends EntityRepository
     public function getVersionMetadataForUpdate(Package $package)
     {
         $rows = $this->getEntityManager()->getConnection()->fetchAll(
-            'SELECT id, version, normalizedVersion, source, softDeletedAt FROM package_version v WHERE v.package_id = :id',
+            'SELECT id, version, normalizedVersion, source, softDeletedAt, `authors` IS NULL as needs_author_migration FROM package_version v WHERE v.package_id = :id',
             ['id' => $package->getId()]
         );
 
@@ -166,6 +166,7 @@ class VersionRepository extends EntityRepository
             if ($row['source']) {
                 $row['source'] = json_decode($row['source'], true);
             }
+            $row['needs_author_migration'] = (int) $row['needs_author_migration'];
             $versions[strtolower($row['normalizedVersion'])] = $row;
         }
 

+ 14 - 33
src/Packagist/WebBundle/Package/Updater.php

@@ -271,6 +271,12 @@ class Updater
             // update if the right flag is set, or the source reference has changed (re-tag or new commit on branch)
             if ($source['reference'] !== $data->getSourceReference() || ($flags & self::UPDATE_EQUAL_REFS)) {
                 $version = $versionRepo->findOneById($existingVersion['id']);
+            } elseif ($existingVersion['needs_author_migration']) {
+                $version = $versionRepo->findOneById($existingVersion['id']);
+
+                $version->setAuthorJson($version->getAuthorData());
+
+                return ['updated' => true, 'id' => $version->getId(), 'version' => strtolower($normVersion), 'object' => $version];
             } else {
                 return ['updated' => false, 'id' => $existingVersion['id'], 'version' => strtolower($normVersion), 'object' => null];
             }
@@ -363,21 +369,19 @@ class Updater
             $version->getTags()->clear();
         }
 
-        $authorRepository = $this->doctrine->getRepository('PackagistWebBundle:Author');
-
         $version->getAuthors()->clear();
+        $version->setAuthorJson([]);
         if ($data->getAuthors()) {
+            $authors = [];
             foreach ($data->getAuthors() as $authorData) {
-                $author = null;
+                $author = [];
 
                 foreach (array('email', 'name', 'homepage', 'role') as $field) {
                     if (isset($authorData[$field])) {
-                        $authorData[$field] = trim($authorData[$field]);
-                        if ('' === $authorData[$field]) {
-                            $authorData[$field] = null;
+                        $author[$field] = trim($authorData[$field]);
+                        if ('' === $author[$field]) {
+                            unset($author[$field]);
                         }
-                    } else {
-                        $authorData[$field] = null;
                     }
                 }
 
@@ -386,32 +390,9 @@ class Updater
                     continue;
                 }
 
-                $author = $authorRepository->findOneBy(array(
-                    'email' => $authorData['email'],
-                    'name' => $authorData['name'],
-                    'homepage' => $authorData['homepage'],
-                    'role' => $authorData['role'],
-                ));
-
-                if (!$author) {
-                    $author = new Author();
-                    $em->persist($author);
-                }
-
-                foreach (array('email', 'name', 'homepage', 'role') as $field) {
-                    if (isset($authorData[$field])) {
-                        $author->{'set'.$field}($authorData[$field]);
-                    }
-                }
-
-                // only update the author timestamp once a month at most as the value is kinda unused
-                if ($author->getUpdatedAt() === null || $author->getUpdatedAt()->getTimestamp() < time() - 86400 * 30) {
-                    $author->setUpdatedAt(new \DateTime);
-                }
-                if (!$version->getAuthors()->contains($author)) {
-                    $version->addAuthor($author);
-                }
+                $authors[] = $author;
             }
+            $version->setAuthorJson($authors);
         }
 
         // handle links

+ 4 - 4
src/Packagist/WebBundle/Resources/views/package/version_details.html.twig

@@ -36,17 +36,17 @@
 <div class="metadata">
     <p class="license"><i class="glyphicon glyphicon-copyright-mark" title="License"></i> {% if not version.license %}<span class="unknown">{% endif %}{{ version.license ? version.license|join(', ') : 'Unknown License' }}{% if not version.license %}</span>{% endif %} <span class="source-reference"><i class="glyphicon glyphicon-bookmark" title="Source Reference"></i> {{ version.source.reference }}</span></p>
 
-    {% if version.authors|length %}
+    {% if version.authorData|length %}
         <i class="glyphicon glyphicon-user" title="Authors"></i>
         <ul class="authors">
-            {% for author in version.authors %}
+            {% for author in version.authorData %}
                 <li>
-                    {%- if author.homepage -%}
+                    {%- if author.homepage|default(false) -%}
                         <a rel="nofollow noopener external noindex" href="{{ author.homepage }}">{{ author.name }}</a>
                     {%- else -%}
                         {{ author.name }}
                     {%- endif -%}
-                    {% if author.email %}
+                    {% if author.email|default(false) %}
                         <span class="visible-sm-inline visible-md-inline visible-lg-inline">&lt;{{ author.email|split('@', 2)[0] }}<span style="display:none">.woop</span>@{{ author.email|split('@', 2)[1] }}&gt;</span>
                     {%- endif -%}
                 </li>