From b23d9bc9c549e0f39a1a77330e00fc089a336eb1 Mon Sep 17 00:00:00 2001 From: Shashank Atreya Date: Wed, 29 Nov 2023 20:24:11 +0530 Subject: [PATCH] Added an API to update message --- extension.json | 19 +++- i18n/en.json | 10 ++- src/Api/UpdateMessageApiModule.php | 90 +++++++++++++++++++ src/Cache.php | 27 +++--- src/Hooks/MainHookHandler.php | 36 ++++++++ .../SpecialLiquipediaMediaWikiMessages.php | 35 ++++++-- 6 files changed, 192 insertions(+), 25 deletions(-) create mode 100644 src/Api/UpdateMessageApiModule.php diff --git a/extension.json b/extension.json index dd8cedb..b124069 100644 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "LiquipediaMediaWikiMessages", - "version": "2.3.1", + "version": "2.3.2", "author": [ "[https://fo-nttax.de Alex Winkler]" ], @@ -19,6 +19,9 @@ "LogActionsHandlers": { "liquipediamediawikimessages/*": "\\Liquipedia\\Extension\\LiquipediaMediaWikiMessages\\LogFormatter" }, + "APIModules": { + "updatelpmwmessageapi": "\\Liquipedia\\Extension\\LiquipediaMediaWikiMessages\\Api\\UpdateMessageApiModule" + }, "LogTypes": [ "liquipediamediawikimessages" ], @@ -30,14 +33,24 @@ }, "HookHandlers": { "Main": { - "class": "\\Liquipedia\\Extension\\LiquipediaMediaWikiMessages\\Hooks\\MainHookHandler" + "class": "\\Liquipedia\\Extension\\LiquipediaMediaWikiMessages\\Hooks\\MainHookHandler", + "services": [ + "PermissionManager" + ] } }, "Hooks": { + "ApiCheckCanExecute": "Main", "MessagesPreLoad": "Main" }, "SpecialPages": { - "LiquipediaMediaWikiMessages": "\\Liquipedia\\Extension\\LiquipediaMediaWikiMessages\\SpecialPage\\SpecialLiquipediaMediaWikiMessages" + "LiquipediaMediaWikiMessages": { + "class": "\\Liquipedia\\Extension\\LiquipediaMediaWikiMessages\\SpecialPage\\SpecialLiquipediaMediaWikiMessages", + "services": [ + "MainConfig", + "DBLoadBalancer" + ] + } }, "ResourceFileModulePaths": { "localBasePath": "", diff --git a/i18n/en.json b/i18n/en.json index fbd7300..af9ac7a 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -38,6 +38,14 @@ "liquipediamediawikimessages-column-edit": "Edit", "liquipediamediawikimessages-column-delete": "Delete", + "apihelp-updatelpmwmessageapi-summary": "API Helper to update LiquipediaMediaWikiMessages message values", + "liquipediamediawikimessages-api-message-name": "Message name to update the value for", + "liquipediamediawikimessages-api-message-value": "Value for the particular message defined before", + "liquipediamediawikimessages-api-example": "Example:", + "liquipediamediawikimessages-api-result-error": "No message with this message name found", + "liquipediamediawikimessages-api-result-success": "Successfully changed the message value", + "updatelpmwmessageapi-action-notallowed": "You are not allowed to update LiquipediaMediaWikiMessages", + "log-name-liquipediamediawikimessages": "LiquipediaMediaWikiMessages log", "log-description-liquipediamediawikimessages": "These events track when someone globally overwrite message keys for all Liquipedia wikis", "logentry-liquipediamediawikimessages-added": "$1 added message \"$4\" via $3", @@ -46,4 +54,4 @@ "specialpages-group-liquipedia": "Liquipedia", "action-editinterface": "edit interface messages" -} \ No newline at end of file +} diff --git a/src/Api/UpdateMessageApiModule.php b/src/Api/UpdateMessageApiModule.php new file mode 100644 index 0000000..a1b6468 --- /dev/null +++ b/src/Api/UpdateMessageApiModule.php @@ -0,0 +1,90 @@ +getRequest()->getText( 'messagename' ); + $value = $this->getRequest()->getText( 'value' ); + $services = MediaWikiServices::getInstance(); + $loadBalancer = $services->getDBLoadBalancer(); + + $dbw = $loadBalancer->getConnection( DB_PRIMARY, '', $this->getConfig()->get( 'DBname' ) ); + $tablename = 'liquipedia_mediawiki_messages'; + + // Search if the message is present + $row = $dbw->selectRow( $tablename, [ '1' ], [ 'messagename' => $messageName ] ); + // If the message is not present, just return an error + if ( !$row ) { + $this->getResult()->addValue( null, $this->getModuleName(), [ + 'message' => $this->msg( 'liquipediamediawikimessages-api-result-error' ) + ] ); + return; + } + // Else update the message to the given value + $dbw->update( $tablename, [ 'messagevalue' => $value ], [ 'messagename' => $messageName ] ); + + // Delete from cache + $cache = $services->getMainWANObjectCache(); + $cache->delete( + $cache->makeGlobalKey( + Cache::getPrefix(), md5( $messageName ) + ), + ); + + $this->getResult()->addValue( null, $this->getModuleName(), [ + 'message' => $this->msg( 'liquipediamediawikimessages-api-result-success' ) + ] ); + } + + /** + * @return mixed + */ + public function getDescription() { + return $this->msg( 'liquipediamediawikimessages-api-shortdesc' )->text(); + } + + /** + * @return mixed + */ + public function getParamDescription() { + return parent::getParamDescription(); + } + + /** + * @return array + */ + public function getExamplesMessages() { + return [ + 'action=updatelpmwmessageapi&messagename=some_message_name&value=some_value&format=json' + => 'liquipediamediawikimessages-api-example', + ]; + } + + /** + * @return array + */ + public function getAllowedParams() { + return [ + 'messagename' => [ + ParamValidator::PARAM_TYPE => 'string', + ApiBase::PARAM_HELP_MSG => 'liquipediamediawikimessages-api-message-name', + ParamValidator::PARAM_REQUIRED => true, + ], + 'value' => [ + ParamValidator::PARAM_TYPE => 'string', + ApiBase::PARAM_HELP_MSG => 'liquipediamediawikimessages-api-message-value', + ParamValidator::PARAM_REQUIRED => true, + ] + ]; + } +} diff --git a/src/Cache.php b/src/Cache.php index 46d5b24..b0b33e6 100644 --- a/src/Cache.php +++ b/src/Cache.php @@ -29,24 +29,25 @@ public static function getByName( $name ) { $mediaWikiServices = MediaWikiServices::getInstance(); $config = $mediaWikiServices->getMainConfig(); $cache = $mediaWikiServices->getMainWANObjectCache(); + $loadBalancer = $mediaWikiServices->getDBLoadBalancer(); $result = $cache->getWithSetCallback( $cache->makeGlobalKey( self::getPrefix(), md5( $name ) ), $cache::TTL_DAY, - static function () use ( $config, $name ) { - $dbr = wfGetDB( DB_REPLICA, '', $config->get( 'DBname' ) ); - $res = $dbr->select( - 'liquipedia_mediawiki_messages', - [ 'messagevalue' ], - [ 'messagename' => $name ] - ); - if ( $res->numRows() === 1 ) { - $obj = $res->fetchObject(); - return [ 'value' => $obj->messagevalue ]; - } - $res->free(); - return [ 'value' => false ]; + static function () use ( $config, $name, $loadBalancer ) { + $dbr = $loadBalancer->getConnection( DB_REPLICA, '', $config->get( 'DBname' ) ); + $res = $dbr->select( + 'liquipedia_mediawiki_messages', + [ 'messagevalue' ], + [ 'messagename' => $name ] + ); + if ( $res->numRows() === 1 ) { + $obj = $res->fetchObject(); + return [ 'value' => $obj->messagevalue ]; + } + $res->free(); + return [ 'value' => false ]; } ); self::$valueCache[ $name ] = $result; diff --git a/src/Hooks/MainHookHandler.php b/src/Hooks/MainHookHandler.php index 15034b7..5bb19fc 100644 --- a/src/Hooks/MainHookHandler.php +++ b/src/Hooks/MainHookHandler.php @@ -4,12 +4,48 @@ use Language; use Liquipedia\Extension\LiquipediaMediaWikiMessages\Cache; +use MediaWiki\Api\Hook\ApiCheckCanExecuteHook; use MediaWiki\Cache\Hook\MessagesPreLoadHook; +use MediaWiki\Permissions\PermissionManager; class MainHookHandler implements + ApiCheckCanExecuteHook, MessagesPreLoadHook { + /** + * @var PermissionManager + */ + private PermissionManager $permissionManager; + + /** + * @param PermissionManager $permissionManager + */ + public function __construct( + PermissionManager $permissionManager + ) { + $this->permissionManager = $permissionManager; + } + + /** + * @param Module $module + * @param User $user + * @param Message &$message + * + * @return bool + */ + public function onApiCheckCanExecute( $module, $user, &$message ) { + $moduleName = $module->getModuleName(); + $userRights = $this->permissionManager->getUserPermissions( $user ); + if ( + $moduleName === 'updatelpmwmessageapi' && !in_array( 'editinterface', $userRights ) + ) { + $message = 'updatelpmwmessageapi-action-notallowed'; + return false; + } + return true; + } + /** * @param Title $title * @param string &$message diff --git a/src/SpecialPage/SpecialLiquipediaMediaWikiMessages.php b/src/SpecialPage/SpecialLiquipediaMediaWikiMessages.php index f987e86..0ac78c2 100644 --- a/src/SpecialPage/SpecialLiquipediaMediaWikiMessages.php +++ b/src/SpecialPage/SpecialLiquipediaMediaWikiMessages.php @@ -2,11 +2,13 @@ namespace Liquipedia\Extension\LiquipediaMediaWikiMessages\SpecialPage; +use Config; use HTMLForm; use Liquipedia\Extension\LiquipediaMediaWikiMessages\Cache; use ManualLogEntry; use MediaWiki\MediaWikiServices; use SpecialPage; +use Wikimedia\Rdbms\ILoadBalancer; class SpecialLiquipediaMediaWikiMessages extends SpecialPage { @@ -15,8 +17,26 @@ class SpecialLiquipediaMediaWikiMessages extends SpecialPage { */ private $output; - public function __construct() { + /** + * + * @var Config + */ + private $config; + + /** + * @var ILoadBalancer + */ + private $loadBalancer; + + /** + * + * @param Config $config + * @param ILoadBalancer $loadBalancer + */ + public function __construct( Config $config, ILoadBalancer $loadBalancer ) { parent::__construct( 'LiquipediaMediaWikiMessages', 'editinterface' ); + $this->config = $config; + $this->loadBalancer = $loadBalancer; } /** @@ -32,13 +52,12 @@ public function getGroupName() { public function execute( $par ) { if ( !$this->userCanExecute( $this->getUser() ) ) { $this->displayRestrictionError(); - return; } $tablename = 'liquipedia_mediawiki_messages'; $params = explode( '/', $par ?? '' ); $this->output = $this->getOutput(); $this->setHeaders(); - $dbw = wfGetDB( DB_PRIMARY, '', $this->getConfig()->get( 'DBname' ) ); + $dbw = $this->loadBalancer->getConnection( DB_PRIMARY, '', $this->config->get( 'DBname' ) ); if ( $params[ 0 ] === 'new' ) { $this->addMessage(); } elseif ( ( $params[ 0 ] === 'edit' ) && isset( $params[ 1 ] ) && !empty( $params[ 1 ] ) ) { @@ -113,7 +132,7 @@ private function addMessage() { */ public function addMessageCB( $formData ) { if ( !empty( $formData[ 'MessageName' ] ) && !empty( $formData[ 'MessageValue' ] ) ) { - $dbw = wfGetDB( DB_PRIMARY, '', $this->getConfig()->get( 'DBname' ) ); + $dbw = $this->loadBalancer->getConnection( DB_PRIMARY, '', $this->config->get( 'DBname' ) ); $reqMessage = $formData[ 'MessageName' ]; $reqValue = $formData[ 'MessageValue' ]; $tablename = 'liquipedia_mediawiki_messages'; @@ -163,7 +182,7 @@ private function editMessage( $id ) { $this->output->addWikiTextAsContent( '

' . $this->msg( 'liquipediamediawikimessages-edit-message' )->text() . '

' ); - $dbw = wfGetDB( DB_PRIMARY, '', $this->getConfig()->get( 'DBname' ) ); + $dbw = $this->loadBalancer->getConnection( DB_PRIMARY, '', $this->config->get( 'DBname' ) ); $tablename = 'liquipedia_mediawiki_messages'; $res = $dbw->selectRow( $tablename, '*', [ 'id' => $id ] ); if ( $res ) { @@ -237,7 +256,7 @@ private function deleteMessage( $id ) { '

' . $this->msg( 'liquipediamediawikimessages-delete-message' )->text() . '

' ); $tablename = 'liquipedia_mediawiki_messages'; - $dbw = wfGetDB( DB_PRIMARY, '', $this->getConfig()->get( 'DBname' ) ); + $dbw = $this->loadBalancer->getConnection( DB_PRIMARY, '', $this->config->get( 'DBname' ) ); $res = $dbw->selectRow( $tablename, '*', [ 'id' => $id ] ); if ( $res ) { $result = get_object_vars( $res ); @@ -313,7 +332,7 @@ public function deleteMessageCB( $formData ) { * @param string $value */ private function update( $id, $value ) { - $dbw = wfGetDB( DB_PRIMARY, '', $this->getConfig()->get( 'DBname' ) ); + $dbw = $this->loadBalancer->getConnection( DB_PRIMARY, '', $this->config->get( 'DBname' ) ); $tablename = 'liquipedia_mediawiki_messages'; $name = $dbw->select( $tablename, 'messagename', [ 'id' => $id ] )->fetchObject()->messagename; @@ -325,7 +344,7 @@ private function update( $id, $value ) { * @param int $id */ private function delete( $id ) { - $dbw = wfGetDB( DB_PRIMARY, '', $this->getConfig()->get( 'DBname' ) ); + $dbw = $this->loadBalancer->getConnection( DB_PRIMARY, '', $this->config->get( 'DBname' ) ); $tablename = 'liquipedia_mediawiki_messages'; $name = $dbw->select( $tablename, [ 'id' => $id ] )->fetchObject()->messagename;