Wctaiwan has uploaded a new change for review.

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

Change subject: Flow Thanks
......................................................................

Flow Thanks

Add support for thanking other users for comments on Flow boards.

bug: 61930
Change-Id: Id37a14e3c75c63419fc34e0b7c2e21f74b3fa875
Co-authored-by: Bencmq <[email protected]>
---
A ApiFlowThank.php
A FlowThanksFormatter.php
M Thanks.hooks.php
M Thanks.i18n.php
M Thanks.php
M modules/ext.thanks.thank.js
6 files changed, 410 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Thanks 
refs/changes/57/115557/1

diff --git a/ApiFlowThank.php b/ApiFlowThank.php
new file mode 100644
index 0000000..5b83642
--- /dev/null
+++ b/ApiFlowThank.php
@@ -0,0 +1,184 @@
+<?php
+/**
+ * API module to send Flow thanks notifications
+ *
+ * @ingroup API
+ * @ingroup Extensions
+ */
+class ApiFlowThank extends ApiBase {
+       public function execute() {
+               $this->dieIfFlowNotInstalled();
+               $this->dieIfEchoNotInstalled();
+
+               $user = $this->getUser();
+               $this->dieOnBadUser( $user );
+
+               $params = $this->extractRequestParams();
+               $postId = $params['post-id'];
+
+               if ( $this->userAlreadySentThanksForPost( $user, $postId ) ) {
+                       $this->markResultSuccess();
+                       return;
+               }
+
+               $data = $this->getFlowData( $postId );
+
+               $recipient = $this->getRecipientFromPost( $data['post'] );
+               $this->dieOnBadRecipient( $user, $recipient );
+
+               $rootPost = $data['root'];
+               $workflowId = $rootPost->getPostId();
+               $topicTitleText = $rootPost->getContent();
+               $pageTitle = $this->getPageTitleFromRootPost( $rootPost );
+
+               $this->sendThanks(
+                       $user,
+                       $recipient,
+                       $postId,
+                       $workflowId,
+                       $topicTitleText,
+                       $pageTitle
+               );
+       }
+
+       private function dieIfFlowNotInstalled() {
+               if ( !class_exists( 'FlowHooks' ) ) {
+                       $this->dieUsage( 'Flow is not installed on this wiki', 
'flownotinstalled' );
+               }
+       }
+
+       private function dieIfEchoNotInstalled() {
+               if ( !class_exists( 'EchoNotifier' ) ) {
+                       $this->dieUsage( 'Echo is not installed on this wiki', 
'echonotinstalled' );
+               }
+       }
+
+       private function dieOnBadUser( User $user ) {
+               if ( $user->isAnon() ) {
+                       $this->dieUsage( 'Anonymous users cannot send thanks', 
'notloggedin' );
+               } elseif ( $user->pingLimiter( 'thanks-notification' ) ) {
+                       $this->dieUsageMsg( array( 'actionthrottledtext' ) );
+               } elseif ( $user->isBlocked() ) {
+                       $this->dieUsageMsg( array( 'blockedtext' ) );
+               }
+       }
+
+       private function userAlreadySentThanksForPost( User $user, $postId ) {
+               return $user->getRequest()->getSessionData( 
"thanks-thanked-{$postId}" );
+       }
+
+       private function markResultSuccess() {
+               $this->getResult()->addValue( null, 'result', array(
+                       'success' => 1,
+               ) );
+       }
+
+       private function getFlowData( $postId ) {
+               $rootPostLoader = new Flow\Data\RootPostLoader( 
Flow\Container::get( 'storage' ), Flow\Container::get( 'repository.tree' ) );
+               $data = $rootPostLoader->getWithRoot( $postId );
+               if ( $data['post'] === null ) {
+                       $this->dieUsage( 'Supplied post-id is invalid', 
'invalidpostid' );
+               }
+               return $data;
+       }
+
+       private function getRecipientFromPost( $post ) {
+               $uid = $post->getCreatorId();
+               $recipient = User::newFromId( $uid );
+               if ( !$recipient->loadFromId() ) {
+                       $this->dieUsage( 'Recipient is invalid', 
'invalidrecipient' );
+               }
+               return $recipient;
+       }
+
+       private function dieOnBadRecipient( User $agent, User $recipient ) {
+               global $wgThanksSendToBots;
+
+               if ( $agent->getId() === $recipient->getId() ) {
+                       $this->dieUsage( 'You cannot thank yourself', 
'invalidrecipient' );
+               } elseif ( !$wgThanksSendToBots && in_array( 'bot', 
$recipient->getGroups() ) ) {
+                       $this->dieUsage( 'Bots cannot be thanked', 
'invalidrecipient' );
+               }
+       }
+
+       private function getPageTitleFromRootPost( $rootPost ) {
+               $workflow = Flow\Container::get( 'storage' )->get( 'Workflow', 
$rootPost->getPostId() );
+               return $workflow->getArticleTitle();
+       }
+
+       private function sendThanks( User $user, User $recipient, $postId, 
$workflowId, $topicTitleText, Title $pageTitle ) {
+               global $wgThanksLogging;
+
+               // Create the notification via Echo extension
+               EchoEvent::create( array(
+                       'type' => 'flow-thank',
+                       'title' => $pageTitle,
+                       'extra' => array(
+                               'post-id' => $postId,
+                               'workflow' => $workflowId,
+                               'thanked-user-id' => $recipient->getId(),
+                               'topic-title' => $topicTitleText,
+                       ),
+                       'agent' => $user,
+               ) );
+
+               // Mark the thank in session to prevent duplicates (Bug 46690)
+               $user->getRequest()->setSessionData( 
"thanks-thanked-{$postId}", true );
+               // Set success message
+               $this->markResultSuccess();
+               // Log it if we're supposed to log it
+               if ( $wgThanksLogging ) {
+                       $logEntry = new ManualLogEntry( 'thanks', 'thank' );
+                       $logEntry->setPerformer( $user );
+                       $target = $recipient->getUserPage();
+                       $logEntry->setTarget( $target );
+                       $logId = $logEntry->insert();
+                       $logEntry->publish( $logId, 'udp' );
+               }
+       }
+
+       public function getDescription() {
+               return array(
+                       'This API is for sending thank you notifications for 
Flow comments.',
+               );
+       }
+
+       public function getParamDescription() {
+               return array(
+                       'post-id' => 'The UUID of the post to thank for',
+                       'token' => 'An edit token (to prevent CSRF abuse)',
+               );
+       }
+
+       public function getAllowedParams() {
+               return array(
+                       'post-id' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true,
+                       ),
+                       'token' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true,
+                       ),
+               );
+       }
+
+       public function needsToken() {
+               return true;
+       }
+
+       // Writes to the Echo database and sometimes log tables.
+       public function isWriteMode() {
+               return true;
+       }
+
+       public function getTokenSalt() {
+               return '';
+       }
+
+       public function getHelpUrls() {
+               return array(
+                       
'https://www.mediawiki.org/wiki/Extension:Thanks#API_Documentation',
+               );
+       }
+}
diff --git a/FlowThanksFormatter.php b/FlowThanksFormatter.php
new file mode 100644
index 0000000..17b607b
--- /dev/null
+++ b/FlowThanksFormatter.php
@@ -0,0 +1,56 @@
+<?php
+
+class EchoFlowThanksFormatter extends EchoBasicFormatter {
+
+       /**
+        * @param $event EchoEvent
+        * @param $param
+        * @param $message Message
+        * @param $user User
+        */
+       protected function processParam( $event, $param, $message, $user ) {
+               if ( $param === 'postlink' ) {
+                       $eventData = $event->getExtra();
+                       $this->setTitleLink(
+                               $event,
+                               $message,
+                               array(
+                                       'class' => 'mw-echo-diff',
+                                       'linkText' => wfMessage( 
'notification-flow-thanks-post-link' )->text(),
+                                       'param' => array(
+                                               'workflow' => 
$eventData['workflow'],
+                                       ),
+                                       'fragment' => 
"flow-post-{$eventData['post-id']}",
+                               )
+                       );
+               } elseif ( $param === 'topictitle' ) {
+                       $eventData = $event->getExtra();
+                       $message->params( $eventData['topic-title'] );
+               } else {
+                       parent::processParam( $event, $param, $message, $user );
+               }
+       }
+
+       /**
+        * Overriding implementation in EchoBasicFormatter to support Flow posts
+        *
+        * @param EchoEvent $event
+        * @param User $user The user receiving the notification
+        * @param String $destination The destination type for the link, e.g. 
'agent'
+        * @return Array including target and query parameters
+        */
+       protected function getLinkParams( $event, $user, $destination ) {
+               $target = null;
+               $query = array();
+
+               if ( $destination === 'post' ) {
+                       $eventData = $event->getExtra();
+                       $target = $event->getTitle();
+                       $target->setFragment( '#flow-post-' . 
$eventData['post-id'] );
+                       $query['workflow'] = $eventData['workflow'];
+                       return array( $target, $query );
+               } else {
+                       return parent::getLinkParams( $event, $user, 
$destination );
+               }
+       }
+}
diff --git a/Thanks.hooks.php b/Thanks.hooks.php
index 4180c03..3df3d54 100644
--- a/Thanks.hooks.php
+++ b/Thanks.hooks.php
@@ -148,6 +148,22 @@
                        'icon' => 'thanks',
                );
 
