Jack Phoenix has uploaded a new change for review.

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

Change subject: [WIP] Initial Echo integration and replacement of old AJAX 
stuff with API modules, based on ikasty's code
......................................................................

[WIP] Initial Echo integration and replacement of old AJAX stuff with API 
modules, based on ikasty's code

Original diff can be found at
https://github.com/wiki-chan/Social/commit/bb932d15d36bcb4ee076bdcf0e8494496eb0906b
Some cleanup, etc. by me.

* Renamed SocialFormatter to SocialProfileEchoFormatter (more descriptive name)
* Renamed API modules to clearly mark them as such
** SendUserBoardMessage --> ApiSendUserBoardMessage
** RelationshipResponse --> ApiRelationshipResponse
* Also prefixed the API actions with socialprofile- instead of social-, for 
consistency (unlike the Wiki-Chan fork, SocialProfile's canonical name is 
SocialProfile); i.e. socialprofile-send-message instead of social-send-message 
for the UserBoard API module used to send out board messages
* Added new API module for deleting UserBoard messages 
(ApiDeleteUserBoardMessage)
* Removed SocialProfileEchoFormatter::truncate() in favor of making 
SocialProfileEchoFormatter::formatPayload() call 
$this->getLanguage()->truncate( ... )
* Made the API modules use $this->getUser() instead of the global $wgUser
* Translated various hard-coded Korean strings (via Google Translate) in the 
API modules to English

And random, not directly related changes nevertheless bundled here:
* Moved one hard-coded English string from UserProfilePage.js into the
* i18n file
** This is kinda shitty because technically it should be and actually *is*
already a UserBoard string (userboard_confirmdelete) and now it's
duplicated here as user-board-confirm-delete
* And also in UserProfilePage.js, got rid of an unnecessary variable (replaceID)

TODO/FIXME before merging:
* Figure out when and where [[MediaWiki:Notification-social-msg-send-bundle]] 
is used and translate it into English so that we don't have Korean text in an 
English file (!)
* Test out foeing and edit UserRelationship Echo i18n strings accordingly 
and/or write new code to handle foes
* Test out the strings and adjust 'em accordingly to ensure they fit into the 
UI and look sane in general
* Finnish (fi) i18n
* Add support for the following things, which UserWelcome already supports 
(since Echo integration has the potential to eventually replace UserWelcome):
** gifts
** awards
** user levels
* Rename some/all remaining things prefixed with social- to be prefixed with 
socialprofile- instead? (i.e. in UserRelationshipHooks.php etc.)
* API i18n? (not a blocker functionality-wise, though)

Bug: T64520
Change-Id: I0c610c2bd33955c7f36619df9a3ce6b61b3c134f
---
M SocialProfile.php
A SocialProfileEchoFormatter.php
A UserBoard/ApiDeleteUserBoardMessage.php
A UserBoard/ApiSendUserBoardMessage.php
M UserBoard/UserBoard.js
M UserBoard/UserBoardClass.php
A UserBoard/UserBoardHooks.php
D UserBoard/UserBoard_AjaxFunctions.php
M UserBoard/i18n/en.json
M UserProfile/UserProfile.php
M UserProfile/UserProfilePage.js
M UserProfile/i18n/en.json
A UserRelationship/ApiRelationshipResponse.php
D UserRelationship/Relationship_AjaxFunctions.php
M UserRelationship/UserRelationship.js
M UserRelationship/UserRelationshipClass.php
A UserRelationship/UserRelationshipHooks.php
M UserRelationship/i18n/en.json
18 files changed, 545 insertions(+), 120 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/SocialProfile 
refs/changes/68/278868/1

diff --git a/SocialProfile.php b/SocialProfile.php
index 3cb910b..fe307f9 100644
--- a/SocialProfile.php
+++ b/SocialProfile.php
@@ -31,12 +31,13 @@
 $wgMessagesDirs['SocialProfileUserProfile'] = __DIR__ . '/UserProfile/i18n';
 $wgMessagesDirs['SocialProfileUserRelationship'] = __DIR__ . 
'/UserRelationship/i18n';
 $wgMessagesDirs['SocialProfileUserStats'] = __DIR__ . '/UserStats/i18n';
+
 $wgExtensionMessagesFiles['SocialProfileNamespaces'] = __DIR__ . 
'/SocialProfile.namespaces.php';
 $wgExtensionMessagesFiles['AvatarMagic'] = __DIR__ . 
'/UserProfile/Avatar.magic.i18n.php';
 
 // Classes to be autoloaded
 $wgAutoloadClasses['GenerateTopUsersReport'] = __DIR__ . 
'/UserStats/GenerateTopUsersReport.php';
-
+$wgAutoloadClasses['SocialProfileEchoFormatter'] = __DIR__ . 
'/SocialProfileEchoFormatter.php';
 $wgAutoloadClasses['SpecialAddRelationship'] = __DIR__ . 
'/UserRelationship/SpecialAddRelationship.php';
 $wgAutoloadClasses['SpecialBoardBlast'] = __DIR__ . 
'/UserBoard/SpecialSendBoardBlast.php';
 $wgAutoloadClasses['SpecialEditProfile'] = __DIR__ . 
'/UserProfile/SpecialEditProfile.php';
@@ -52,9 +53,11 @@
 $wgAutoloadClasses['RemoveAvatar'] = __DIR__ . 
