[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/specials/ -> SpecialRecentchangeslinked.php (source)

   1  <?php
   2  /**
   3   * Implements Special:Recentchangeslinked
   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   * @ingroup SpecialPage
  22   */
  23  
  24  /**
  25   * This is to display changes made to all articles linked in an article.
  26   *
  27   * @ingroup SpecialPage
  28   */
  29  class SpecialRecentChangesLinked extends SpecialRecentChanges {
  30      /** @var bool|Title */
  31      protected $rclTargetTitle;
  32  
  33  	function __construct() {
  34          parent::__construct( 'Recentchangeslinked' );
  35      }
  36  
  37  	public function getDefaultOptions() {
  38          $opts = parent::getDefaultOptions();
  39          $opts->add( 'target', '' );
  40          $opts->add( 'showlinkedto', false );
  41  
  42          return $opts;
  43      }
  44  
  45  	public function parseParameters( $par, FormOptions $opts ) {
  46          $opts['target'] = $par;
  47      }
  48  
  49  	public function doMainQuery( $conds, $opts ) {
  50          $target = $opts['target'];
  51          $showlinkedto = $opts['showlinkedto'];
  52          $limit = $opts['limit'];
  53  
  54          if ( $target === '' ) {
  55              return false;
  56          }
  57          $outputPage = $this->getOutput();
  58          $title = Title::newFromURL( $target );
  59          if ( !$title || $title->isExternal() ) {
  60              $outputPage->addHtml( '<div class="errorbox">' . $this->msg( 'allpagesbadtitle' )
  61                      ->parse() . '</div>' );
  62  
  63              return false;
  64          }
  65  
  66          $outputPage->setPageTitle( $this->msg( 'recentchangeslinked-title', $title->getPrefixedText() ) );
  67  
  68          /*
  69           * Ordinary links are in the pagelinks table, while transclusions are
  70           * in the templatelinks table, categorizations in categorylinks and
  71           * image use in imagelinks.  We need to somehow combine all these.
  72           * Special:Whatlinkshere does this by firing multiple queries and
  73           * merging the results, but the code we inherit from our parent class
  74           * expects only one result set so we use UNION instead.
  75           */
  76  
  77          $dbr = wfGetDB( DB_SLAVE, 'recentchangeslinked' );
  78          $id = $title->getArticleID();
  79          $ns = $title->getNamespace();
  80          $dbkey = $title->getDBkey();
  81  
  82          $tables = array( 'recentchanges' );
  83          $select = RecentChange::selectFields();
  84          $join_conds = array();
  85          $query_options = array();
  86  
  87          // left join with watchlist table to highlight watched rows
  88          $uid = $this->getUser()->getId();
  89          if ( $uid && $this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
  90              $tables[] = 'watchlist';
  91              $select[] = 'wl_user';
  92              $join_conds['watchlist'] = array( 'LEFT JOIN', array(
  93                  'wl_user' => $uid,
  94                  'wl_title=rc_title',
  95                  'wl_namespace=rc_namespace'
  96              ) );
  97          }
  98          if ( $this->getUser()->isAllowed( 'rollback' ) ) {
  99              $tables[] = 'page';
 100              $join_conds['page'] = array( 'LEFT JOIN', 'rc_cur_id=page_id' );
 101              $select[] = 'page_latest';
 102          }
 103          ChangeTags::modifyDisplayQuery(
 104              $tables,
 105              $select,
 106              $conds,
 107              $join_conds,
 108              $query_options,
 109              $opts['tagfilter']
 110          );
 111  
 112          if ( !$this->runMainQueryHook( $tables, $select, $conds, $query_options, $join_conds,
 113              $opts )
 114          ) {
 115              return false;
 116          }
 117  
 118          if ( $ns == NS_CATEGORY && !$showlinkedto ) {
 119              // special handling for categories
 120              // XXX: should try to make this less kludgy
 121              $link_tables = array( 'categorylinks' );
 122              $showlinkedto = true;
 123          } else {
 124              // for now, always join on these tables; really should be configurable as in whatlinkshere
 125              $link_tables = array( 'pagelinks', 'templatelinks' );
 126              // imagelinks only contains links to pages in NS_FILE
 127              if ( $ns == NS_FILE || !$showlinkedto ) {
 128                  $link_tables[] = 'imagelinks';
 129              }
 130          }
 131  
 132          if ( $id == 0 && !$showlinkedto ) {
 133              return false; // nonexistent pages can't link to any pages
 134          }
 135  
 136          // field name prefixes for all the various tables we might want to join with
 137          $prefix = array(
 138              'pagelinks' => 'pl',
 139              'templatelinks' => 'tl',
 140              'categorylinks' => 'cl',
 141              'imagelinks' => 'il'
 142          );
 143  
 144          $subsql = array(); // SELECT statements to combine with UNION
 145  
 146          foreach ( $link_tables as $link_table ) {
 147              $pfx = $prefix[$link_table];
 148  
 149              // imagelinks and categorylinks tables have no xx_namespace field,
 150              // and have xx_to instead of xx_title
 151              if ( $link_table == 'imagelinks' ) {
 152                  $link_ns = NS_FILE;
 153              } elseif ( $link_table == 'categorylinks' ) {
 154                  $link_ns = NS_CATEGORY;
 155              } else {
 156                  $link_ns = 0;
 157              }
 158  
 159              if ( $showlinkedto ) {
 160                  // find changes to pages linking to this page
 161                  if ( $link_ns ) {
 162                      if ( $ns != $link_ns ) {
 163                          continue;
 164                      } // should never happen, but check anyway
 165                      $subconds = array( "{$pfx}_to" => $dbkey );
 166                  } else {
 167                      $subconds = array( "{$pfx}_namespace" => $ns, "{$pfx}_title" => $dbkey );
 168                  }
 169                  $subjoin = "rc_cur_id = {$pfx}_from";
 170              } else {
 171                  // find changes to pages linked from this page
 172                  $subconds = array( "{$pfx}_from" => $id );
 173                  if ( $link_table == 'imagelinks' || $link_table == 'categorylinks' ) {
 174                      $subconds["rc_namespace"] = $link_ns;
 175                      $subjoin = "rc_title = {$pfx}_to";
 176                  } else {
 177                      $subjoin = array( "rc_namespace = {$pfx}_namespace", "rc_title = {$pfx}_title" );
 178                  }
 179              }
 180  
 181              if ( $dbr->unionSupportsOrderAndLimit() ) {
 182                  $order = array( 'ORDER BY' => 'rc_timestamp DESC' );
 183              } else {
 184                  $order = array();
 185              }
 186  
 187              $query = $dbr->selectSQLText(
 188                  array_merge( $tables, array( $link_table ) ),
 189                  $select,
 190                  $conds + $subconds,
 191                  __METHOD__,
 192                  $order + $query_options,
 193                  $join_conds + array( $link_table => array( 'INNER JOIN', $subjoin ) )
 194              );
 195  
 196              if ( $dbr->unionSupportsOrderAndLimit() ) {
 197                  $query = $dbr->limitResult( $query, $limit );
 198              }
 199  
 200              $subsql[] = $query;
 201          }
 202  
 203          if ( count( $subsql ) == 0 ) {
 204              return false; // should never happen
 205          }
 206          if ( count( $subsql ) == 1 && $dbr->unionSupportsOrderAndLimit() ) {
 207              $sql = $subsql[0];
 208          } else {
 209              // need to resort and relimit after union
 210              $sql = $dbr->unionQueries( $subsql, false ) . ' ORDER BY rc_timestamp DESC';
 211              $sql = $dbr->limitResult( $sql, $limit, false );
 212          }
 213  
 214          $res = $dbr->query( $sql, __METHOD__ );
 215  
 216          if ( $res->numRows() == 0 ) {
 217              $this->mResultEmpty = true;
 218          }
 219  
 220          return $res;
 221      }
 222  
 223  	function setTopText( FormOptions $opts ) {
 224          $target = $this->getTargetTitle();
 225          if ( $target ) {
 226              $this->getOutput()->addBacklinkSubtitle( $target );
 227              $this->getSkin()->setRelevantTitle( $target );
 228          }
 229      }
 230  
 231      /**
 232       * Get options to be displayed in a form
 233       *
 234       * @param FormOptions $opts
 235       * @return array
 236       */
 237  	function getExtraOptions( $opts ) {
 238          $extraOpts = parent::getExtraOptions( $opts );
 239  
 240          $opts->consumeValues( array( 'showlinkedto', 'target' ) );
 241  
 242          $extraOpts['target'] = array( $this->msg( 'recentchangeslinked-page' )->escaped(),
 243              Xml::input( 'target', 40, str_replace( '_', ' ', $opts['target'] ) ) .
 244              Xml::check( 'showlinkedto', $opts['showlinkedto'], array( 'id' => 'showlinkedto' ) ) . ' ' .
 245              Xml::label( $this->msg( 'recentchangeslinked-to' )->text(), 'showlinkedto' ) );
 246  
 247          return $extraOpts;
 248      }
 249  
 250      /**
 251       * @return Title
 252       */
 253  	function getTargetTitle() {
 254          if ( $this->rclTargetTitle === null ) {
 255              $opts = $this->getOptions();
 256              if ( isset( $opts['target'] ) && $opts['target'] !== '' ) {
 257                  $this->rclTargetTitle = Title::newFromText( $opts['target'] );
 258              } else {
 259                  $this->rclTargetTitle = false;
 260              }
 261          }
 262  
 263          return $this->rclTargetTitle;
 264      }
 265  }


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