+               $notifications['flow-thank'] = array(
+                       'primary-link' => array ( 'message' => 
'notification-link-text-view-post', 'destination' => 'post' ),
+                       'category' => 'edit-thank',
+                       'group' => 'positive',
+                       'formatter-class' => 'EchoFlowThanksFormatter',
+                       'title-message' => 'notification-flow-thanks',
+                       'title-params' => array( 'agent', 'postlink', 
'topictitle', 'title' ),
+                       'flyout-message' => 'notification-flow-thanks-flyout',
+                       'flyout-params' => array( 'agent', 'topictitle', 
'title' ),
+                       'email-subject-message' => 
'notification-flow-thanks-email-subject',
+                       'email-subject-params' => array( 'agent' ),
+                       'email-body-batch-message' => 
'notification-flow-thanks-email-batch-body',
+                       'email-body-batch-params' => array( 'agent', 
'topictitle', 'title' ),
+                       'icon' => 'thanks',
+               );
+
                $icons['thanks'] = array(
                        'path' => 'Thanks/ThankYou.png',
                );
@@ -164,6 +180,7 @@
        public static function onEchoGetDefaultNotifiedUsers( $event, &$users ) 
{
                switch ( $event->getType() ) {
                        case 'edit-thank':
+                       case 'flow-thank':
                                $extra = $event->getExtra();
                                if ( !$extra || !isset( 
$extra['thanked-user-id'] ) ) {
                                        break;
@@ -253,4 +270,100 @@
                $types[] = 'thanks';
                return true;
        }
+
+       /**
+        * Handler for FlowRegisterModules
+        * @param  $context
+        * @return bool
+        */
+       public static function onFlowRegisterModules( $context ) {
+               $context->addModules( array( 'ext.thanks' ) );
+               return true;
+       }
+
+       /**
+        * Handler for FlowAddInteractionLinks
+        * Inserts 'thank' link into flow post interface
+        * @param  $rev     Flow PostRevision object where the Thank link 
belongs to
+        * @param  $links   array of interaction links to be added to interface
+        * @param  $classes associative array for 'active' and 'inactive' link 
CSS classes
+        * @return bool
+        */
+       public static function onFlowAddPostInteractionLinks( $rev, &$links, 
$classes ) {
+               global $wgUser, $wgThanksSendToBots;
+               // Make sure Echo is turned on.
+               // Exclude anonymous users.
+               // Don't let users thank themselves.
+               // Exclude users who are blocked.
+               if ( class_exists( 'EchoNotifier' )
+                       && !$wgUser->isAnon()
+                       && $rev->getCreatorId() != $wgUser->getId()
+                       && !$wgUser->isBlocked()
+                       // TODO: suppression level
+               ) {
+                       $recipient = User::newFromId( $rev->getCreatorId() );
+                       $recipientAllowed = true;
+                       // If bots are not allowed, exclude them as recipients
+                       if ( !$wgThanksSendToBots ) {
+                               $recipientAllowed = !in_array( 'bot', 
$recipient->getGroups() );
+                       }
+                       if ( $recipientAllowed && !$recipient->isAnon() ) {
+                               $links[] = self::generateFlowThankElement( 
$rev, $recipient, $classes );
+                       }
+               }
+               return true;
+       }
+
+       /**
+        * Helper for self::insertThankLink
+        * Creates either a thank link or thanked span based on users session
+        * @param $rev Flow PostRevision object where the Thank link belongs to
+        * @param $recipient User the user who receives thanks notification
+        * @return string HTML segment for the links
+        */
+       protected static function generateFlowThankElement( $rev, $recipient, 
$classes ) {
+               global $wgUser;
+               if ( empty( $classes[ 'active' ] ) ) {
+                       $cssActiveClass = 'mw-thanks-flow-thank-link';
+               } else {
+                       $cssActiveClass = 'mw-thanks-flow-thank-link ' . 
$classes[ 'active' ];
+               }
+
+               if ( empty ( $classes[ 'inactive' ] ) ) {
+                       $cssInactiveClass = 'mw-thanks-flow-thanked';
+               } else {
+                       $cssInactiveClass = 'mw-thanks-flow-thanked ' . 
$classes[ 'inactive' ];
+               }
+
+               // User has already thanked for revision
+               if ( $wgUser->getRequest()->getSessionData( 
"thanks-thanked-{$rev->getPostId()}" ) ) {
+                       return Html::element(
+                               'span',
+                               array( 'class' => $cssInactiveClass ),
+                               wfMessage( 'thanks-button-thanked', $wgUser 
)->parse()
+                       );
+               }
+
+               // Add 'thank' link
+               $tooltip = wfMessage( 'thanks-thank-tooltip' )
+                               ->params( $wgUser->getName(), 
$recipient->getName() )
+                               ->text();
+
+               return Html::element(
+                       'a',
+                       array(
+                               'class' => $cssActiveClass,
+                               'href' => '#', // TODO: No-javascript fallback
+                               'title' => $tooltip,
+                               'data-post-id' => $rev->getPostId()
+                       ),
+                       wfMessage( 'thanks-button-thank', $wgUser )->parse()
+               )
+               . Html::element(
+                       'span',
+                       array( 'class' => $cssInactiveClass,
+                               'style' => 'display:none;' ),  // TODO: is this 
acceptable without using jQuery.hide
+                       wfMessage( 'thanks-button-thanked', $wgUser )->parse()
+               );
+       }
 }
diff --git a/Thanks.i18n.php b/Thanks.i18n.php
index dba7e07..10be3b9 100644
--- a/Thanks.i18n.php
+++ b/Thanks.i18n.php
@@ -39,6 +39,14 @@
        'log-description-thanks' => 'Below is a list of users thanked by other 
users.',
        'logentry-thanks-thank' => '$1 {{GENDER:$2|thanked}} {{GENDER:$4|$3}}',
        'log-show-hide-thanks' => '$1 thanks log',
+
+       //Flow Thanks
+       'notification-link-text-view-post' => 'View post',
+       'notification-flow-thanks' => '[[User:$1|$1]] {{GENDER:$1|thanked}} you 
for $2 in "$3" on [[:$4]].',
+       'notification-flow-thanks-post-link' => 'your comment',
+       'notification-flow-thanks-flyout' => '[[User:$1|$1]] 
{{GENDER:$1|thanked}} you for your comment in "$2" on $3.',
+       'notification-flow-thanks-email-subject' => '$1 {{GENDER:$1|thanked}} 
you for your comment on {{SITENAME}}',
+       'notification-flow-thanks-email-batch-body' => '$1 
{{GENDER:$1|thanked}} you for your comment in "$2" on $3.',
 );
 
 /** Message documentation (Message documentation)
diff --git a/Thanks.php b/Thanks.php
index 4d703e9..110b5b7 100644
--- a/Thanks.php
+++ b/Thanks.php
@@ -43,7 +43,9 @@
 // Register files
 $wgAutoloadClasses['ThanksHooks'] = $dir . '/Thanks.hooks.php';
 $wgAutoloadClasses['EchoThanksFormatter'] = $dir . '/ThanksFormatter.php';
+$wgAutoloadClasses['EchoFlowThanksFormatter'] = $dir . 
'/FlowThanksFormatter.php';
 $wgAutoloadClasses['ApiThank'] = $dir . '/ApiThank.php';
+$wgAutoloadClasses['ApiFlowThank'] = $dir . '/ApiFlowThank.php';
 $wgAutoloadClasses['ThanksLogFormatter'] = $dir . '/ThanksLogFormatter.php';
 $wgAutoloadClasses['SpecialThanks'] = $dir . '/SpecialThanks.php';
 $wgExtensionMessagesFiles['Thanks'] = $dir . '/Thanks.i18n.php';
@@ -52,6 +54,7 @@
 
 // Register APIs
 $wgAPIModules['thank'] = 'ApiThank';
+$wgAPIModules['flow-thank'] = 'ApiFlowThank';
 
 // Register special page
 $wgSpecialPages['Thanks'] = 'SpecialThanks';
@@ -68,6 +71,9 @@
 $wgHooks['UnitTestsList'][] = 'ThanksHooks::registerUnitTests';
 $wgHooks['GetLogTypesOnUser'][] = 'ThanksHooks::onGetLogTypesOnUser';
 
+$wgHooks['FlowAddPostInteractionLinks'][] = 
'ThanksHooks::onFlowAddPostInteractionLinks';
+$wgHooks['FlowRegisterModules'][] = 'ThanksHooks::onFlowRegisterModules';
+
 // Register modules
 $wgResourceModules['ext.thanks'] = array(
        'scripts' => array(
@@ -75,6 +81,7 @@
        ),
        'messages' => array(
                'thanks-thanked',
+               'thanks-button-thanked',
                'thanks-error-undefined',
                'thanks-error-invalidrevision',
                'thanks-error-ratelimited',
diff --git a/modules/ext.thanks.thank.js b/modules/ext.thanks.thank.js
index 6526823..cb89e37 100644
--- a/modules/ext.thanks.thank.js
+++ b/modules/ext.thanks.thank.js
@@ -67,7 +67,7 @@
                } );
                $dialog.dialog( 'open' );
        };
-       
+
        var sendThanks = function( $thankLink ) {
                var source;
                if ( mw.config.get( 'wgAction' ) === 'history' ) {
@@ -119,4 +119,45 @@
                }
        } );
 
+       $( 'a.mw-thanks-flow-thank-link' ).click( function( e ) {
+               var $thankLink = $( this );
+               e.preventDefault();
+               if ( !$thankLink.hasClass( 'mw-thanks-flow-thanked' ) ) {
+                       sendFlowThanks( $thankLink );
+               }
+       } );
+
+       var sendFlowThanks = function( $thankLink ) {
+               var source;
+               if ( mw.config.get( 'wgAction' ) === 'history' ) {
+                       source = 'history';
+               } else {
+                       source = 'diff';
+               }
+               ( new mw.Api ).get( {
+                       'action' : 'flow-thank',
+                       'post-id' : $thankLink.attr( 'data-post-id' ),
+                       'token' : mw.user.tokens.values.editToken
+               } )
+               .done( function( data ) {
+                       $thankLink.next().show();
+                       $thankLink.remove();
+
+                       thanked.push( $thankLink );
+               } )
+               .fail( function( errorCode, details ) {
+                       // TODO: use something besides alert for the error 
messages
+                       switch( errorCode ) {
+                               case 'invalidrevision':
+                                       alert( mw.msg( 
'thanks-error-invalidrevision' ) );
+                                       break;
+                               case 'ratelimited':
+                                       alert( mw.msg( 
'thanks-error-ratelimited', mw.user ) );
+                                       break;
+                               default:
+                                       alert( mw.msg( 'thanks-error-undefined' 
) );
+                       }
+               } );
+       };
+
 } )( jQuery, mediaWiki );

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id37a14e3c75c63419fc34e0b7c2e21f74b3fa875
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Thanks
Gerrit-Branch: master
Gerrit-Owner: Wctaiwan <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to