'/UserProfile/SpecialRemoveAvatar.php';
 $wgAutoloadClasses['UpdateEditCounts'] = __DIR__ . 
'/UserStats/SpecialUpdateEditCounts.php';
 $wgAutoloadClasses['UserBoard'] = __DIR__ . '/UserBoard/UserBoardClass.php';
+$wgAutoloadClasses['UserBoardHooks'] = __DIR__ . 
'/UserBoard/UserBoardHooks.php';
 $wgAutoloadClasses['UserProfile'] = __DIR__ . 
'/UserProfile/UserProfileClass.php';
 $wgAutoloadClasses['UserProfilePage'] = __DIR__ . 
'/UserProfile/UserProfilePage.php';
 $wgAutoloadClasses['UserRelationship'] = __DIR__ . 
'/UserRelationship/UserRelationshipClass.php';
+$wgAutoloadClasses['UserRelationshipHooks'] = __DIR__ . 
'/UserRelationship/UserRelationshipHooks.php';
 $wgAutoloadClasses['UserLevel'] = __DIR__ . '/UserStats/UserStatsClass.php';
 $wgAutoloadClasses['UserStats'] = __DIR__ . '/UserStats/UserStatsClass.php';
 $wgAutoloadClasses['UserStatsTrack'] = __DIR__ . 
'/UserStats/UserStatsClass.php';
@@ -67,9 +70,34 @@
 $wgAutoloadClasses['AvatarParserFunction'] = __DIR__ . 
'/UserProfile/AvatarParserFunction.php';
 $wgAutoloadClasses['SPUserSecurity'] = __DIR__ . 
'/UserSecurity/UserSecurityClass.php';
 
-// API module
+// API modules
 $wgAutoloadClasses['ApiUserProfilePrivacy'] = __DIR__ . 
'/UserProfile/ApiUserProfilePrivacy.php';
 $wgAPIModules['smpuserprivacy'] = 'ApiUserProfilePrivacy';
+
+$wgAutoloadClasses['ApiDeleteUserBoardMessage'] = __DIR__ . 
'/UserBoard/ApiDeleteUserBoardMessage.php';
+$wgAPIModules['socialprofile-delete-message'] = 'ApiDeleteUserBoardMessage';
+
+$wgAutoloadClasses['ApiSendUserBoardMessage'] = __DIR__ . 
'/UserBoard/ApiSendUserBoardMessage.php';
+$wgAPIModules['socialprofile-send-message'] = 'ApiSendUserBoardMessage';
+
+$wgAutoloadClasses['ApiRelationshipResponse'] = __DIR__ . 
'/UserRelationship/ApiRelationshipResponse.php';
+$wgAPIModules['socialprofile-request-response'] = 'ApiRelationshipResponse';
+
+// Echo (Notifications) stuff
+// UserBoard
+$wgHooks['BeforeCreateEchoEvent'][] = 
'UserBoardHooks::onBeforeCreateEchoEvent';
+$wgHooks['EchoGetDefaultNotifiedUsers'][] = 
'UserBoardHooks::onEchoGetDefaultNotifiedUsers';
+$wgHooks['EchoGetBundleRules'][] = 'UserBoardHooks::onEchoGetBundleRules';
+
+$wgDefaultUserOptions['echo-subscriptions-web-social-msg'] = true;
+$wgDefaultUserOptions['echo-subscriptions-email-social-msg'] = false;
+
+// UserRelationship
+$wgHooks['BeforeCreateEchoEvent'][] = 
'UserRelationshipHooks::onBeforeCreateEchoEvent';
+$wgHooks['EchoGetDefaultNotifiedUsers'][] = 
'UserRelationshipHooks::onEchoGetDefaultNotifiedUsers';
+
+$wgDefaultUserOptions['echo-subscriptions-web-social-rel'] = true;
+$wgDefaultUserOptions['echo-subscriptions-email-social-rel'] = false;
 
 // New special pages
 $wgSpecialPages['AddRelationship'] = 'SpecialAddRelationship';
@@ -89,10 +117,6 @@
 $wgSpecialPages['UserBoard'] = 'SpecialViewUserBoard';
 $wgSpecialPages['ViewRelationshipRequests'] = 
'SpecialViewRelationshipRequests';
 $wgSpecialPages['ViewRelationships'] = 'SpecialViewRelationships';
-
-// Necessary AJAX functions
-require_once( 
"$IP/extensions/SocialProfile/UserBoard/UserBoard_AjaxFunctions.php" );
-require_once( 
"$IP/extensions/SocialProfile/UserRelationship/Relationship_AjaxFunctions.php" 
);
 
 // What to display on social profile pages by default?
 $wgUserProfileDisplay['board'] = true;
@@ -116,7 +140,7 @@
        'path' => __FILE__,
        'name' => 'SocialProfile',
        'author' => array( 'Aaron Wright', 'David Pean', 'Jack Phoenix' ),
-       'version' => '1.8',
+       'version' => '1.9',
        'url' => 'https://www.mediawiki.org/wiki/Extension:SocialProfile',
        'descriptionmsg' => 'socialprofile-desc',
 );
@@ -306,6 +330,7 @@
 
 $wgResourceModules['ext.socialprofile.userrelationship.js'] = array(
        'scripts' => 'UserRelationship.js',
+       'dependencies' => 'mediawiki.util',
        'localBasePath' => __DIR__ . '/UserRelationship',
        'remoteExtPath' => 'SocialProfile/UserRelationship',
 );
diff --git a/SocialProfileEchoFormatter.php b/SocialProfileEchoFormatter.php
new file mode 100644
index 0000000..397df8a
--- /dev/null
+++ b/SocialProfileEchoFormatter.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Formatter class for the Echo (Notifications) framework.
+ *
+ * @file
+ * @ingroup Extensions
+ * @author ikasty
+ */
+class SocialProfileEchoFormatter extends EchoBasicFormatter {
+       /**
+        * @param EchoEvent $event
+        * @param string $param
+        * @param Message $message
+        * @param User $user
+        */
+       protected function processParam( $event, $param, $message, $user ) {
+               switch ( $param ) {
+                       case 'user':
+                               $extra = $event->getExtra();
+                               $target_id = $extra['from'];
+                               $target_user = User::newFromId( $target_id );
+                               $target_title = $target_user->getUserPage();
+
+                               $link = $this->buildLinkParam( $target_title, 
array(
+                                       'linkText' => $target_user->getName()
+                               ) );
+                               $message->params( $link );
+                               break;
+
+                       case 'relationship':
+                               $title = SpecialPage::getTitleFor( 
'ViewRelationshipRequests' );
+                               $link = $this->buildLinkParam( $title, array(
+                                       'linkText' => $this->getMessage( 
'echo-show-social-rel-add-link' )->text()
+                               ) );
+                               $message->params( $link );
+                               break;
+
+                       case 'bundle-user-count':
+                               // @todo I have no idea what the Korean comment 
below means and
+                               // everyone's favorite online translator tool 
isn't being very
+                               // useful here. --ashley, 22 March 2016
+                               $user_count = 
$this->bundleData['agent-other-count'] + 1; // 나 빼고 다른 사람 + 나
+                               $message->params( $user_count );
+                               break;
+
+                       case 'bundle-noti-count':
+                               $noti_count = 
$this->bundleData['raw-data-count'];
+                               $message->params( $noti_count );
+                               break;
+
+                       default:
+                               parent::processParam( $event, $param, $message, 
$user );
+               }
+       }
+
+       /**
+        * Formats the payload of a notification.
+        *
+     * @param $payload string
+     * @param $event EchoEvent
+     * @param $user User
+     * @return string
+        */
+       protected function formatPayload( $payload, $event, $user ) {
+               switch ( $payload ) {
+                       case 'relationship-add':
+                               $extra = $event->getExtra();
+                               return $extra['message'];
+                               break;
+                       case 'send-message':
+                               $extra = $event->getExtra();
+                               $message = $this->getLanguage()->truncate( 
$extra['message'], 100 );
+                               return $message;
+                               break;
+                       default:
+                               return parent::formatPayload( $payload, $event, 
$user );
+                               break;
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/UserBoard/ApiDeleteUserBoardMessage.php 
b/UserBoard/ApiDeleteUserBoardMessage.php
new file mode 100644
index 0000000..b1428bb
--- /dev/null
+++ b/UserBoard/ApiDeleteUserBoardMessage.php
@@ -0,0 +1,52 @@
+<?php
+
+class ApiDeleteUserBoardMessage extends ApiBase {
+       public function execute() {
+               $main = $this->getMain();
+               $user = $this->getUser();
+
+               $messageId = $main->getVal( 'id' );
+
+               // Don't allow deleting messages when the database is locked 
for some reason
+               if ( wfReadOnly() ) {
+                       $this->getResult()->addValue( null, 'result', 'You 
cannot delete messages right now.' );
+                       return true;
+               }
+
+               $b = new UserBoard();
+               if (
+                       $b->doesUserOwnMessage( $user->getId(), $messageId ) ||
+                       $user->isAllowed( 'userboard-delete' )
+               )
+               {
+                       $b->deleteMessage( $messageId );
+               }
+
+               $this->getResult()->addValue( null, 'result', 'ok' );
+
+               return true;
+       }
+
+       public function getDescription() {
+               return 'Delete a UserBoard message.';
+       }
+
+       public function getAllowedParams() {
+               return array_merge( parent::getAllowedParams(), array(
+                       'id' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_REQUIRED => false
+                       )
+               ) );
+       }
+
+       public function getParamDescription() {
+               return array_merge( parent::getParamDescription(), array(
+                       'id' => 'Unique identifier of the board message to 
delete.'
+               ) );
+       }
+
+       public function getExamplesMessages() {
+               return array();
+       }
+}
\ No newline at end of file
diff --git a/UserBoard/ApiSendUserBoardMessage.php 
b/UserBoard/ApiSendUserBoardMessage.php
new file mode 100644
index 0000000..5bf6622
--- /dev/null
+++ b/UserBoard/ApiSendUserBoardMessage.php
@@ -0,0 +1,71 @@
+<?php
+
+class ApiSendUserBoardMessage extends ApiBase {
+       public function execute() {
+               $main = $this->getMain();
+
+               $user_name = $main->getVal( 'username' );
+               $message = $main->getVal( 'message' );
+               $message_type = $main->getVal( 'type' ) || 0;
+
+               $user = $this->getUser();
+
+               // Don't allow blocked users to send messages and also don't 
allow message
+               // sending when the database is locked for some reason
+               if ( $user->isBlocked() || wfReadOnly() ) {
+                       $this->getResult()->addValue( null, 'result', 'You 
cannot send messages.' );
+                       return true;
+               }
+
+               $user_name = stripslashes( $user_name );
+               $user_name = urldecode( $user_name );
+               $user_id_to = User::idFromName( $user_name );
+               $b = new UserBoard();
+
+               $m = $b->sendBoardMessage(
+                       $user->getId(),
+                       $user->getName(),
+                       $user_id_to,
+                       $user_name,
+                       urldecode( $message ),
+                       $message_type
+               );
+
+               $this->getResult()->addValue( null, 'result', 
$b->displayMessages( $user_id_to, 0, 1 ) );
+
+               return true;
+       }
+
+       public function getDescription() {
+               return 'Send a message to a user\'s UserBoard.';
+       }
+
+       public function getAllowedParams() {
+               return array_merge( parent::getAllowedParams(), array(
+                       'username' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true
+                       ),
+                       'message' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => true
+                       ),
+                       'type' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_REQUIRED => false
+                       )
+               ) );
+       }
+
+       public function getParamDescription() {
+               return array_merge( parent::getParamDescription(), array(
+                       'username' => 'The recipient\'s user name.',
+                       'message' => 'urlencoded version of the message to 
send.',
+                       'type' => 'Message type; 0 for a public message, 1 for 
a private message.'
+               ) );
+       }
+
+       public function getExamplesMessages() {
+               return array();
+       }
+}
\ No newline at end of file
diff --git a/UserBoard/UserBoard.js b/UserBoard/UserBoard.js
index 5ec071a..ba61efe 100644
--- a/UserBoard/UserBoard.js
+++ b/UserBoard/UserBoard.js
@@ -14,10 +14,12 @@
                                encodedMsg = encodeURIComponent( message ),
                                messageType = document.getElementById( 
'message_type' ).value;
                        jQuery.post(
-                               mediaWiki.util.wikiScript(), {
-                                       action: 'ajax',
-                                       rs: 'wfSendBoardMessage',
-                                       rsargs: [encodedName, encodedMsg, 
messageType, perPage]
+                               mediaWiki.util.wikiScript( 'api' ), {
+                                       action: 'socialprofile-send-message',
+                                       format: 'json',
+                                       username: encodedName,
+                                       message: encodedMsg,
+                                       type: messageType
                                },
                                function() {
                                        UserBoard.posted = 0;
@@ -40,10 +42,10 @@
        deleteMessage: function( id ) {
                if ( window.confirm( mediaWiki.msg( 'userboard_confirmdelete' ) 
) ) {
                        jQuery.post(
-                               mediaWiki.util.wikiScript(), {
-                                       action: 'ajax',
-                                       rs: 'wfDeleteBoardMessage',
-                                       rsargs: [id]
+                               mediaWiki.util.wikiScript( 'api' ), {
+                                       action: 'socialprofile-delete-message',
+                                       format: 'json',
+                                       'id': id
                                },
                                function() {
                                        //window.location.reload();
diff --git a/UserBoard/UserBoardClass.php b/UserBoard/UserBoardClass.php
index d2a5aa0..291cd2d 100644
--- a/UserBoard/UserBoardClass.php
+++ b/UserBoard/UserBoardClass.php
@@ -60,6 +60,21 @@
                $stats = new UserStatsTrack( $user_id_from, $user_name_from );
                $stats->incStatField( 'user_board_sent' );
 
+               if ( class_exists( 'EchoEvent' ) ) {
+                       $userFrom = User::newFromId( $user_id_from );
+
+                       EchoEvent::create( array(
+                               'type' => 'social-msg-send',
+                               'agent' => $userFrom,
+                               'extra' => array(
+                                       'target' => $user_id_to,
+                                       'from' => $user_id_from,
+                                       'type' => $message_type,
+                                       'message' => $message
+                               )
+                       ) );
+               }
+
                return $dbw->insertId();
        }
 
diff --git a/UserBoard/UserBoardHooks.php b/UserBoard/UserBoardHooks.php
new file mode 100644
index 0000000..4087aa3
--- /dev/null
+++ b/UserBoard/UserBoardHooks.php
@@ -0,0 +1,70 @@
+<?php
+
+class UserBoardHooks {
+       /**
+        * For the Echo extension.
+        *
+        * @param array $notifications Echo notifications
+        * @param array $notificationCategories Echo notification categories
+        * @param array $icons Icon details
+        * @return bool
+        */
+       public static function onBeforeCreateEchoEvent( &$notifications, 
&$notificationCategories, &$icons ) {
+               $notificationCategories['social-msg'] = array(
+                       'priority' => 3,
+                       'tooltip' => 'echo-pref-tooltip-social-msg',
+               );
+
+               $notifications['social-msg-send'] = array(
+                       'category' => 'social-msg',
+                       'group' => 'interactive',
+                       'formatter-class' => 'SocialProfileEchoFormatter',
+
+                       'title-message' => 'notification-social-msg-send',
+                       'title-params' => array( 'user' ),
+                       'payload' => array( 'send-message' ),
+
+                       'icon' => 'mention',
+
+                       'bundle' => array( 'web' => true, 'email' => true ),
+                       'bundle-message' => 
'notification-social-msg-send-bundle',
+                       'bundle-params' => array( 'bundle-user-count', 
'bundle-noti-count' )
+               );
+
+               return true;
+       }
+
+       /**
+        * Add user to be notified on Echo event
+        *
+        * @param EchoEvent $event
+        * @param array $users
+        * @return bool
+        */
+       public static function onEchoGetDefaultNotifiedUsers( $event, &$users ) 
{
+               switch ( $event->getType() ) {
+                       case 'social-msg-send':
+                               $extra = $event->getExtra();
+                               $targetId = $extra['target'];
+                               $users[] = User::newFromId( $targetId );
+                               break;
+               }
+               return true;
+       }
+
+       /**
+        * Set bundle for message
+        *
+        * @param EchoEvent $event
+        * @param string $bundleString
+        * @return bool
+        */
+       public static function onEchoGetBundleRules( $event, &$bundleString ) {
+               switch ( $event->getType() ) {
+                       case 'social-msg-send':
+                               $bundleString = 'social-msg-send';
+                               break;
+               }
+               return true;
+       }
+}
\ No newline at end of file
diff --git a/UserBoard/UserBoard_AjaxFunctions.php 
b/UserBoard/UserBoard_AjaxFunctions.php
deleted file mode 100644
index b0d3057..0000000
--- a/UserBoard/UserBoard_AjaxFunctions.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/**
- * AJAX functions used by UserBoard.
- */
-$wgAjaxExportList[] = 'wfSendBoardMessage';
-function wfSendBoardMessage( $user_name, $message, $message_type, $count ) {
-       global $wgUser;
-
-       // Don't allow blocked users to send messages and also don't allow 
message
-       // sending when the database is locked for some reason
-       if ( $wgUser->isBlocked() || wfReadOnly() ) {
-               return '';
-       }
-
-       $user_name = stripslashes( $user_name );
-       $user_name = urldecode( $user_name );
-       $user_id_to = User::idFromName( $user_name );
-       $b = new UserBoard();
-
-       $m = $b->sendBoardMessage(
-               $wgUser->getID(), $wgUser->getName(), $user_id_to, $user_name,
-               urldecode( $message ), $message_type
-       );
-
-       return $b->displayMessages( $user_id_to, 0, $count );
-}
-
-$wgAjaxExportList[] = 'wfDeleteBoardMessage';
-function wfDeleteBoardMessage( $ub_id ) {
-       global $wgUser;
-
-       // Don't allow deleting messages when the database is locked for some 
reason
-       if ( wfReadOnly() ) {
-               return '';
-       }
-
-       $b = new UserBoard();
-       if (
-               $b->doesUserOwnMessage( $wgUser->getID(), $ub_id ) ||
-               $wgUser->isAllowed( 'userboard-delete' )
-       ) {
-               $b->deleteMessage( $ub_id );
-       }
-
-       return 'ok';
-}
\ No newline at end of file
diff --git a/UserBoard/i18n/en.json b/UserBoard/i18n/en.json
index b04486b..99dad4c 100644
--- a/UserBoard/i18n/en.json
+++ b/UserBoard/i18n/en.json
@@ -56,5 +56,9 @@
        "userboard-time-seconds": "{{PLURAL:$1|one second|$1 seconds}}",
        "message_received_subject": "$1 wrote on your board on {{SITENAME}}",
        "message_received_body_html": "Hi $1.\n\n$2 just wrote on your board on 
{{SITENAME}}!\n\nClick below to check out your 
board!\n\n[[Special:UserBoard]]\n\n---\n\nHey, want to stop getting e-mails 
from us?\n\nClick [[Special:UpdateProfile]]\nand change your settings to 
disable email notifications.",
-       "message_received_body": "Hi $1.\n\n$2 just wrote on your board on 
{{SITENAME}}!\n\nClick below to check out your board!\n\n$3\n\n---\n\nHey, want 
to stop getting e-mails from us?\n\nClick $4\nand change your settings to 
disable email notifications."
+       "message_received_body": "Hi $1.\n\n$2 just wrote on your board on 
{{SITENAME}}!\n\nClick below to check out your board!\n\n$3\n\n---\n\nHey, want 
to stop getting e-mails from us?\n\nClick $4\nand change your settings to 
disable email notifications.",
+       "echo-category-title-social-msg": "User board messages",
+       "echo-pref-tooltip-social-msg": "Notify me when someone leaves a 
message on my user board.",
+       "notification-social-msg-send": "$1 just left a message for you.",
+       "notification-social-msg-send-bundle": "$1명의 사용자로부터 $2개의 메시지를 받았습니다."
 }
diff --git a/UserProfile/UserProfile.php b/UserProfile/UserProfile.php
index baf00d8..95c8230 100644
--- a/UserProfile/UserProfile.php
+++ b/UserProfile/UserProfile.php
@@ -77,6 +77,8 @@
 
 $wgResourceModules['ext.socialprofile.userprofile.js'] = array(
        'scripts' => 'UserProfilePage.js',
+       'messages' => array( 'user-board-confirm-delete' ),
+       'dependencies' => 'mediawiki.util',
        'localBasePath' => __DIR__,
        'remoteExtPath' => 'SocialProfile/UserProfile',
 );
diff --git a/UserProfile/UserProfilePage.js b/UserProfile/UserProfilePage.js
index 8c7d86f..7554d4a 100644
--- a/UserProfile/UserProfilePage.js
+++ b/UserProfile/UserProfilePage.js
@@ -1,7 +1,6 @@
 /**
  * JavaScript functions used by UserProfile
  */
-var replaceID;
 var UserProfilePage = {
        posted: 0,
        numReplaces: 0,
@@ -16,10 +15,12 @@
                if ( document.getElementById( 'message' ).value && 
!UserProfilePage.posted ) {
                        UserProfilePage.posted = 1;
                        jQuery.post(
-                               mediaWiki.util.wikiScript(), {
-                                       action: 'ajax',
-                                       rs: 'wfSendBoardMessage',
-                                       rsargs: [userTo, encMsg, msgType, 10]
+                               mediaWiki.util.wikiScript( 'api' ), {
+                                       action: 'socialprofile-send-message',
+                                       format: 'json',
+                                       username: userTo,
+                                       message: encMsg,
+                                       type: msgType
                                },
                                function( data ) {
                                        jQuery( '#user-page-board' ).html( data 
);
@@ -31,12 +32,12 @@
        },
 
        deleteMessage: function( id ) {
-               if ( window.confirm( 'Are you sure you want to delete this 
message?' ) ) {
+               if ( window.confirm( mediaWiki.msg( 'user-board-confirm-delete' 
) ) ) {
                        jQuery.post(
-                               mediaWiki.util.wikiScript(), {
-                                       action: 'ajax',
-                                       rs: 'wfDeleteBoardMessage',
-                                       rsargs: [id]
+                               mediaWiki.util.wikiScript( 'api' ), {
+                                       action: 'socialprofile-delete-message',
+                                       format: 'json',
+                                       'id': id
                                },
                                function() {
                                        //window.location.reload();
@@ -55,7 +56,7 @@
        },
 
        uploadError: function( message ) {
-               document.getElementById( 'mini-gallery-' + replaceID 
).innerHTML = UserProfilePage.oldHtml;
+               document.getElementById( 'mini-gallery-' + 
UserProfilePage.replaceID ).innerHTML = UserProfilePage.oldHtml;
                document.getElementById( 'upload-frame-errors' ).innerHTML = 
message;
                document.getElementById( 'imageUpload-frame' ).src = 
'index.php?title=Special:MiniAjaxUpload&wpThumbWidth=75';
 
diff --git a/UserProfile/i18n/en.json b/UserProfile/i18n/en.json
index 7e989da..8d20588 100644
--- a/UserProfile/i18n/en.json
+++ b/UserProfile/i18n/en.json
@@ -195,6 +195,7 @@
        "user-type-toggle-old": "Use wiki userpage",
        "user-type-toggle-new": "Use social userpage",
        "user-board-login-message": "You must be <a href=\"$1\">logged in</a> 
to post messages to other users",
+       "user-board-confirm-delete": "Are you sure you want to delete this 
message?",
        "removeavatar": "Remove avatar",
        "givegift": "Give a gift",
        "viewgifts": "View gifts",
diff --git a/UserRelationship/ApiRelationshipResponse.php 
b/UserRelationship/ApiRelationshipResponse.php
new file mode 100644
index 0000000..0c61887
--- /dev/null
+++ b/UserRelationship/ApiRelationshipResponse.php
@@ -0,0 +1,84 @@
+<?php
+
+class ApiRelationshipResponse extends ApiBase {
+       public function execute() {
+               $main = $this->getMain();
+
+               $response = $main->getVal( 'response' );
+               $requestId = $main->getVal( 'id' );
+
+               $user = $this->getUser();
+
+               // Don't allow blocked users to send messages and also don't 
allow message
+               // sending when the database is locked for some reason
+               if ( $user->isBlocked() || wfReadOnly() ) {
+                       return false;
+               }
+
+               $out = '';
+
+               $rel = new UserRelationship( $user->getName() );
+               if ( $rel->verifyRelationshipRequest( $requestId ) == true ) {
+                       $request = $rel->getRequest( $requestId );
+                       $user_name_from = $request[0]['user_name_from'];
+                       $user_id_from = User::idFromName( $user_name_from );
+                       $rel_type = strtolower( $request[0]['type'] );
+
+                       $rel->updateRelationshipRequestStatus( $requestId, 
intval( $response ) );
+
+                       $avatar = new wAvatar( $user_id_from, 'l' );
+                       $avatar_img = $avatar->getAvatarURL();
+
+                       if ( $response == 1 ) {
+                               $rel->addRelationship( $requestId );
+                               $out .= "<div class=\"relationship-action 
red-text\">
+                                       {$avatar_img}" .
+                                               wfMessage( 
"ur-requests-added-message-{$rel_type}", $user_name_from )->escaped() .
+                                       '<div class="visualClear"></div>
+                               </div>';
+                       } else {
+                               $out .= "<div class=\"relationship-action 
red-text\">
+                                       {$avatar_img}" .
+                                               wfMessage( 
"ur-requests-reject-message-{$rel_type}", $user_name_from )->escaped() .
+                                       '<div class="visualClear"></div>
+                               </div>';
+                       }
+                       $rel->deleteRequest( $requestId );
+               } else {
+                       return false;
+               }
+
+               $this->getResult()->addValue( null, 'html', $out );
+
+               return true;
+       }
+
+       public function getDescription() {
+               return 'Responds to user relationship (friend/foe) requests.';
+       }
+
+       public function getAllowedParams() {
+               return array_merge( parent::getAllowedParams(), array(
+                       'response' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_REQUIRED => true
+                       ),
+                       'id' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_REQUIRED => true
+                       )
+               ) );
+       }
+
+       public function getParamDescription() {
+               return array_merge( parent::getParamDescription(), array(
+                       'response' => 'Response to the relationship request; 1 
to accept, -1 to reject.',
+                       'id' => 'Unique identifier of the relationship request'
+               ) );
+       }
+
+       public function getExamplesMessages() {
+               return array();
+       }
+}
+
diff --git a/UserRelationship/Relationship_AjaxFunctions.php 
b/UserRelationship/Relationship_AjaxFunctions.php
deleted file mode 100644
index f919c25..0000000
--- a/UserRelationship/Relationship_AjaxFunctions.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * AJAX functions used by UserRelationship extension.
- */
-
-$wgAjaxExportList[] = 'wfRelationshipRequestResponse';
-function wfRelationshipRequestResponse( $response, $requestId ) {
-       global $wgUser;
-       $out = '';
-
-       $rel = new UserRelationship( $wgUser->getName() );
-       if ( $rel->verifyRelationshipRequest( $requestId ) == true ) {
-               $request = $rel->getRequest( $requestId );
-               $user_name_from = $request[0]['user_name_from'];
-               $user_id_from = User::idFromName( $user_name_from );
-               $rel_type = strtolower( $request[0]['type'] );
-
-               $response = ( isset( $_POST['response' ] ) ) ? 
$_POST['response'] : $response;
-               $rel->updateRelationshipRequestStatus( $requestId, intval( 
$response ) );
-
-               $avatar = new wAvatar( $user_id_from, 'l' );
-               $avatar_img = $avatar->getAvatarURL();
-
-               if ( $response == 1 ) {
-                       $rel->addRelationship( $requestId );
-                       $out .= "<div class=\"relationship-action red-text\">
-                               {$avatar_img}" .
-                                       wfMessage( 
"ur-requests-added-message-{$rel_type}", $user_name_from )->escaped() .
-                               '<div class="visualClear"></div>
-                       </div>';
-               } else {
-                       $out .= "<div class=\"relationship-action red-text\">
-                               {$avatar_img}" .
-                                       wfMessage( 
"ur-requests-reject-message-{$rel_type}", $user_name_from )->escaped() .
-                               '<div class="visualClear"></div>
-                       </div>';
-               }
-               $rel->deleteRequest( $requestId );
-       }
-
-       return $out;
-}
diff --git a/UserRelationship/UserRelationship.js 
b/UserRelationship/UserRelationship.js
index 5107d1a..a5f3ed4 100644
--- a/UserRelationship/UserRelationship.js
+++ b/UserRelationship/UserRelationship.js
@@ -7,10 +7,11 @@
        document.getElementById( 'request_action_' + id ).style.visibility = 
'hidden';
 
        jQuery.post(
-               mediaWiki.util.wikiScript(), {
-                       action: 'ajax',
-                       rs: 'wfRelationshipRequestResponse',
-                       rsargs: [response, id]
+               mediaWiki.util.wikiScript( 'api' ), {
+                       action: 'socialprofile-request-response',
+                       format: 'json',
+                       response: response,
+                       id: id
                },
                function( data ) {
                        document.getElementById( 'request_action_' + id 
).innerHTML = data;
diff --git a/UserRelationship/UserRelationshipClass.php 
b/UserRelationship/UserRelationshipClass.php
index 546a06d..0575224 100644
--- a/UserRelationship/UserRelationshipClass.php
+++ b/UserRelationship/UserRelationshipClass.php
@@ -51,6 +51,22 @@
                        $this->sendRelationshipRequestEmail( $userIdTo, 
$this->user_name, $type );
                }
 
+               if ( class_exists( 'EchoEvent' ) ) {
+                       $userFrom = User::newFromId( $this->user_id );
+
+                       EchoEvent::create( array(
+                               'type' => 'social-rel-add',
+                               'agent' => $userFrom,
+                               'title' => $userFrom->getUserPage(),
+                               'extra' => array(
+                                       'target' => $userIdTo,
+                                       'from' => $this->user_id,
+                                       'rel_type' => $type,
+                                       'message' => $message
+                               )
+                       ) );
+               }
+
                return $requestId;
        }
 
@@ -298,6 +314,21 @@
                        $wgMemc->delete( wfMemcKey( 'relationship', 'profile', 
"{$this->user_id}-{$ur_type}" ) );
                        $wgMemc->delete( wfMemcKey( 'relationship', 'profile', 
"{$ur_user_id_from}-{$ur_type}" ) );
 
+                       if ( class_exists( 'EchoEvent' ) ) {
+                               $userFrom = User::newFromId( $this->user_id );
+
+                               EchoEvent::create( array(
+                                       'type' => 'social-rel-accept',
+                                       'agent' => $userFrom,
+                                       'title' => $userFrom->getUserPage(),
+                                       'extra' => array(
+                                               'target' => $ur_user_id_from,
+                                               'from' => $this->user_id,
+                                               'rel_type' => $ur_type
+                                       )
+                               ) );
+                       }
+
                        // Hooks (for Semantic SocialProfile mostly)
                        if ( $ur_type == 1 ) {
                                Hooks::run( 'NewFriendAccepted', array( 
$ur_user_name_from, $this->user_name ) );
diff --git a/UserRelationship/UserRelationshipHooks.php 
b/UserRelationship/UserRelationshipHooks.php
new file mode 100644
index 0000000..dc677df
--- /dev/null
+++ b/UserRelationship/UserRelationshipHooks.php
@@ -0,0 +1,68 @@
+<?php
+
+class UserRelationshipHooks {
+       /**
+        * For the Echo extension.
+        *
+        * @param array $notifications Echo notifications
+        * @param array $notificationCategories Echo notification categories
+        * @param array $icons Icon details
+        * @return bool
+        */
+       public static function onBeforeCreateEchoEvent( &$notifications, 
&$notificationCategories, &$icons ) {
+               $notificationCategories['social-rel'] = array(
+                       'priority' => 2,
+                       'tooltip' => 'echo-pref-tooltip-social-rel',
+               );
+
+               $notifications['social-rel-add'] = array(
+                       'primary-link' => array( 'message' => 
'notification-link-text-view-edit', 'destination' => 'diff' ),
+                       'category' => 'social-rel',
+                       'group' => 'interactive',
+                       'formatter-class' => 'SocialProfileEchoFormatter',
+                       'title-message' => 'notification-social-rel-add',
+                       'title-params' => array( 'user', 'relationship' ),
+                       'payload' => array( 'relationship-add' ),
+                       'email-subject-message' => 
'notification-social-rel-add-email-subject',
+                       'email-subject-params' => array( 'user' ),
+                       'email-body-batch-message' => 
'notification-social-rel-add-email-batch-body',
+                       'email-body-batch-params' => array( 'user', 
'relationship' ),
+                       'icon' => 'gratitude',
+               );
+
+               $notifications['social-rel-accept'] = array(
+                       'primary-link' => array( 'message' => 
'notification-link-text-view-edit', 'destination' => 'diff' ),
+                       'category' => 'social-rel',
+                       'group' => 'interactive',
+                       'formatter-class' => 'SocialProfileEchoFormatter',
+                       'title-message' => 'notification-social-rel-accept',
+                       'title-params' => array( 'user' ),
+                       'email-subject-message' => 
'notification-social-rel-accept-email-subject',
+                       'email-subject-params' => array( 'user' ),
+                       'email-body-batch-message' => 
'notification-social-rel-accept-email-batch-body',
+                       'email-body-batch-params' => array( 'user' ),
+                       'icon' => 'gratitude',
+               );
+
+               return true;
+       }
+
+       /**
+        * Add user to be notified on Echo event
+        *
+        * @param EchoEvent $event
+        * @param array $users
+        * @return bool
+        */
+       public static function onEchoGetDefaultNotifiedUsers( $event, &$users ) 
{
+               switch ( $event->getType() ) {
+                       case 'social-rel-add':
+                       case 'social-rel-accept':
+                               $extra = $event->getExtra();
+                               $targetId = $extra['target'];
+                               $users[] = User::newFromId( $targetId );
+                               break;
+               }
+               return true;
+       }
+}
\ No newline at end of file
diff --git a/UserRelationship/i18n/en.json b/UserRelationship/i18n/en.json
index ae28825..9467b0d 100644
--- a/UserRelationship/i18n/en.json
+++ b/UserRelationship/i18n/en.json
@@ -90,5 +90,10 @@
        "friend_removed_body": "Hi $1.\n\n$2 has removed you as a friend on 
{{SITENAME}}!\n\nThanks,\n\n\nThe {{SITENAME}} team\n\n---\n\nHey, want to stop 
getting e-mails from us?\n\nClick $4\nand change your settings to disable 
e-mail notifications.",
        "foe_removed_subject": "Woohoo! $1 has removed you as a foe on 
{{SITENAME}}!",
        "foe_removed_body_html": "Hi $1.\n\n\t$2 has removed you as a foe on 
{{SITENAME}}!\n\nPerhaps you two are on your way to becoming 
friends?\n\nThanks,\n\n\nThe {{SITENAME}} team\n\n---\n\nHey, want to stop 
getting e-mails from us?\n\nClick [[Special:UpdateProfile]]\nand change your 
settings to disable e-mail notifications.",
-       "foe_removed_body": "Hi $1.\n\n\t$2 has removed you as a foe on 
{{SITENAME}}!\n\nPerhaps you two are on your way to becoming 
friends?\n\nThanks,\n\n\nThe {{SITENAME}} team\n\n---\n\nHey, want to stop 
getting e-mails from us?\n\nClick $4\nand change your settings to disable 
e-mail notifications."
+       "foe_removed_body": "Hi $1.\n\n\t$2 has removed you as a foe on 
{{SITENAME}}!\n\nPerhaps you two are on your way to becoming 
friends?\n\nThanks,\n\n\nThe {{SITENAME}} team\n\n---\n\nHey, want to stop 
getting e-mails from us?\n\nClick $4\nand change your settings to disable 
e-mail notifications.",
+       "echo-category-title-social-rel": "User relationship changes",
+       "echo-pref-tooltip-social-rel": "Notify me when someone sends me a user 
relationship request (friend or foe request).",
+       "echo-show-social-rel-add-link": "(Friend/Foe request)",
+       "notification-social-rel-add": "$1 wants to be your friend. $2",
+       "notification-social-rel-accept": "You became friends with $1."
 }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0c610c2bd33955c7f36619df9a3ce6b61b3c134f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/SocialProfile
Gerrit-Branch: master
Gerrit-Owner: Jack Phoenix <[email protected]>

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

Reply via email to