Werdna has uploaded a new change for review.

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


Change subject: Flow: Implement initial notifications for 
edit/rename/reply/newtopic
......................................................................

Flow: Implement initial notifications for edit/rename/reply/newtopic

Change-Id: I4da232cd162f85aac71c4f39fc84af66d3c16ae7
---
M Flow.i18n.php
M Flow.php
M Hooks.php
M includes/Block/Topic.php
M includes/Block/TopicList.php
M includes/Container.php
M includes/Model/PostRevision.php
A includes/NotificationFormatter.php
M includes/UrlGenerator.php
M includes/api/ApiFlow.php
M includes/api/ApiQueryFlow.php
M special/SpecialFlow.php
12 files changed, 313 insertions(+), 7 deletions(-)


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

diff --git a/Flow.i18n.php b/Flow.i18n.php
index d162c47..b53e559 100644
--- a/Flow.i18n.php
+++ b/Flow.i18n.php
@@ -67,6 +67,11 @@
 
        'flow-comment-restored' => 'Restored comment',
        'flow-comment-deleted' => 'Deleted comment',
+
+       'flow-notification-reply' => '$1 replied to your [$5 post] in $2 on 
[[$3|$4]].',
+       'flow-notification-edit' => '$1 edited your [$5 post] in $2 on 
[[$3|$4]].',
+       'flow-notification-newtopic' => '$1 created a [$5 new topic] on 
[[$2|$3]]: $4.',
+       'flow-notification-rename' => '$1 changed the title of [$2 $3] to "$4" 
on [[$5|$6]]'
 );
 
 /** Message documentation (Message documentation)
@@ -165,6 +170,33 @@
 
 See also:
 * {{msg-mw|Flow-comment-restored}}',
+
+       'flow-notification-reply' => 'Notification text for when a user 
receives a reply. Parameters:
+* $1: Username of the person who replied.
+* $2: Title of the topic.
+* $3: Title for the Flow board.
+* $4: Title for the page that the Flow board is attached to.
+* $5: Permanent URL for the post.',
+       'flow-notification-edit' => 'Notification text for when a user\'s post 
is edited. Parameters:
+* $1: Username of the person who edited the post.
+* $2: Title of the topic.
+* $3: Title for the Flow board.
+* $4: Title for the page that the Flow board is attached to.
+* $5: Permanent URL for the post.',
+       'flow-notification-newtopic' => 'Notification text for when a new topic 
is created. Parameters:
+* $1: Username of the person who created the topic.
+* $2: Title for the Flow board.
+* $3: Title for the page that the Flow board is attached to.
+* $4: Title of the topic.
+* $5: Permanent URL for the topic.',
+       'flow-notification-rename' => 'Notification text for when the subject 
of a topic is changed. Parameters:
+* $1: Username of the person who edited the title.
+* $2: Permalink to the topic.
+* $3: Old topic subject.
+* $4: New topic subject.
+* $5: Title for the Flow board.
+* $6: Title for the page that the Flow board is attached to.
+',
 );
 
 /** Asturian (asturianu)
diff --git a/Flow.php b/Flow.php
index 6eb6f22..76211f2 100755
--- a/Flow.php
+++ b/Flow.php
@@ -56,6 +56,7 @@
 $wgAutoloadClasses['Flow\UrlGenerator'] = $dir . 'includes/UrlGenerator.php';
 $wgAutoloadClasses['Flow\WorkflowLoader'] = $dir . 
'includes/WorkflowLoader.php';
 $wgAutoloadClasses['Flow\WorkflowLoaderFactory'] = $dir . 
'includes/WorkflowLoader.php';
+$wgAutoloadClasses['FlowCommentFormatter'] = $dir . 
'includes/NotificationFormatter.php';
 
 // Classes that model our data
 $wgAutoloadClasses['Flow\Model\Definition'] = $dir . 
'includes/Model/Definition.php';
diff --git a/Hooks.php b/Hooks.php
index ded1608..426e384 100644
--- a/Hooks.php
+++ b/Hooks.php
@@ -1,11 +1,61 @@
 <?php
 
+use Flow\Model\UUID;
+
 class FlowHooks {
        /**
         * Initialize Flow extension with necessary data, this function is 
invoked
         * from $wgExtensionFunctions
         */
        public static function initFlowExtension() {
+               global $wgEchoNotifications, $wgHooks, $wgEchoNotificationIcons;
+
+               if ( isset( $wgEchoNotifications ) ) {
+                       $wgHooks['EchoGetDefaultNotifiedUsers'][] = 
'FlowHooks::getDefaultNotifiedUsers';
+
+                       $notificationTemplate = array(
+                               'category' => 'flow-discussion',
+                               'group' => 'other',
+                               'formatter-class' => 'FlowCommentFormatter',
+                               'icon' => 'flow-discussion',
+                       );
+
+                       $wgEchoNotifications['flow-new-topic'] = array(
+                               'title-message' => 'flow-notification-newtopic',
+                               'title-params' => array( 'user', 'flow-title', 
'title', 'subject', 'topic-permalink' ),
+                               'payload' => array( 'comment-text' ),
+                       ) + $notificationTemplate;
+
+                       $wgEchoNotifications['flow-post-reply'] = array(
+                               'title-message' => 'flow-notification-reply',
+                               'title-params' => array( 'user', 'subject', 
'flow-title', 'title', 'post-permalink' ),
+                               'payload' => array( 'comment-text' ),
+                       ) + $notificationTemplate;
+
+                       $wgEchoNotifications['flow-post-edited'] = array(
+                               'title-message' => 'flow-notification-edit',
+                               'title-params' => array( 'user', 'subject', 
'flow-title', 'title', 'post-permalink' ),
+                       ) + $notificationTemplate;
+
+                       // Saving for a rainy day
+                       // $wgEchoNotifications['flow-post-moderated'] = array(
+                       //      'title-message' => 
'flow-notification-moderated',
+                       //      'title-params' => array( 'user', 'subject', 
'flow-title', 'title', 'post-permalink' ),
+                       // ) + $notificationTemplate;
+
+                       $wgEchoNotifications['flow-topic-renamed'] = array(
+                               'title-message' => 'flow-notification-rename',
+                               'title-params' => array( 'user', 
'topic-permalink', 'old-subject', 'new-subject', 'flow-title', 'title' ),
+                       ) + $notificationTemplate;
+
+                       $wgEchoNotificationIcons['flow-discussion'] = array(
+                               'path' => 
'Flow/modules/discussion/images/Talk.png',
+                       );
+
+                       $wgEchoNotificationCategories['flow-discussion'] = 
array(
+                               // 'echo-pref'
+                       );
+               }
        }
 
        /**
@@ -31,4 +81,62 @@
                //$files[] = "$dir/DiscussionParserTest.php";
                return true;
        }
+
+       /**
+        * Handler for EchoGetDefaultNotifiedUsers hook
+        *  Returns a list of User objects in the second param
+        *
+        * @param $event EchoEvent being triggered
+        * @param &$users Array of User objects.
+        * @return true
+        */
+       public static function getDefaultNotifiedUsers( EchoEvent $event, 
&$users ) {
+               $container = Flow\Container::getContainer();
+               $storage = $container['storage'];
+               $extra = $event->getExtra();
+               switch ( $event->getType() ) {
+               case 'flow-new-topic':
+                       $title = $event->getTitle();
+                       if ( $title->getNamespace() == NS_USER_TALK ) {
+                               $users[] = User::newFromName( $title->getText() 
);
+                       }
+                       break;
+               case 'flow-topic-renamed':
+                       $postId = $extra['topic-workflow'];
+               case 'flow-post-reply':
+               case 'flow-post-edited':
+               case 'flow-post-moderated':
+                       if ( isset( $extra['reply-to'] ) ) {
+                               $postId = $extra['reply-to'];
+                       } elseif ( ! $postId ) {
+                               $postId = $extra['post-id'];
+                       }
+
+                       $post = $storage->find(
+                               'PostRevision',
+                               array(
+                                       'tree_rev_descendant_id' => 
UUID::create( $postId )
+                               ),
+                               array(
+                                       'sort' => 'rev_id',
+                                       'order' => 'DESC',
+                                       'limit' => 1
+                               )
+                       );
+
+                       $post = reset( $post );
+
+                       if ( $post ) {
+                               $user = User::newFromName( 
$post->getCreatorName() );
+
+                               if ( ! $user->isAnon() ) {
+                                       $users[$user->getId()] = $user;
+                               }
+                       }
+                       break;
+               default:
+                       // Do nothing
+               }
+               return true;
+       }
 }
diff --git a/includes/Block/Topic.php b/includes/Block/Topic.php
index 8420c8b..7f1a009 100644
--- a/includes/Block/Topic.php
+++ b/includes/Block/Topic.php
@@ -10,6 +10,7 @@
 use Flow\DbFactory;
 use Flow\ParsoidUtils;
 use Flow\Templating;
+use EchoEvent;
 use User;
 
 class TopicBlock extends AbstractBlock {
@@ -18,6 +19,7 @@
        protected $topicTitle;
        protected $rootLoader;
        protected $newRevision;
+       protected $notification;
        protected $requestedPost;
 
        // POST actions, GET do not need to be listed
@@ -84,6 +86,14 @@
                        }
 
                        $this->newRevision = $topicTitle->newNextRevision( 
$this->user, $this->submitted['content'], 'flow-edit-title' );
+
+                       $this->setNotification(
+                               'flow-topic-renamed',
+                               array(
+                                       'old-subject' => 
$topicTitle->getContent(),
+                                       'new-subject' => 
$this->newRevision->getContent(),
+                               )
+                       );
                }
        }
 
@@ -108,6 +118,15 @@
                                // TODO: assert post belongs to this tree?  
Does it realy matter?
                                // answer: might not belong, and probably does 
matter due to inter-wiki interaction
                                $this->newRevision = $post->reply( $this->user, 
$this->parsedContent, 'flow-comment-added' );
+
+                               $this->setNotification(
+                                       'flow-post-reply',
+                                       array(
+                                               'reply-to' => 
$post->getPostId(),
+                                               'content' => 
$this->submitted['content'],
+                                               'topic-title' => 
$this->getTitleText(),
+                                       )
+                               );
                        }
                }
        }
