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
