Make use of the new API for the conversation feed (#192)
authorMarcel Werk <burntime@woltlab.com>
Mon, 5 Feb 2024 15:19:22 +0000 (16:19 +0100)
committerGitHub <noreply@github.com>
Mon, 5 Feb 2024 15:19:22 +0000 (16:19 +0100)
See https://github.com/WoltLab/WCF/pull/5790

.php-cs-fixer.dist.php
files/lib/data/conversation/Conversation.class.php
files/lib/data/conversation/ConversationAction.class.php
files/lib/data/conversation/FeedConversation.class.php
files/lib/data/conversation/FeedConversationList.class.php
files/lib/data/conversation/UserConversationList.class.php
files/lib/page/ConversationFeedPage.class.php
files/lib/page/ConversationRssFeedPage.class.php [new file with mode: 0644]
files/lib/system/cache/runtime/ConversationMessageRuntimeCache.class.php [new file with mode: 0644]
templates/conversationList.tpl

index 60d7da8b007a90ea716844c2b5aaf33f32b138a2..52d79e6aa2a2516347bd4f266be135dfe1d6574c 100644 (file)
@@ -57,7 +57,7 @@ return (new PhpCsFixer\Config())
         'nullable_type_declaration_for_default_null_value' => true,
         'static_lambda' => true,
 
-        'fully_qualified_strict_types' => true,
+        'fully_qualified_strict_types' => ['leading_backslash_in_global_namespace' => true],
         'no_unused_imports' => true,
         'ordered_imports' => true,
 
index 1f59d14487c41a6cd8816a9752d4c023c723963d..abb8fb21bf7a1440b5eef9b2f73d41d8a2cfeb7f 100644 (file)
@@ -8,6 +8,7 @@ use wcf\data\IPopoverObject;
 use wcf\data\user\group\UserGroup;
 use wcf\data\user\ignore\UserIgnore;
 use wcf\data\user\UserProfile;
+use wcf\system\cache\runtime\ConversationMessageRuntimeCache;
 use wcf\system\cache\runtime\UserProfileRuntimeCache;
 use wcf\system\conversation\ConversationHandler;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
@@ -76,12 +77,6 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
      */
     protected $canAddUnrestricted;
 
-    /**
-     * first message object
-     * @var ConversationMessage
-     */
-    protected $firstMessage;
-
     /**
      * true if the current user is an active participant of this conversation
      * @var bool
@@ -313,28 +308,9 @@ class Conversation extends DatabaseObject implements IPopoverObject, IRouteContr
         return $this->canAddUnrestricted;
     }
 
-    /**
-     * Returns the first message in this conversation.
-     *
-     * @return  ConversationMessage
-     */
-    public function getFirstMessage()
-    {
-        if ($this->firstMessage === null) {
-            $this->firstMessage = new ConversationMessage($this->firstMessageID);
-        }
-
-        return $this->firstMessage;
-    }
-
-    /**
-     * Sets the first message.
-     *
-     * @param ConversationMessage $message
-     */
-    public function setFirstMessage(ConversationMessage $message)
+    public function getFirstMessage(): ?ConversationMessage
     {
-        $this->firstMessage = $message;
+        return ConversationMessageRuntimeCache::getInstance()->getObject($this->firstMessageID);
     }
 
     /**
index 335ecbb5d07e893f229c14de83b1daf90f97fdb9..328fdca7965ea3199f4737d43a9511a08faf5676 100644 (file)
@@ -134,7 +134,6 @@ class ConversationAction extends AbstractDatabaseObjectAction implements
             'firstMessageID' => $resultValues['returnValues']->messageID,
         ]);
 
-        $conversation->setFirstMessage($resultValues['returnValues']);
         if (!$conversation->isDraft) {
             // fire notification event
             $notificationRecipients = \array_merge(
@@ -144,7 +143,7 @@ class ConversationAction extends AbstractDatabaseObjectAction implements
             UserNotificationHandler::getInstance()->fireEvent(
                 'conversation',
                 'com.woltlab.wcf.conversation.notification',
-                new ConversationUserNotificationObject($conversation),
+                new ConversationUserNotificationObject(new Conversation($conversation->conversationID)),
                 $notificationRecipients
             );
         }
index 3789a4ec4ebb88abaa47dac13f90d6892df224fa..fc7b097a44987f88dfcf35112ecd6a0c686e6fc2 100644 (file)
@@ -15,6 +15,7 @@ use wcf\system\request\LinkHandler;
  *
  * @method  Conversation    getDecoratedObject()
  * @mixin   Conversation
+ * @deprecated 6.1
  */
 class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
 {
index 7575d6aa588c04cd403bd84b40debf9477ced927..4d1c732994c210358a21e3f2a57b80fdddfef12f 100644 (file)
@@ -16,6 +16,7 @@ use wcf\system\WCF;
  * @method  FeedConversation|null   getSingleObject()
  * @method  FeedConversation|null   search($objectID)
  * @property    FeedConversation[] $objects
+ * @deprecated 6.1
  */
 class FeedConversationList extends ConversationList
 {
index 305250a2e4d17a62a67b77c5be84c1be5be5de75..8a759ad504c9370410fd54919943be1f42a0bb93 100644 (file)
@@ -4,6 +4,7 @@ namespace wcf\data\conversation;
 
 use wcf\data\conversation\label\ConversationLabel;
 use wcf\data\conversation\label\ConversationLabelList;
+use wcf\system\cache\runtime\ConversationMessageRuntimeCache;
 use wcf\system\cache\runtime\UserProfileRuntimeCache;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\WCF;
@@ -216,7 +217,7 @@ class UserConversationList extends ConversationList
 
             $labels = $this->loadLabelAssignments();
 
-            $userIDs = [];
+            $userIDs = $messageIDs = [];
             foreach ($this->objects as $conversationID => $conversation) {
                 if (isset($labels[$conversationID])) {
                     foreach ($labels[$conversationID] as $label) {
@@ -230,11 +231,18 @@ class UserConversationList extends ConversationList
                 if ($conversation->lastPosterID) {
                     $userIDs[] = $conversation->lastPosterID;
                 }
+
+                if ($conversation->firstMessageID) {
+                    $messageIDs[] = $conversation->firstMessageID;
+                }
             }
 
-            if (!empty($userIDs)) {
+            if ($userIDs !== []) {
                 UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
             }
+            if ($messageIDs !== []) {
+                ConversationMessageRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
+            }
         }
     }
 
index 3a0956a17476b81416c453703f06fa33cf7c70f1..ed5798480c748c76a46341e309a9b3ceb2cf2474 100644 (file)
@@ -11,6 +11,7 @@ use wcf\system\WCF;
  * @author  Alexander Ebert
  * @copyright   2001-2019 WoltLab GmbH
  * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @deprecated 6.1 use `ConversationRssFeedPage` instead
  */
 class ConversationFeedPage extends AbstractFeedPage
 {
@@ -19,6 +20,16 @@ class ConversationFeedPage extends AbstractFeedPage
      */
     public $loginRequired = true;
 
+    /**
+     * @inheritDoc
+     */
+    public function readParameters()
+    {
+        parent::readParameters();
+
+        $this->redirectToNewPage(ConversationRssFeedPage::class);
+    }
+
     /**
      * @inheritDoc
      */
diff --git a/files/lib/page/ConversationRssFeedPage.class.php b/files/lib/page/ConversationRssFeedPage.class.php
new file mode 100644 (file)
index 0000000..955ab98
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+
+namespace wcf\page;
+
+use wcf\data\conversation\UserConversationList;
+use wcf\system\rssFeed\RssFeed;
+use wcf\system\rssFeed\RssFeedItem;
+use wcf\system\WCF;
+
+/**
+ * Outputs a list of recent conversations as an rss feed.
+ *
+ * @author      Marcel Werk
+ * @copyright   2001-2024 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ */
+class ConversationRssFeedPage extends AbstractRssFeedPage
+{
+    /**
+     * @inheritDoc
+     */
+    public $loginRequired = true;
+
+    protected UserConversationList $conversations;
+
+    #[\Override]
+    public function readData()
+    {
+        parent::readData();
+
+        $this->conversations = new UserConversationList(WCF::getUser()->userID);
+        $this->conversations->sqlLimit = 20;
+        $this->conversations->sqlOrderBy = 'conversation.lastPostTime DESC';
+        $this->conversations->readObjects();
+    }
+
+    #[\Override]
+    protected function getRssFeed(): RssFeed
+    {
+        $feed = new RssFeed();
+        $channel = $this->getDefaultChannel();
+        $channel->title(WCF::getLanguage()->get('wcf.conversation.conversations'));
+
+        if ($this->conversations->valid()) {
+            $channel->lastBuildDateFromTimestamp($this->conversations->current()->lastPostTime);
+        }
+        $feed->channel($channel);
+
+        foreach ($this->conversations as $conversation) {
+            $item = new RssFeedItem();
+            $item
+                ->title($conversation->getTitle())
+                ->link($conversation->getLink())
+                ->description($conversation->getFirstMessage()->getExcerpt())
+                ->pubDateFromTimestamp($conversation->lastPostTime)
+                ->creator($conversation->lastPoster)
+                ->guid($conversation->getLink())
+                ->contentEncoded($conversation->getFirstMessage()->getSimplifiedFormattedMessage())
+                ->slashComments($conversation->replies);
+
+            $channel->item($item);
+        }
+
+        return $feed;
+    }
+}
diff --git a/files/lib/system/cache/runtime/ConversationMessageRuntimeCache.class.php b/files/lib/system/cache/runtime/ConversationMessageRuntimeCache.class.php
new file mode 100644 (file)
index 0000000..82a1c36
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+
+namespace wcf\system\cache\runtime;
+
+use wcf\data\conversation\message\ConversationMessage;
+use wcf\data\conversation\message\ConversationMessageList;
+
+/**
+ * Runtime cache implementation for conversation messages.
+ *
+ * @author      Matthias Schmidt, Marcel Werk
+ * @copyright   2001-2024 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @since       6.1
+ *
+ * @method  ConversationMessage[]      getCachedObjects()
+ * @method  ConversationMessage        getObject($objectID)
+ * @method  ConversationMessage[]      getObjects(array $objectIDs)
+ */
+class ConversationMessageRuntimeCache extends AbstractRuntimeCache
+{
+    /**
+     * @inheritDoc
+     */
+    protected $listClassName = ConversationMessageList::class;
+}
index 3db37286d6a206979f25427a333136841697678d..268c1ebfb483c056d6bf5f4bb93879eb42d74367 100644 (file)
@@ -27,7 +27,7 @@
 {/capture}
 
 {capture assign='headContent'}
-       <link rel="alternate" type="application/rss+xml" title="{lang}wcf.global.button.rss{/lang}" href="{link controller='ConversationFeed'}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}">
+       <link rel="alternate" type="application/rss+xml" title="{lang}wcf.global.button.rss{/lang}" href="{link controller='ConversationRssFeed'}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}">
 {/capture}
 
 {capture assign='sidebarRight'}
 {/capture}
 
 {capture assign='contentInteractionDropdownItems'}
-       <li><a rel="alternate" href="{link controller='ConversationFeed'}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}">{lang}wcf.global.button.rss{/lang}</a></li>
+       <li><a rel="alternate" href="{link controller='ConversationRssFeed'}at={@$__wcf->getUser()->userID}-{@$__wcf->getUser()->accessToken}{/link}">{lang}wcf.global.button.rss{/lang}</a></li>
 {/capture}
 
 {include file='header'}