@@ -181,6 +200,13 @@
                $post = $this->loadRequestedPost( $this->submitted['postId'] );
                if ( $post ) {
                        $this->newRevision = $post->newNextRevision( 
$this->user, $this->parsedContent, 'flow-edit-post' );
+                       $this->setNotification(
+                                       'flow-post-edited',
+                                       array(
+                                               'content' => 
$this->submitted['content'],
+                                               'topic-title' => 
$this->getTitleText(),
+                                       )
+                               );
                } else {
                        $this->errors['edit-post'] = wfMessage( 
'flow-post-not-found' );
                }
@@ -212,6 +238,13 @@
                                $renderFunction = function( $templating ) use ( 
$self, $newRevision, $rootPost ) {
                                        return $templating->renderPost( 
$newRevision, $self, $rootPost );
                                };
+                       }
+
+                       if ( class_exists( 'EchoEvent' ) && is_array( 
$this->notification ) ) {
+                               $this->notification['extra']['revision-id'] = 
$this->newRevision->getRevisionId();
+                               $this->notification['extra']['post-id'] = 
$this->newRevision->getPostId();
+
+                               EchoEvent::create( $this->notification );
                        }
 
                        $output = array(
@@ -469,6 +502,10 @@
                return $this->topicTitle;
        }
 
+       public function getTitleText() {
+               return $this->loadTopicTitle()->getContent();
+       }
+
        protected function loadTopicHistory() {
                $found = $this->storage->find(
                        'PostRevision',
@@ -515,4 +552,15 @@
                return 'topic';
        }
 
+       protected function setNotification( $notificationType, $extraVars ) {
+               $this->notification = array(
+                               'type' => $notificationType,
+                               'agent' => $this->user,
+                               'title' => $this->workflow->getArticleTitle(),
+                               'extra' => $extraVars + array(
+                                       'topic-workflow' => 
$this->workflow->getId(),
+                               )
+                       );
+       }
+
 }
