[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Query the list of contributors to a page 4 * 5 * Created on Nov 14, 2013 6 * 7 * Copyright © 2013 Brad Jorsch 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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 * http://www.gnu.org/copyleft/gpl.html 23 * 24 * @file 25 * @since 1.23 26 */ 27 28 /** 29 * A query module to show contributors to a page 30 * 31 * @ingroup API 32 * @since 1.23 33 */ 34 class ApiQueryContributors extends ApiQueryBase { 35 /** We don't want to process too many pages at once (it hits cold 36 * database pages too heavily), so only do the first MAX_PAGES input pages 37 * in each API call (leaving the rest for continuation). 38 */ 39 const MAX_PAGES = 100; 40 41 public function __construct( ApiQuery $query, $moduleName ) { 42 // "pc" is short for "page contributors", "co" was already taken by the 43 // GeoData extension's prop=coordinates. 44 parent::__construct( $query, $moduleName, 'pc' ); 45 } 46 47 public function execute() { 48 $db = $this->getDB(); 49 $params = $this->extractRequestParams(); 50 $this->requireMaxOneParameter( $params, 'group', 'excludegroup', 'rights', 'excluderights' ); 51 52 // Only operate on existing pages 53 $pages = array_keys( $this->getPageSet()->getGoodTitles() ); 54 55 // Filter out already-processed pages 56 if ( $params['continue'] !== null ) { 57 $cont = explode( '|', $params['continue'] ); 58 $this->dieContinueUsageIf( count( $cont ) != 2 ); 59 $cont_page = (int)$cont[0]; 60 $pages = array_filter( $pages, function ( $v ) use ( $cont_page ) { 61 return $v >= $cont_page; 62 } ); 63 } 64 if ( !count( $pages ) ) { 65 // Nothing to do 66 return; 67 } 68 69 // Apply MAX_PAGES, leaving any over the limit for a continue. 70 sort( $pages ); 71 $continuePages = null; 72 if ( count( $pages ) > self::MAX_PAGES ) { 73 $continuePages = $pages[self::MAX_PAGES] . '|0'; 74 $pages = array_slice( $pages, 0, self::MAX_PAGES ); 75 } 76 77 $result = $this->getResult(); 78 79 // First, count anons 80 $this->addTables( 'revision' ); 81 $this->addFields( array( 82 'page' => 'rev_page', 83 'anons' => 'COUNT(DISTINCT rev_user_text)', 84 ) ); 85 $this->addWhereFld( 'rev_page', $pages ); 86 $this->addWhere( 'rev_user = 0' ); 87 $this->addWhere( $db->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ); 88 $this->addOption( 'GROUP BY', 'rev_page' ); 89 $res = $this->select( __METHOD__ ); 90 foreach ( $res as $row ) { 91 $fit = $result->addValue( array( 'query', 'pages', $row->page ), 92 'anoncontributors', $row->anons 93 ); 94 if ( !$fit ) { 95 // This not fitting isn't reasonable, so it probably means that 96 // some other module used up all the space. Just set a dummy 97 // continue and hope it works next time. 98 $this->setContinueEnumParameter( 'continue', 99 $params['continue'] !== null ? $params['continue'] : '0|0' 100 ); 101 102 return; 103 } 104 } 105 106 // Next, add logged-in users 107 $this->resetQueryParams(); 108 $this->addTables( 'revision' ); 109 $this->addFields( array( 110 'page' => 'rev_page', 111 'user' => 'rev_user', 112 'username' => 'MAX(rev_user_text)', // Non-MySQL databases don't like partial group-by 113 ) ); 114 $this->addWhereFld( 'rev_page', $pages ); 115 $this->addWhere( 'rev_user != 0' ); 116 $this->addWhere( $db->bitAnd( 'rev_deleted', Revision::DELETED_USER ) . ' = 0' ); 117 $this->addOption( 'GROUP BY', 'rev_page, rev_user' ); 118 $this->addOption( 'LIMIT', $params['limit'] + 1 ); 119 120 // Force a sort order to ensure that properties are grouped by page 121 // But only if pp_page is not constant in the WHERE clause. 122 if ( count( $pages ) > 1 ) { 123 $this->addOption( 'ORDER BY', 'rev_page, rev_user' ); 124 } else { 125 $this->addOption( 'ORDER BY', 'rev_user' ); 126 } 127 128 $limitGroups = array(); 129 if ( $params['group'] ) { 130 $excludeGroups = false; 131 $limitGroups = $params['group']; 132 } elseif ( $params['excludegroup'] ) { 133 $excludeGroups = true; 134 $limitGroups = $params['excludegroup']; 135 } elseif ( $params['rights'] ) { 136 $excludeGroups = false; 137 foreach ( $params['rights'] as $r ) { 138 $limitGroups = array_merge( $limitGroups, User::getGroupsWithPermission( $r ) ); 139 } 140 141 // If no group has the rights requested, no need to query 142 if ( !$limitGroups ) { 143 if ( $continuePages !== null ) { 144 // But we still need to continue for the next page's worth 145 // of anoncontributors 146 $this->setContinueEnumParameter( 'continue', $continuePages ); 147 } 148 149 return; 150 } 151 } elseif ( $params['excluderights'] ) { 152 $excludeGroups = true; 153 foreach ( $params['excluderights'] as $r ) { 154 $limitGroups = array_merge( $limitGroups, User::getGroupsWithPermission( $r ) ); 155 } 156 } 157 158 if ( $limitGroups ) { 159 $limitGroups = array_unique( $limitGroups ); 160 $this->addTables( 'user_groups' ); 161 $this->addJoinConds( array( 'user_groups' => array( 162 $excludeGroups ? 'LEFT OUTER JOIN' : 'INNER JOIN', 163 array( 'ug_user=rev_user', 'ug_group' => $limitGroups ) 164 ) ) ); 165 $this->addWhereIf( 'ug_user IS NULL', $excludeGroups ); 166 } 167 168 if ( $params['continue'] !== null ) { 169 $cont = explode( '|', $params['continue'] ); 170 $this->dieContinueUsageIf( count( $cont ) != 2 ); 171 $cont_page = (int)$cont[0]; 172 $cont_user = (int)$cont[1]; 173 $this->addWhere( 174 "rev_page > $cont_page OR " . 175 "(rev_page = $cont_page AND " . 176 "rev_user >= $cont_user)" 177 ); 178 } 179 180 $res = $this->select( __METHOD__ ); 181 $count = 0; 182 foreach ( $res as $row ) { 183 if ( ++$count > $params['limit'] ) { 184 // We've reached the one extra which shows that 185 // there are additional pages to be had. Stop here... 186 $this->setContinueEnumParameter( 'continue', $row->page . '|' . $row->user ); 187 188 return; 189 } 190 191 $fit = $this->addPageSubItem( $row->page, 192 array( 'userid' => $row->user, 'name' => $row->username ), 193 'user' 194 ); 195 if ( !$fit ) { 196 $this->setContinueEnumParameter( 'continue', $row->page . '|' . $row->user ); 197 198 return; 199 } 200 } 201 202 if ( $continuePages !== null ) { 203 $this->setContinueEnumParameter( 'continue', $continuePages ); 204 } 205 } 206 207 public function getCacheMode( $params ) { 208 return 'public'; 209 } 210 211 public function getAllowedParams() { 212 $userGroups = User::getAllGroups(); 213 $userRights = User::getAllRights(); 214 215 return array( 216 'group' => array( 217 ApiBase::PARAM_TYPE => $userGroups, 218 ApiBase::PARAM_ISMULTI => true, 219 ), 220 'excludegroup' => array( 221 ApiBase::PARAM_TYPE => $userGroups, 222 ApiBase::PARAM_ISMULTI => true, 223 ), 224 'rights' => array( 225 ApiBase::PARAM_TYPE => $userRights, 226 ApiBase::PARAM_ISMULTI => true, 227 ), 228 'excluderights' => array( 229 ApiBase::PARAM_TYPE => $userRights, 230 ApiBase::PARAM_ISMULTI => true, 231 ), 232 'limit' => array( 233 ApiBase::PARAM_DFLT => 10, 234 ApiBase::PARAM_TYPE => 'limit', 235 ApiBase::PARAM_MIN => 1, 236 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1, 237 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2 238 ), 239 'continue' => null, 240 ); 241 } 242 243 public function getParamDescription() { 244 return array( 245 'group' => array( 246 'Limit users to given group name(s)', 247 'Does not include implicit or auto-promoted groups like *, user, or autoconfirmed' 248 ), 249 'excludegroup' => array( 250 'Exclude users in given group name(s)', 251 'Does not include implicit or auto-promoted groups like *, user, or autoconfirmed' 252 ), 253 'rights' => array( 254 'Limit users to those having given right(s)', 255 'Does not include rights granted by implicit or auto-promoted groups ' . 256 'like *, user, or autoconfirmed' 257 ), 258 'excluderights' => array( 259 'Limit users to those not having given right(s)', 260 'Does not include rights granted by implicit or auto-promoted groups ' . 261 'like *, user, or autoconfirmed' 262 ), 263 'limit' => 'How many contributors to return', 264 'continue' => 'When more results are available, use this to continue', 265 ); 266 } 267 268 public function getDescription() { 269 return 'Get the list of logged-in contributors and ' . 270 'the count of anonymous contributors to a page.'; 271 } 272 273 public function getExamples() { 274 return array( 275 'api.php?action=query&prop=contributors&titles=Main_Page', 276 ); 277 } 278 279 public function getHelpUrls() { 280 return 'https://www.mediawiki.org/wiki/API:Properties#contributors_.2F_pc'; 281 } 282 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |