Matthias Mullie has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/267017

Change subject: Bunch of Flow notification refactors
......................................................................

Bunch of Flow notification refactors

* generate notification for mentions in topic title
* cleaned up the method that generates mentions: just pass in
  those objects immediately, instead of that array with a lot
  of validation checks & exceptions
* stop passing around $data that is available through other
  objects already ('title' & 'reply-to')
* getMentionedUsers didn't work with topic-titles (which can't
  convert to 'wikitext')
* made mentions userlocator more flexible, it will now fetch
  conflicting user locators from config

Bug: T124794
Change-Id: Ibf18c48529eb4f8409f7b66e66beb1f1f1b39381
---
M includes/Data/Listener/NotificationListener.php
M includes/Notifications/Controller.php
M includes/Notifications/UserLocator.php
3 files changed, 46 insertions(+), 72 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Flow 
refs/changes/17/267017/1

diff --git a/includes/Data/Listener/NotificationListener.php 
b/includes/Data/Listener/NotificationListener.php
index 8414133..4005829 100644
--- a/includes/Data/Listener/NotificationListener.php
+++ b/includes/Data/Listener/NotificationListener.php
@@ -53,9 +53,7 @@
                        break;
 
                case 'reply':
-                       $this->notifyPostChange( 'flow-post-reply', $object, 
$metadata, array(
-                               'reply-to' => $metadata['reply-to'],
-                       ) );
+                       $this->notifyPostChange( 'flow-post-reply', $object, 
$metadata );
                        break;
 
                case 'edit-post':
@@ -86,7 +84,6 @@
 
                $this->notificationController->notifyPostChange( $type, $params 
+ array(
                        'revision' => $object,
-                       'title' => $workflow->getOwnerTitle(),
                        'topic-workflow' => $workflow,
                        'topic-title' => $metadata['topic-title'],
                ) );
diff --git a/includes/Notifications/Controller.php 
b/includes/Notifications/Controller.php
index 42f3820..dd6ad0d 100644
--- a/includes/Notifications/Controller.php
+++ b/includes/Notifications/Controller.php
@@ -57,7 +57,6 @@
         * * revision: The PostRevision created by the action. Always required.
         * * title: The Title on which this Topic sits. Always required.
         * * topic-workflow: The Workflow object for the topic. Always required.
-        * * reply-to: The UUID of the post that is being replied to. Required 
for replies.
         * * topic-title: The Title of the Topic that the post belongs to. 
Required except for topic renames.
         * * old-subject: The old subject of a Topic. Required for topic 
renames.
         * * new-subject: The new subject of a Topic. Required for topic 
renames.
@@ -88,7 +87,6 @@
                        throw new FlowException( 'Expected Workflow but 
received ' . get_class( $topicWorkflow ) );
                }
 
-               $title = $data['title'];
                $user = $revision->getUser();
 
                $extraData['revision-id'] = $revision->getRevisionId();
@@ -99,25 +97,13 @@
                $events = array();
                switch( $eventName ) {
                        case 'flow-post-reply':
-                               $replyTo = $data['reply-to'];
-                               if ( !$replyTo instanceof PostRevision ) {
-                                       throw new FlowException( 'Expected 
PostRevision but received ' . get_class( $replyTo ) );
-                               }
-                               $replyToPostId = $replyTo->getPostId();
                                $extraData += array(
-                                       'reply-to' => $replyToPostId,
+                                       'reply-to' => $revision->getReplyToId(),
                                        'content' => Utils::htmlToPlaintext( 
$revision->getContent(), 200, $this->language ),
                                        'topic-title' => 
Utils::htmlToPlaintext( $topicRevision->getContent( 'topic-title-html' ), 200, 
$this->language ),
                                );
 
-                               $mentionEvent = $this->generateMentionEvent( 
array(
-                                       'title' => $title,
-                                       'user' => $user,
-                                       'post' => $revision,
-                                       'reply-to' => $replyToPostId,
-                                       'topic-title' => $topicRevision,
-                                       'topic-workflow' => $topicWorkflow,
-                               ) );
+                               $mentionEvent = $this->generateMentionEvent( 
$revision, $topicRevision, $topicWorkflow, $user );
                                if ( $mentionEvent ) {
                                        $events[] = $mentionEvent;
                                }
@@ -148,7 +134,7 @@
                $info = array(
                        'type' => $eventName,
                        'agent' => $user,
-                       'title' => $title,
+                       'title' => $topicWorkflow->getOwnerTitle(),
                        'extra' => $extraData,
                );
 
@@ -219,6 +205,11 @@
                        )
                ) );
 
+               $mentionEvent = $this->generateMentionEvent( $topicTitle, 
$topicTitle, $topicWorkflow, $user );
+               if ( $mentionEvent ) {
+                       $events[] = $mentionEvent;
+               }
+
                return $events;
        }
 
@@ -242,58 +233,34 @@
        }
 
        /**
-        * Generate flow-mention event, if there is anyone that got mentioned.
-        * @param  array $data Associative array of parameters, all required:
-        * * title: Title for the page on which the new Post sits.
-        * * user: User who created the new Post.
-        * * post: The Post that was created.
-        * * topic-title: The title for the Topic.
-        * @return EchoEvent|null.
-        * @throws FlowException When $data contains unexpected types/values
+        * @param PostRevision $content The (post|topic) revision that contains 
the content of the mention
+        * @param PostRevision $topic Topic PostRevision object
+        * @param Workflow $workflow Topic Workflow object
+        * @param User $user User who created the new post
+        * @return bool|EchoEvent
+        * @throws Exception\InvalidDataException
+        * @throws \MWException
         */
-       protected function generateMentionEvent( $data ) {
-               // Handle mentions.
-               $newRevision = $data['post'];
-               if ( $newRevision !== null && !$newRevision instanceof 
PostRevision ) {
-                       throw new FlowException( 'Expected PostRevision but 
received ' . get_class( $newRevision ) );
-               }
-               $topicRevision = $data['topic-title'];
-               if ( !$topicRevision instanceof PostRevision ) {
-                       throw new FlowException( 'Expected PostRevision but 
received ' . get_class( $topicRevision ) );
-               }
-               $title = $data['title'];
-               if ( !$title instanceof \Title ) {
-                       throw new FlowException( 'Expected Title but received ' 
. get_class( $title ) );
-               }
-               $user = $data['user'];
-               $topicWorkflow = $data['topic-workflow'];
-               if ( !$topicWorkflow instanceof Workflow ) {
-                       throw new FlowException( 'Expected Workflow but 
received ' . get_class( $topicWorkflow ) );
-               }
-
-               $mentionedUsers = $newRevision ? $this->getMentionedUsers( 
$newRevision, $title ) : array();
-
-               if ( !$topicRevision instanceof PostRevision ) {
-                       throw new FlowException( 'Expected PostRevision but 
received: ' . get_class( $topicRevision ) );
-               }
-
+       protected function generateMentionEvent( PostRevision $content, 
PostRevision $topic, Workflow $workflow, User $user ) {
+               $title = $workflow->getOwnerTitle();
+               $mentionedUsers = $this->getMentionedUsers( $content, $title );
                if ( count( $mentionedUsers ) === 0 ) {
-                       return null;
+                       return false;
                }
 
                return EchoEvent::create( array(
                        'type' => 'flow-mention',
                        'title' => $title,
                        'extra' => array(
-                               'content' => $newRevision
-                                       ? Utils::htmlToPlaintext( 
$newRevision->getContent(), 200, $this->language )
-                                       : null,
-                               'topic-title' => Utils::htmlToPlaintext( 
$topicRevision->getContent( 'topic-title-html' ), 200, $this->language ),
-                               'post-id' => $newRevision ? 
$newRevision->getPostId() : null,
+                               // don't include topic content again if the 
notification IS in the title
+                               'content' => $content !== $topic ? 
Utils::htmlToPlaintext( $content->getContent(), 200, $this->language ) : '',
+                               'topic-title' => Utils::htmlToPlaintext( 
$topic->getContent( 'topic-title-html' ), 200, $this->language ),
+                               'post-id' => $content->getPostId(),
                                'mentioned-users' => $mentionedUsers,
-                               'topic-workflow' => $topicWorkflow->getId(),
-                               'target-page' => 
$topicWorkflow->getArticleTitle()->getArticleID(),
-                               'reply-to' => isset( $data['reply-to'] ) ? 
$data['reply-to'] : null
+                               'topic-workflow' => $workflow->getId(),
+                               'target-page' => 
$workflow->getArticleTitle()->getArticleID(),
+                               // used to exclude mentions for authors already 
getting a "replied to your post" notification
+                               'reply-to' => $content->getReplyToId()
                        ),
                        'agent' => $user,
                ) );
@@ -303,14 +270,14 @@
         * Analyses a PostRevision to determine which users are mentioned.
         *
         * @param PostRevision $post The Post to analyse.
-        * @param \Title $title
+        * @param Title $title
         * @return User[] Array of User objects.
         */
-       protected function getMentionedUsers( $post, $title ) {
+       protected function getMentionedUsers( PostRevision $post, Title $title 
) {
                // At the moment, it is not possible to get a list of mentioned 
users from HTML
                //  unless that HTML comes from Parsoid. But VisualEditor (what 
is currently used
                //  to convert wikitext to HTML) does not currently use Parsoid.
-               $wikitext = $post->getContent( 'wikitext' );
+               $wikitext = $post->getContentInWikitext();
                $mentions = $this->getMentionedUsersFromWikitext( $wikitext );
                $notifyUsers = $this->filterMentionedUsers( $mentions, $post, 
$title );
 
@@ -325,7 +292,7 @@
         * owner of the talk page
         * @param  User[] $mentions Array of User objects
         * @param  PostRevision $post The Post that is being examined.
-        * @param  \Title $title The Title of the page that the comment is made 
on.
+        * @param  Title $title The Title of the page that the comment is made 
on.
         * @return array Array of user IDs
         */
        protected function filterMentionedUsers( $mentions, PostRevision $post, 
$title ) {
diff --git a/includes/Notifications/UserLocator.php 
b/includes/Notifications/UserLocator.php
index 61737e3..f357937 100644
--- a/includes/Notifications/UserLocator.php
+++ b/includes/Notifications/UserLocator.php
@@ -94,11 +94,21 @@
                        return array();
                }
 
-               // figure out which users may already receive a notification 
for this event because they're author,
-               // or because they're watching this topic
+               $notifications = require __DIR__ . "/Notifications.php";
+               $extra = $event->getExtra();
+
+               /*
+                * Figure out which users may already receive a notification 
for this
+                * (e.g. because they're watching this)
+                * Mention notifications are triggered for new topics & for 
replies:
+                * let's fetch their locators & see which those events will 
already
+                * notify, so that we can discard those users here.
+                */
+               $conflict = isset( $extra['reply-to'] ) ? 'flow-post-reply' : 
'flow-new-topic';
+               $locators = $notifications[$conflict]['user-locators'];
                $notifiedUsers = array();
-               $locators = array( self::locatePostAuthors( $event ), 
self::locateUsersWatchingTopic( $event ) );
-               foreach ( $locators as $locator ) {
+               foreach ( $locators as $callable ) {
+                       $locator = call_user_func( $callable, $event );
                        /** @var User $user */
                        foreach ( $locator as $user ) {
                                $notifiedUsers[$user->getId()] = $user;

-- 
To view, visit https://gerrit.wikimedia.org/r/267017
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibf18c48529eb4f8409f7b66e66beb1f1f1b39381
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to