[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/api/ -> ApiQueryContributors.php (source)

   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  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1