ApiQuerySiteinfo.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. <?php
  2. /*
  3. * Created on Sep 25, 2006
  4. *
  5. * API for MediaWiki 1.8+
  6. *
  7. * Copyright (C) 2006 Yuri Astrakhan <Firstname><Lastname>@gmail.com
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. * http://www.gnu.org/copyleft/gpl.html
  23. */
  24. if( !defined('MEDIAWIKI') ) {
  25. // Eclipse helper - will be ignored in production
  26. require_once( 'ApiQueryBase.php' );
  27. }
  28. /**
  29. * A query action to return meta information about the wiki site.
  30. *
  31. * @ingroup API
  32. */
  33. class ApiQuerySiteinfo extends ApiQueryBase {
  34. public function __construct( $query, $moduleName ) {
  35. parent :: __construct( $query, $moduleName, 'si' );
  36. }
  37. public function execute() {
  38. $params = $this->extractRequestParams();
  39. $done = array();
  40. foreach( $params['prop'] as $p )
  41. {
  42. switch ( $p )
  43. {
  44. case 'general':
  45. $fit = $this->appendGeneralInfo( $p );
  46. break;
  47. case 'namespaces':
  48. $fit = $this->appendNamespaces( $p );
  49. break;
  50. case 'namespacealiases':
  51. $fit = $this->appendNamespaceAliases( $p );
  52. break;
  53. case 'specialpagealiases':
  54. $fit = $this->appendSpecialPageAliases( $p );
  55. break;
  56. case 'magicwords':
  57. $fit = $this->appendMagicWords( $p );
  58. break;
  59. case 'interwikimap':
  60. $filteriw = isset( $params['filteriw'] ) ? $params['filteriw'] : false;
  61. $fit = $this->appendInterwikiMap( $p, $filteriw );
  62. break;
  63. case 'dbrepllag':
  64. $fit = $this->appendDbReplLagInfo( $p, $params['showalldb'] );
  65. break;
  66. case 'statistics':
  67. $fit = $this->appendStatistics( $p );
  68. break;
  69. case 'usergroups':
  70. $fit = $this->appendUserGroups( $p );
  71. break;
  72. case 'extensions':
  73. $fit = $this->appendExtensions( $p );
  74. break;
  75. case 'fileextensions':
  76. $fit = $this->appendFileExtensions( $p );
  77. break;
  78. case 'rightsinfo':
  79. $fit = $this->appendRightsInfo( $p );
  80. break;
  81. default :
  82. ApiBase :: dieDebug( __METHOD__, "Unknown prop=$p" );
  83. }
  84. if(!$fit)
  85. {
  86. # Abuse siprop as a query-continue parameter
  87. # and set it to all unprocessed props
  88. $this->setContinueEnumParameter('prop', implode('|',
  89. array_diff($params['prop'], $done)));
  90. break;
  91. }
  92. $done[] = $p;
  93. }
  94. }
  95. protected function appendGeneralInfo( $property ) {
  96. global $wgSitename, $wgVersion, $wgCapitalLinks, $wgRightsCode, $wgRightsText, $wgContLang;
  97. global $wgLanguageCode, $IP, $wgEnableWriteAPI, $wgLang, $wgLocaltimezone, $wgLocalTZoffset;
  98. $data = array();
  99. $mainPage = Title :: newFromText(wfMsgForContent('mainpage'));
  100. $data['mainpage'] = $mainPage->getPrefixedText();
  101. $data['base'] = $mainPage->getFullUrl();
  102. $data['sitename'] = $wgSitename;
  103. $data['generator'] = "MediaWiki $wgVersion";
  104. $svn = SpecialVersion::getSvnRevision( $IP );
  105. if( $svn )
  106. $data['rev'] = $svn;
  107. $data['case'] = $wgCapitalLinks ? 'first-letter' : 'case-sensitive'; // 'case-insensitive' option is reserved for future
  108. if( isset( $wgRightsCode ) )
  109. $data['rightscode'] = $wgRightsCode;
  110. $data['rights'] = $wgRightsText;
  111. $data['lang'] = $wgLanguageCode;
  112. if( $wgContLang->isRTL() )
  113. $data['rtl'] = '';
  114. $data['fallback8bitEncoding'] = $wgLang->fallback8bitEncoding();
  115. if( wfReadOnly() )
  116. $data['readonly'] = '';
  117. if( $wgEnableWriteAPI )
  118. $data['writeapi'] = '';
  119. $tz = $wgLocaltimezone;
  120. $offset = $wgLocalTZoffset;
  121. if( is_null( $tz ) ) {
  122. $tz = 'UTC';
  123. $offset = 0;
  124. } elseif( is_null( $offset ) ) {
  125. $offset = 0;
  126. }
  127. $data['timezone'] = $tz;
  128. $data['timeoffset'] = intval($offset);
  129. return $this->getResult()->addValue( 'query', $property, $data );
  130. }
  131. protected function appendNamespaces( $property ) {
  132. global $wgContLang;
  133. $data = array();
  134. foreach( $wgContLang->getFormattedNamespaces() as $ns => $title )
  135. {
  136. $data[$ns] = array(
  137. 'id' => intval($ns)
  138. );
  139. ApiResult :: setContent( $data[$ns], $title );
  140. $canonical = MWNamespace::getCanonicalName( $ns );
  141. if( MWNamespace::hasSubpages( $ns ) )
  142. $data[$ns]['subpages'] = '';
  143. if( $canonical )
  144. $data[$ns]['canonical'] = strtr($canonical, '_', ' ');
  145. }
  146. $this->getResult()->setIndexedTagName( $data, 'ns' );
  147. return $this->getResult()->addValue( 'query', $property, $data );
  148. }
  149. protected function appendNamespaceAliases( $property ) {
  150. global $wgNamespaceAliases, $wgContLang;
  151. $wgContLang->load();
  152. $aliases = array_merge( $wgNamespaceAliases, $wgContLang->namespaceAliases );
  153. $namespaces = $wgContLang->getNamespaces();
  154. $data = array();
  155. foreach( $aliases as $title => $ns ) {
  156. if( $namespaces[$ns] == $title ) {
  157. // Don't list duplicates
  158. continue;
  159. }
  160. $item = array(
  161. 'id' => intval($ns)
  162. );
  163. ApiResult :: setContent( $item, strtr( $title, '_', ' ' ) );
  164. $data[] = $item;
  165. }
  166. $this->getResult()->setIndexedTagName( $data, 'ns' );
  167. return $this->getResult()->addValue( 'query', $property, $data );
  168. }
  169. protected function appendSpecialPageAliases( $property ) {
  170. global $wgLang;
  171. $data = array();
  172. foreach( $wgLang->getSpecialPageAliases() as $specialpage => $aliases )
  173. {
  174. $arr = array( 'realname' => $specialpage, 'aliases' => $aliases );
  175. $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
  176. $data[] = $arr;
  177. }
  178. $this->getResult()->setIndexedTagName( $data, 'specialpage' );
  179. return $this->getResult()->addValue( 'query', $property, $data );
  180. }
  181. protected function appendMagicWords( $property ) {
  182. global $wgContLang;
  183. $data = array();
  184. foreach($wgContLang->getMagicWords() as $magicword => $aliases)
  185. {
  186. $caseSensitive = array_shift($aliases);
  187. $arr = array('name' => $magicword, 'aliases' => $aliases);
  188. if($caseSensitive)
  189. $arr['case-sensitive'] = '';
  190. $this->getResult()->setIndexedTagName($arr['aliases'], 'alias');
  191. $data[] = $arr;
  192. }
  193. $this->getResult()->setIndexedTagName($data, 'magicword');
  194. return $this->getResult()->addValue( 'query', $property, $data );
  195. }
  196. protected function appendInterwikiMap( $property, $filter ) {
  197. $this->resetQueryParams();
  198. $this->addTables( 'interwiki' );
  199. $this->addFields( array( 'iw_prefix', 'iw_local', 'iw_url' ) );
  200. if( $filter === 'local' )
  201. $this->addWhere( 'iw_local = 1' );
  202. elseif( $filter === '!local' )
  203. $this->addWhere( 'iw_local = 0' );
  204. elseif( $filter )
  205. ApiBase :: dieDebug( __METHOD__, "Unknown filter=$filter" );
  206. $this->addOption( 'ORDER BY', 'iw_prefix' );
  207. $db = $this->getDB();
  208. $res = $this->select( __METHOD__ );
  209. $data = array();
  210. $langNames = Language::getLanguageNames();
  211. while( $row = $db->fetchObject($res) )
  212. {
  213. $val = array();
  214. $val['prefix'] = $row->iw_prefix;
  215. if( $row->iw_local == '1' )
  216. $val['local'] = '';
  217. // $val['trans'] = intval($row->iw_trans); // should this be exposed?
  218. if( isset( $langNames[$row->iw_prefix] ) )
  219. $val['language'] = $langNames[$row->iw_prefix];
  220. $val['url'] = $row->iw_url;
  221. $data[] = $val;
  222. }
  223. $db->freeResult( $res );
  224. $this->getResult()->setIndexedTagName( $data, 'iw' );
  225. return $this->getResult()->addValue( 'query', $property, $data );
  226. }
  227. protected function appendDbReplLagInfo( $property, $includeAll ) {
  228. global $wgShowHostnames;
  229. $data = array();
  230. if( $includeAll ) {
  231. if ( !$wgShowHostnames )
  232. $this->dieUsage('Cannot view all servers info unless $wgShowHostnames is true', 'includeAllDenied');
  233. $lb = wfGetLB();
  234. $lags = $lb->getLagTimes();
  235. foreach( $lags as $i => $lag ) {
  236. $data[] = array(
  237. 'host' => $lb->getServerName( $i ),
  238. 'lag' => $lag
  239. );
  240. }
  241. } else {
  242. list( $host, $lag ) = wfGetLB()->getMaxLag();
  243. $data[] = array(
  244. 'host' => $wgShowHostnames ? $host : '',
  245. 'lag' => intval( $lag )
  246. );
  247. }
  248. $result = $this->getResult();
  249. $result->setIndexedTagName( $data, 'db' );
  250. return $this->getResult()->addValue( 'query', $property, $data );
  251. }
  252. protected function appendStatistics( $property ) {
  253. global $wgDisableCounters;
  254. $data = array();
  255. $data['pages'] = intval( SiteStats::pages() );
  256. $data['articles'] = intval( SiteStats::articles() );
  257. if ( !$wgDisableCounters ) {
  258. $data['views'] = intval( SiteStats::views() );
  259. }
  260. $data['edits'] = intval( SiteStats::edits() );
  261. $data['images'] = intval( SiteStats::images() );
  262. $data['users'] = intval( SiteStats::users() );
  263. $data['activeusers'] = intval( SiteStats::activeUsers() );
  264. $data['admins'] = intval( SiteStats::numberingroup('sysop') );
  265. $data['jobs'] = intval( SiteStats::jobs() );
  266. return $this->getResult()->addValue( 'query', $property, $data );
  267. }
  268. protected function appendUserGroups( $property ) {
  269. global $wgGroupPermissions;
  270. $data = array();
  271. foreach( $wgGroupPermissions as $group => $permissions ) {
  272. $arr = array( 'name' => $group, 'rights' => array_keys( $permissions, true ) );
  273. $this->getResult()->setIndexedTagName( $arr['rights'], 'permission' );
  274. $data[] = $arr;
  275. }
  276. $this->getResult()->setIndexedTagName( $data, 'group' );
  277. return $this->getResult()->addValue( 'query', $property, $data );
  278. }
  279. protected function appendFileExtensions( $property ) {
  280. global $wgFileExtensions;
  281. $data = array();
  282. foreach( $wgFileExtensions as $ext ) {
  283. $data[] = array( 'ext' => $ext );
  284. }
  285. $this->getResult()->setIndexedTagName( $data, 'fe' );
  286. return $this->getResult()->addValue( 'query', $property, $data );
  287. }
  288. protected function appendExtensions( $property ) {
  289. global $wgExtensionCredits;
  290. $data = array();
  291. foreach ( $wgExtensionCredits as $type => $extensions ) {
  292. foreach ( $extensions as $ext ) {
  293. $ret = array();
  294. $ret['type'] = $type;
  295. if ( isset( $ext['name'] ) )
  296. $ret['name'] = $ext['name'];
  297. if ( isset( $ext['description'] ) )
  298. $ret['description'] = $ext['description'];
  299. if ( isset( $ext['descriptionmsg'] ) )
  300. $ret['descriptionmsg'] = $ext['descriptionmsg'];
  301. if ( isset( $ext['author'] ) ) {
  302. $ret['author'] = is_array( $ext['author'] ) ?
  303. implode( ', ', $ext['author' ] ) : $ext['author'];
  304. }
  305. if ( isset( $ext['version'] ) ) {
  306. $ret['version'] = $ext['version'];
  307. } elseif ( isset( $ext['svn-revision'] ) &&
  308. preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
  309. $ext['svn-revision'], $m ) )
  310. {
  311. $ret['version'] = 'r' . $m[1];
  312. }
  313. $data[] = $ret;
  314. }
  315. }
  316. $this->getResult()->setIndexedTagName( $data, 'ext' );
  317. return $this->getResult()->addValue( 'query', $property, $data );
  318. }
  319. protected function appendRightsInfo( $property ) {
  320. global $wgRightsPage, $wgRightsUrl, $wgRightsText;
  321. $title = Title::newFromText( $wgRightsPage );
  322. $url = $title ? $title->getFullURL() : $wgRightsUrl;
  323. $text = $wgRightsText;
  324. if( !$text && $title ) {
  325. $text = $title->getPrefixedText();
  326. }
  327. $data = array(
  328. 'url' => $url ? $url : '',
  329. 'text' => $text ? $text : ''
  330. );
  331. return $this->getResult()->addValue( 'query', $property, $data );
  332. }
  333. public function getAllowedParams() {
  334. return array(
  335. 'prop' => array(
  336. ApiBase :: PARAM_DFLT => 'general',
  337. ApiBase :: PARAM_ISMULTI => true,
  338. ApiBase :: PARAM_TYPE => array(
  339. 'general',
  340. 'namespaces',
  341. 'namespacealiases',
  342. 'specialpagealiases',
  343. 'magicwords',
  344. 'interwikimap',
  345. 'dbrepllag',
  346. 'statistics',
  347. 'usergroups',
  348. 'extensions',
  349. 'fileextensions',
  350. 'rightsinfo',
  351. )
  352. ),
  353. 'filteriw' => array(
  354. ApiBase :: PARAM_TYPE => array(
  355. 'local',
  356. '!local',
  357. )
  358. ),
  359. 'showalldb' => false,
  360. );
  361. }
  362. public function getParamDescription() {
  363. return array(
  364. 'prop' => array(
  365. 'Which sysinfo properties to get:',
  366. ' general - Overall system information',
  367. ' namespaces - List of registered namespaces and their canonical names',
  368. ' namespacealiases - List of registered namespace aliases',
  369. ' specialpagealiases - List of special page aliases',
  370. ' magicwords - List of magic words and their aliases',
  371. ' statistics - Returns site statistics',
  372. ' interwikimap - Returns interwiki map (optionally filtered)',
  373. ' dbrepllag - Returns database server with the highest replication lag',
  374. ' usergroups - Returns user groups and the associated permissions',
  375. ' extensions - Returns extensions installed on the wiki',
  376. ' fileextensions - Returns list of file extensions allowed to be uploaded',
  377. ' rightsinfo - Returns wiki rights (license) information if available',
  378. ),
  379. 'filteriw' => 'Return only local or only nonlocal entries of the interwiki map',
  380. 'showalldb' => 'List all database servers, not just the one lagging the most',
  381. );
  382. }
  383. public function getDescription() {
  384. return 'Return general information about the site.';
  385. }
  386. protected function getExamples() {
  387. return array(
  388. 'api.php?action=query&meta=siteinfo&siprop=general|namespaces|namespacealiases|statistics',
  389. 'api.php?action=query&meta=siteinfo&siprop=interwikimap&sifilteriw=local',
  390. 'api.php?action=query&meta=siteinfo&siprop=dbrepllag&sishowalldb',
  391. );
  392. }
  393. public function getVersion() {
  394. return __CLASS__ . ': $Id: ApiQuerySiteinfo.php 48060 2009-03-05 13:52:14Z demon $';
  395. }
  396. }