ApiQueryAllMessages.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. /**
  3. * Copyright © 2006 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. */
  22. use MediaWiki\MediaWikiServices;
  23. /**
  24. * A query action to return messages from site message cache
  25. *
  26. * @ingroup API
  27. */
  28. class ApiQueryAllMessages extends ApiQueryBase {
  29. public function __construct( ApiQuery $query, $moduleName ) {
  30. parent::__construct( $query, $moduleName, 'am' );
  31. }
  32. public function execute() {
  33. $params = $this->extractRequestParams();
  34. if ( is_null( $params['lang'] ) ) {
  35. $langObj = $this->getLanguage();
  36. } elseif ( !Language::isValidCode( $params['lang'] ) ) {
  37. $this->dieWithError(
  38. [ 'apierror-invalidlang', $this->encodeParamName( 'lang' ) ], 'invalidlang'
  39. );
  40. } else {
  41. $langObj = Language::factory( $params['lang'] );
  42. }
  43. if ( $params['enableparser'] ) {
  44. if ( !is_null( $params['title'] ) ) {
  45. $title = Title::newFromText( $params['title'] );
  46. if ( !$title || $title->isExternal() ) {
  47. $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
  48. }
  49. } else {
  50. $title = Title::newFromText( 'API' );
  51. }
  52. }
  53. $prop = array_flip( (array)$params['prop'] );
  54. // Determine which messages should we print
  55. if ( in_array( '*', $params['messages'] ) ) {
  56. $message_names = Language::getMessageKeysFor( $langObj->getCode() );
  57. if ( $params['includelocal'] ) {
  58. $message_names = array_unique( array_merge(
  59. $message_names,
  60. // Pass in the content language code so we get local messages that have a
  61. // MediaWiki:msgkey page. We might theoretically miss messages that have no
  62. // MediaWiki:msgkey page but do have a MediaWiki:msgkey/lang page, but that's
  63. // just a stupid case.
  64. MessageCache::singleton()->getAllMessageKeys( $this->getConfig()->get( 'LanguageCode' ) )
  65. ) );
  66. }
  67. sort( $message_names );
  68. $messages_target = $message_names;
  69. } else {
  70. $messages_target = $params['messages'];
  71. }
  72. // Filter messages that have the specified prefix
  73. // Because we sorted the message array earlier, they will appear in a clump:
  74. if ( isset( $params['prefix'] ) ) {
  75. $skip = false;
  76. $messages_filtered = [];
  77. foreach ( $messages_target as $message ) {
  78. // === 0: must be at beginning of string (position 0)
  79. if ( strpos( $message, $params['prefix'] ) === 0 ) {
  80. if ( !$skip ) {
  81. $skip = true;
  82. }
  83. $messages_filtered[] = $message;
  84. } elseif ( $skip ) {
  85. break;
  86. }
  87. }
  88. $messages_target = $messages_filtered;
  89. }
  90. // Filter messages that contain specified string
  91. if ( isset( $params['filter'] ) ) {
  92. $messages_filtered = [];
  93. foreach ( $messages_target as $message ) {
  94. // !== is used because filter can be at the beginning of the string
  95. if ( strpos( $message, $params['filter'] ) !== false ) {
  96. $messages_filtered[] = $message;
  97. }
  98. }
  99. $messages_target = $messages_filtered;
  100. }
  101. // Whether we have any sort of message customisation filtering
  102. $customiseFilterEnabled = $params['customised'] !== 'all';
  103. if ( $customiseFilterEnabled ) {
  104. $customisedMessages = AllMessagesTablePager::getCustomisedStatuses(
  105. array_map(
  106. [ $langObj, 'ucfirst' ],
  107. $messages_target
  108. ),
  109. $langObj->getCode(),
  110. !$langObj->equals( MediaWikiServices::getInstance()->getContentLanguage() )
  111. );
  112. $customised = $params['customised'] === 'modified';
  113. }
  114. // Get all requested messages and print the result
  115. $skip = !is_null( $params['from'] );
  116. $useto = !is_null( $params['to'] );
  117. $result = $this->getResult();
  118. foreach ( $messages_target as $message ) {
  119. // Skip all messages up to $params['from']
  120. if ( $skip && $message === $params['from'] ) {
  121. $skip = false;
  122. }
  123. if ( $useto && $message > $params['to'] ) {
  124. break;
  125. }
  126. if ( !$skip ) {
  127. $a = [
  128. 'name' => $message,
  129. 'normalizedname' => MessageCache::normalizeKey( $message ),
  130. ];
  131. $args = [];
  132. if ( isset( $params['args'] ) && count( $params['args'] ) != 0 ) {
  133. $args = $params['args'];
  134. }
  135. if ( $customiseFilterEnabled ) {
  136. $messageIsCustomised = isset( $customisedMessages['pages'][$langObj->ucfirst( $message )] );
  137. if ( $customised === $messageIsCustomised ) {
  138. if ( $customised ) {
  139. $a['customised'] = true;
  140. }
  141. } else {
  142. continue;
  143. }
  144. }
  145. $msg = wfMessage( $message, $args )->inLanguage( $langObj );
  146. if ( !$msg->exists() ) {
  147. $a['missing'] = true;
  148. } else {
  149. // Check if the parser is enabled:
  150. if ( $params['enableparser'] ) {
  151. $msgString = $msg->title( $title )->text();
  152. } else {
  153. $msgString = $msg->plain();
  154. }
  155. if ( !$params['nocontent'] ) {
  156. ApiResult::setContentValue( $a, 'content', $msgString );
  157. }
  158. if ( isset( $prop['default'] ) ) {
  159. $default = wfMessage( $message )->inLanguage( $langObj )->useDatabase( false );
  160. if ( !$default->exists() ) {
  161. $a['defaultmissing'] = true;
  162. } elseif ( $default->plain() != $msgString ) {
  163. $a['default'] = $default->plain();
  164. }
  165. }
  166. }
  167. $fit = $result->addValue( [ 'query', $this->getModuleName() ], null, $a );
  168. if ( !$fit ) {
  169. $this->setContinueEnumParameter( 'from', $message );
  170. break;
  171. }
  172. }
  173. }
  174. $result->addIndexedTagName( [ 'query', $this->getModuleName() ], 'message' );
  175. }
  176. public function getCacheMode( $params ) {
  177. if ( is_null( $params['lang'] ) ) {
  178. // Language not specified, will be fetched from preferences
  179. return 'anon-public-user-private';
  180. } elseif ( $params['enableparser'] ) {
  181. // User-specific parser options will be used
  182. return 'anon-public-user-private';
  183. } else {
  184. // OK to cache
  185. return 'public';
  186. }
  187. }
  188. public function getAllowedParams() {
  189. return [
  190. 'messages' => [
  191. ApiBase::PARAM_DFLT => '*',
  192. ApiBase::PARAM_ISMULTI => true,
  193. ],
  194. 'prop' => [
  195. ApiBase::PARAM_ISMULTI => true,
  196. ApiBase::PARAM_TYPE => [
  197. 'default'
  198. ]
  199. ],
  200. 'enableparser' => false,
  201. 'nocontent' => false,
  202. 'includelocal' => false,
  203. 'args' => [
  204. ApiBase::PARAM_ISMULTI => true,
  205. ApiBase::PARAM_ALLOW_DUPLICATES => true,
  206. ],
  207. 'filter' => [],
  208. 'customised' => [
  209. ApiBase::PARAM_DFLT => 'all',
  210. ApiBase::PARAM_TYPE => [
  211. 'all',
  212. 'modified',
  213. 'unmodified'
  214. ]
  215. ],
  216. 'lang' => null,
  217. 'from' => null,
  218. 'to' => null,
  219. 'title' => null,
  220. 'prefix' => null,
  221. ];
  222. }
  223. protected function getExamplesMessages() {
  224. return [
  225. 'action=query&meta=allmessages&amprefix=ipb-'
  226. => 'apihelp-query+allmessages-example-ipb',
  227. 'action=query&meta=allmessages&ammessages=august|mainpage&amlang=de'
  228. => 'apihelp-query+allmessages-example-de',
  229. ];
  230. }
  231. public function getHelpUrls() {
  232. return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Allmessages';
  233. }
  234. }