]> source.dussan.org Git - nextcloud-server.git/commitdiff
Order the reaction summary, improvements on validations
authorVitor Mattos <vitor@php.rio>
Fri, 14 Jan 2022 14:14:52 +0000 (11:14 -0300)
committerVitor Mattos <vitor@php.rio>
Fri, 21 Jan 2022 11:39:39 +0000 (08:39 -0300)
Signed-off-by: Vitor Mattos <vitor@php.rio>
lib/private/Comments/Manager.php
tests/lib/Comments/ManagerTest.php

index 534de6a937bc510524c7ef2bfd43223771fe108f..2e9acb6ca24d324eca37e77abb4b71af530773e1 100644 (file)
@@ -41,6 +41,7 @@ use OCP\IConfig;
 use OCP\IDBConnection;
 use OCP\IUser;
 use OCP\IInitialStateService;
+use OCP\PreConditionNotMetException;
 use OCP\Util;
 use Psr\Log\LoggerInterface;
 
@@ -136,6 +137,10 @@ class Manager implements ICommentsManager {
                        throw new \UnexpectedValueException('Actor, Object and Verb information must be provided for saving');
                }
 
+               if ($comment->getVerb() === 'reaction' && strlen($comment->getMessage()) > 8) {
+                       throw new \UnexpectedValueException('Reactions cannot be longer than 8 bytes');
+               }
+
                if ($comment->getId() === '') {
                        $comment->setChildrenCount(0);
                        $comment->setLatestChildDateTime(new \DateTime('0000-00-00 00:00:00', new \DateTimeZone('UTC')));
@@ -912,9 +917,6 @@ class Manager implements ICommentsManager {
        }
 
        private function deleteReaction(IComment $reaction): void {
-               if (!$this->supportReactions()) {
-                       return;
-               }
                $qb = $this->dbConn->getQueryBuilder();
                $qb->delete('reactions')
                        ->where($qb->expr()->eq('parent_id', $qb->createNamedParameter($reaction->getParentId())))
@@ -926,18 +928,20 @@ class Manager implements ICommentsManager {
        /**
         * Get comment related with user reaction
         *
+        * Throws PreConditionNotMetException when the system haven't the minimum requirements to
+        * use reactions
+        *
         * @param integer $parentId
         * @param string $actorType
         * @param string $actorId
         * @param string $reaction
         * @return IComment
         * @throws NotFoundException
+        * @throws PreConditionNotMetException
         * @since 24.0.0
         */
        public function getReactionComment(int $parentId, string $actorType, string $actorId, string $reaction): IComment {
-               if (!$this->supportReactions()) {
-                       throw new NotFoundException('The database does not support reactions');
-               }
+               $this->throwIfNotSupportReactions();
                $qb = $this->dbConn->getQueryBuilder();
                $messageId = $qb
                        ->select('message_id')
@@ -984,22 +988,40 @@ class Manager implements ICommentsManager {
                return $comments;
        }
 
+       /**
+        * Support reactions
+        *
+        * @return boolean
+        * @since 24.0.0
+        */
        public function supportReactions(): bool {
                return $this->dbConn->supports4ByteText();
        }
 
+       /**
+        * @throws PreConditionNotMetException
+        * @since 24.0.0
+        */
+       private function throwIfNotSupportReactions() {
+               if (!$this->supportReactions()) {
+                       throw new PreConditionNotMetException('The database does not support reactions');
+               }
+       }
+
        /**
         * Retrieve all reactions of a message
         *
+        * Throws PreConditionNotMetException when the system haven't the minimum requirements to
+        * use reactions
+        *
         * @param integer $parentId
         * @param string $reaction
+        * @throws PreConditionNotMetException
         * @return IComment[]
         * @since 24.0.0
         */
        public function retrieveAllReactions(int $parentId): array {
-               if (!$this->supportReactions()) {
-                       return [];
-               }
+               $this->throwIfNotSupportReactions();
                $qb = $this->dbConn->getQueryBuilder();
                $result = $qb
                        ->select('message_id')
@@ -1058,9 +1080,13 @@ class Manager implements ICommentsManager {
         * Throws NotFoundException when a comment that is to be updated does not
         * exist anymore at this point of time.
         *
+        * Throws PreConditionNotMetException when the system haven't the minimum requirements to
+        * use reactions
+        *
         * @param IComment $comment
         * @return bool
         * @throws NotFoundException
+        * @throws PreConditionNotMetException
         * @since 9.0.0
         */
        public function save(IComment $comment) {
@@ -1140,9 +1166,6 @@ class Manager implements ICommentsManager {
        }
 
        private function addReaction(IComment $reaction): void {
-               if (!$this->supportReactions()) {
-                       return;
-               }
                // Prevent violate constraint
                $qb = $this->dbConn->getQueryBuilder();
                $qb->select($qb->func()->count('*'))
@@ -1191,7 +1214,9 @@ class Manager implements ICommentsManager {
                        )
                        ->from('reactions', 'r')
                        ->where($totalQuery->expr()->eq('r.parent_id', $qb->createNamedParameter($parentId)))
-                       ->groupBy('r.reaction');
+                       ->groupBy('r.reaction')
+                       ->orderBy($totalQuery->func()->count('id'), 'DESC')
+                       ->setMaxResults(200);
 
                $jsonQuery = $this->dbConn->getQueryBuilder();
                $jsonQuery
index 2a837a02abf39f59d7386d7693a442b33d57ba45..9e34cce6476e3b25c64c71c5e35f9cf08e2bec5d 100644 (file)
@@ -1139,4 +1139,88 @@ class ManagerTest extends TestCase {
                        ],
                ];
        }
+
+       /**
+        * @dataProvider providerTestReactionMessageSize
+        */
+       public function testReactionMessageSize($reactionString, $valid) {
+               if (!$valid) {
+                       $this->expectException(\UnexpectedValueException::class);
+               }
+
+               $manager = $this->getManager();
+               $comment = new Comment();
+               $comment->setMessage($reactionString)
+                       ->setVerb('reaction')
+                       ->setActor('users', 'alice')
+                       ->setObject('files', 'file64');
+               $status = $manager->save($comment);
+               $this->assertTrue($status);
+       }
+
+       public function providerTestReactionMessageSize(): array {
+               return [
+                       ['a', true],
+                       ['1', true],
+                       ['12345678', true],
+                       ['123456789', false],
+                       ['👍', true],
+                       ['👍👍', true],
+                       ['👍🏽', true],
+                       ['👍🏽👍', false],
+                       ['👍🏽👍🏽', false],
+               ];
+       }
+
+       /**
+        * @dataProvider providerTestReactionsSummarizeOrdered
+        */
+       public function testReactionsSummarizeOrdered(array $comments, $expected) {
+               $this->skipIfNotSupport4ByteUTF();
+               $manager = $this->getManager();
+
+               $buffer = [];
+               foreach ($comments as $comment) {
+                       [$message, $actorId, $verb, $parentText] = $comment;
+                       $parentId = null;
+                       if ($parentText) {
+                               $parentId = (string) $buffer[$parentText]->getId();
+                       }
+                       $comment = $this->testSaveNew($message, $actorId, $verb, $parentId);
+                       if (!$parentId) {
+                               $buffer[$comment->getMessage()] = $comment;
+                       }
+               }
+               $actual = $manager->get($comment->getParentId());
+               $this->assertSame($expected, $actual->getReactions());
+       }
+
+       public function providerTestReactionsSummarizeOrdered(): array {
+               return [
+                       [
+                               [
+                                       ['message', 'alice', 'comment', null],
+                                       ['👍', 'alice', 'reaction', 'message'],
+                               ],
+                               ['👍' => 1],
+                       ],
+                       [
+                               [
+                                       ['message', 'alice', 'comment', null],
+                                       ['👎', 'John', 'reaction', 'message'],
+                                       ['👍', 'Paul', 'reaction', 'message'],
+                                       ['👍', 'Peter', 'reaction', 'message'],
+                                       ['💜', 'Matthew', 'reaction', 'message'],
+                                       ['💜', 'Mark', 'reaction', 'message'],
+                                       ['💜', 'Luke', 'reaction', 'message'],
+                               ],
+                               [
+
+                                       '💜' => 3,
+                                       '👍' => 2,
+                                       '👎' => 1,
+                               ],
+                       ],
+               ];
+       }
 }