diff --git a/includes/Block/TopicList.php b/includes/Block/TopicList.php
index 142493f..161b7e2 100644
--- a/includes/Block/TopicList.php
+++ b/includes/Block/TopicList.php
@@ -10,6 +10,7 @@
 use Flow\Data\RootPostLoader;
 use Flow\DbFactory;
 use Flow\Templating;
+use EchoEvent;
 use User;
 
 class TopicListBlock extends AbstractBlock {
@@ -61,6 +62,21 @@
 
                $user = $this->user;
 
+               if ( class_exists( 'EchoEvent' ) ) {
+                       EchoEvent::create( array(
+                               'type' => 'flow-new-topic',
+                               'agent' => $user,
+                               'title' => $this->workflow->getArticleTitle(),
+                               'extra' => array(
+                                       'board-workflow' => 
$this->workflow->getId(),
+                                       'topic-workflow' => 
$topicWorkflow->getId(),
+                                       'post-id' => 
$firstPost->getRevisionId(),
+                                       'topic-title' => 
$this->submitted['topic'],
+                                       'content' => 
$this->submitted['content'],
+                               ),
+                       ) );
+               }
+
                $output = array(
                        'created-topic-id' => $topicWorkflow->getId(),
                        'created-post-id' => $firstPost->getRevisionId(),
diff --git a/includes/Container.php b/includes/Container.php
index a89eb49..6dba03f 100644
--- a/includes/Container.php
+++ b/includes/Container.php
@@ -3,4 +3,24 @@
 namespace Flow;
 
 class Container extends \Pimple {
+       /**
+        * Get a Flow Container
+        * IMPORTANT: If you are using this function, consider if you can 
achieve
+        *  your objectives by passing values from an existing, accessible
+        *  container object instead.
+        * If you use this function outside a Flow entry point (such as a hook,
+        *  special page or API module), there is a good chance that your code
+        *  requires refactoring
+        * 
+        * @return FLow\Container
+        */
+       static function getContainer() {
+               static $container = false;
+
+               if ( $container == false ) {
+                       $container = include __DIR__ . '/../container.php';
+               }
+
+               return $container;
+       }
 }
diff --git a/includes/Model/PostRevision.php b/includes/Model/PostRevision.php
index e91da62..1286c1d 100644
--- a/includes/Model/PostRevision.php
+++ b/includes/Model/PostRevision.php
@@ -87,6 +87,14 @@
                return $this->userText;
        }
 
+       public function getCreatorId() {
+               return $this->origUserId;
+       }
+
+       public function getCreatorName() {
+               return $this->origUserText;
+       }
+
        public function isTopicTitle() {
                return $this->replyToId === null;
        }
diff --git a/includes/NotificationFormatter.php 
b/includes/NotificationFormatter.php
new file mode 100644
index 0000000..7053a9f
--- /dev/null
+++ b/includes/NotificationFormatter.php
@@ -0,0 +1,67 @@
+<?php
+
+use Flow\UrlGenerator;
+
+class FlowCommentFormatter extends EchoBasicFormatter {
+       protected function processParam( $event, $param, $message, $user ) {
+               $extra = $event->getExtra();
+               if ( $param === 'flow-board' ) {
+                       $title = $event->getTitle();
+                       $boardTitle = Special::getTitleFor( 'Flow', 
$title->getPrefixedText() );
+                       $output = $this->formatTitle( $boardTitle );
+                       $message->params( $output );
+               } elseif ( $param === 'subject' ) {
+                       if ( isset( $extra['topic-title'] ) && 
$extra['topic-title'] ) {
+                               $message->params( $extra['topic-title'] );
+                       } else {
+                               $message->params( '' );
+                       }
+               } elseif ( $param === 'commentText' ) {
+                       /**
+                        * @var $wgLang Language
+                        */
+                       global $wgLang; // Message::language is protected :(
+
+                       if ( isset( $extra['content'] ) && $extra['content'] ) {
+                               $content = $extra['content'];
+                               $content = trim( $content );
+                               $content = $wgLang->truncate( $content, 200 );
+
+                               $message->params( $content );
+                       } else {
+                               $message->params( '' );
+                       }
+               } elseif ( $param === 'post-permalink' ) {
+                       $postId = $extra['post-id'];
+                       $url = UrlGenerator::buildUrl(
+                               $event->getTitle(),
+                               'view',
+                               array(
+                                       'topic[postId]' => $postId->getHex(),
+                                       'workflow' => 
$extra['topic-workflow']->getHex(),
+                               )
+                       );
+
+                       $message->params( $url );
+               } elseif ( $param === 'topic-permalink' ) {
+                       $url = UrlGenerator::buildUrl(
+                               $event->getTitle(),
+                               'view',
+                               array(
+                                       'workflow' => 
$extra['topic-workflow']->getHex(),
+                               )
+                       );
+
+                       $message->params( $url );
+               } elseif ( $param == 'flow-title' ) {
+                       $title = $this->formatTitle( SpecialPage::getTitleFor( 
'Flow', $event->getTitle() ) );
+                       $message->params( $title );
+               } elseif ( $param == 'old-subject' ) {
+                       $message->params( $extra['old-subject'] );
+               } elseif ( $param == 'new-subject' ) {
+                       $message->params( $extra['new-subject'] );
+               } else {
+                       parent::processParam( $event, $param, $message, $user );
+               }
+       }
+}
\ No newline at end of file
diff --git a/includes/UrlGenerator.php b/includes/UrlGenerator.php
index c476797..8f54e67 100644
--- a/includes/UrlGenerator.php
+++ b/includes/UrlGenerator.php
@@ -2,13 +2,20 @@
 
 namespace Flow;
 
-use Flow\Model\Workflow;
 use Flow\Data\ObjectManager;
+use Flow\Model\Workflow;
+use SpecialPage;
 use Title;
 
 class UrlGenerator {
        public function __construct( ObjectManager $workflowStorage ) {
                $this->storage = $workflowStorage;
+       }
+
+       public static function buildUrl( $title, $action, $query ) {
+               $query['action'] = $action;
+               return SpecialPage::getTitleFor( 'Flow', 
$title->getPrefixedText() )
+                       ->getFullUrl( $query );
        }
 
        public function generateUrl( $workflow, $action = 'view', array $query 
= array() ) {
@@ -20,14 +27,13 @@
                                throw new \MWException( "Unknown flow object: 
$workflowId" );
                        }
                }
-               $query['action'] = $action;
+               
                if ( $workflow->isNew() ) {
                        $query['definition'] = 
$workflow->getDefinitionId()->getHex();
                } else {
                        $query['workflow'] = $workflow->getId()->getHex();
                }
 
-               return Title::newFromText( 'Flow/' . 
$workflow->getTitleFullText(), NS_SPECIAL )
-                       ->getLinkURL( $query );
+               return self::buildUrl( $workflow->getTitle(), $action, $query );
        }
 }
diff --git a/includes/api/ApiFlow.php b/includes/api/ApiFlow.php
index 0cf4418..46f0379 100644
--- a/includes/api/ApiFlow.php
+++ b/includes/api/ApiFlow.php
@@ -4,7 +4,7 @@
 
 class ApiFlow extends ApiBase {
        public function execute() {
-               $this->container = include __DIR__ . "/../../container.php";
+               $this->container = Flow\Container::getContainer();
                $params = $this->extractRequestParams();
                $output = array();
 
diff --git a/includes/api/ApiQueryFlow.php b/includes/api/ApiQueryFlow.php
index faef3e3..1d4390e 100644
--- a/includes/api/ApiQueryFlow.php
+++ b/includes/api/ApiQueryFlow.php
@@ -11,7 +11,7 @@
        }
 
        public function execute() {
-               $this->container = include __DIR__ . "/../../container.php";
+               $this->container = Flow\Container::getContainer();
                // Get the parameters
                $params = $this->extractRequestParams();
                $passedParams = json_decode( $params['params'], true );
diff --git a/special/SpecialFlow.php b/special/SpecialFlow.php
index cd14148..07cec02 100644
--- a/special/SpecialFlow.php
+++ b/special/SpecialFlow.php
@@ -92,7 +92,7 @@
        }
 
        protected function loadContainer() {
-               $container = include __DIR__ . '/../container.php';
+               $container = Flow\Container::getContainer();
                $container['request'] = $this->getRequest();
                $container['output'] = $this->getOutput();
 

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

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

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

Reply via email to