[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/maintenance/ -> orphans.php (source)

   1  <?php
   2  /**
   3   * Look for 'orphan' revisions hooked to pages which don't exist and
   4   * 'childless' pages with no revisions.
   5   * Then, kill the poor widows and orphans.
   6   * Man this is depressing.
   7   *
   8   * Copyright © 2005 Brion Vibber <[email protected]>
   9   * https://www.mediawiki.org/
  10   *
  11   * This program is free software; you can redistribute it and/or modify
  12   * it under the terms of the GNU General Public License as published by
  13   * the Free Software Foundation; either version 2 of the License, or
  14   * (at your option) any later version.
  15   *
  16   * This program is distributed in the hope that it will be useful,
  17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19   * GNU General Public License for more details.
  20   *
  21   * You should have received a copy of the GNU General Public License along
  22   * with this program; if not, write to the Free Software Foundation, Inc.,
  23   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24   * http://www.gnu.org/copyleft/gpl.html
  25   *
  26   * @file
  27   * @author <[email protected]>
  28   * @ingroup Maintenance
  29   */
  30  
  31  require_once  __DIR__ . '/Maintenance.php';
  32  
  33  /**
  34   * Maintenance script that looks for 'orphan' revisions hooked to pages which
  35   * don't exist and 'childless' pages with no revisions.
  36   *
  37   * @ingroup Maintenance
  38   */
  39  class Orphans extends Maintenance {
  40  	public function __construct() {
  41          parent::__construct();
  42          $this->mDescription = "Look for 'orphan' revisions hooked to pages which don't exist\n" .
  43              "and 'childless' pages with no revisions\n" .
  44              "Then, kill the poor widows and orphans\n" .
  45              "Man this is depressing";
  46          $this->addOption( 'fix', 'Actually fix broken entries' );
  47      }
  48  
  49  	public function execute() {
  50          $this->checkOrphans( $this->hasOption( 'fix' ) );
  51          $this->checkSeparation( $this->hasOption( 'fix' ) );
  52          # Does not work yet, do not use
  53          # $this->checkWidows( $this->hasOption( 'fix' ) );
  54      }
  55  
  56      /**
  57       * Lock the appropriate tables for the script
  58       * @param DatabaseBase $db
  59       * @param string $extraTable The name of any extra tables to lock (eg: text)
  60       */
  61  	private function lockTables( $db, $extraTable = array() ) {
  62          $tbls = array( 'page', 'revision', 'redirect' );
  63          if ( $extraTable ) {
  64              $tbls = array_merge( $tbls, $extraTable );
  65          }
  66          $db->lockTables( array(), $tbls, __METHOD__, false );
  67      }
  68  
  69      /**
  70       * Check for orphan revisions
  71       * @param bool $fix Whether to fix broken revisions when found
  72       */
  73  	private function checkOrphans( $fix ) {
  74          $dbw = wfGetDB( DB_MASTER );
  75          $page = $dbw->tableName( 'page' );
  76          $revision = $dbw->tableName( 'revision' );
  77  
  78          if ( $fix ) {
  79              $this->lockTables( $dbw );
  80          }
  81  
  82          $this->output( "Checking for orphan revision table entries... "
  83              . "(this may take a while on a large wiki)\n" );
  84          $result = $dbw->query( "
  85              SELECT *
  86              FROM $revision LEFT OUTER JOIN $page ON rev_page=page_id
  87              WHERE page_id IS NULL
  88          " );
  89          $orphans = $result->numRows();
  90          if ( $orphans > 0 ) {
  91              global $wgContLang;
  92  
  93              $this->output( "$orphans orphan revisions...\n" );
  94              $this->output( sprintf(
  95                  "%10s %10s %14s %20s %s\n",
  96                  'rev_id', 'rev_page', 'rev_timestamp', 'rev_user_text', 'rev_comment'
  97              ) );
  98  
  99              foreach ( $result as $row ) {
 100                  $comment = ( $row->rev_comment == '' )
 101                      ? ''
 102                      : '(' . $wgContLang->truncate( $row->rev_comment, 40 ) . ')';
 103                  $this->output( sprintf( "%10d %10d %14s %20s %s\n",
 104                      $row->rev_id,
 105                      $row->rev_page,
 106                      $row->rev_timestamp,
 107                      $wgContLang->truncate( $row->rev_user_text, 17 ),
 108                      $comment ) );
 109                  if ( $fix ) {
 110                      $dbw->delete( 'revision', array( 'rev_id' => $row->rev_id ) );
 111                  }
 112              }
 113              if ( !$fix ) {
 114                  $this->output( "Run again with --fix to remove these entries automatically.\n" );
 115              }
 116          } else {
 117              $this->output( "No orphans! Yay!\n" );
 118          }
 119  
 120          if ( $fix ) {
 121              $dbw->unlockTables( __METHOD__ );
 122          }
 123      }
 124  
 125      /**
 126       * @param bool $fix
 127       * @todo DON'T USE THIS YET! It will remove entries which have children,
 128       *       but which aren't properly attached (eg if page_latest is bogus
 129       *       but valid revisions do exist)
 130       */
 131  	private function checkWidows( $fix ) {
 132          $dbw = wfGetDB( DB_MASTER );
 133          $page = $dbw->tableName( 'page' );
 134          $revision = $dbw->tableName( 'revision' );
 135  
 136          if ( $fix ) {
 137              $this->lockTables( $dbw );
 138          }
 139  
 140          $this->output( "\nChecking for childless page table entries... "
 141              . "(this may take a while on a large wiki)\n" );
 142          $result = $dbw->query( "
 143              SELECT *
 144              FROM $page LEFT OUTER JOIN $revision ON page_latest=rev_id
 145              WHERE rev_id IS NULL
 146          " );
 147          $widows = $result->numRows();
 148          if ( $widows > 0 ) {
 149              $this->output( "$widows childless pages...\n" );
 150              $this->output( sprintf( "%10s %11s %2s %s\n", 'page_id', 'page_latest', 'ns', 'page_title' ) );
 151              foreach ( $result as $row ) {
 152                  printf( "%10d %11d %2d %s\n",
 153                      $row->page_id,
 154                      $row->page_latest,
 155                      $row->page_namespace,
 156                      $row->page_title );
 157                  if ( $fix ) {
 158                      $dbw->delete( 'page', array( 'page_id' => $row->page_id ) );
 159                  }
 160              }
 161              if ( !$fix ) {
 162                  $this->output( "Run again with --fix to remove these entries automatically.\n" );
 163              }
 164          } else {
 165              $this->output( "No childless pages! Yay!\n" );
 166          }
 167  
 168          if ( $fix ) {
 169              $dbw->unlockTables( __METHOD__ );
 170          }
 171      }
 172  
 173      /**
 174       * Check for pages where page_latest is wrong
 175       * @param bool $fix Whether to fix broken entries
 176       */
 177  	private function checkSeparation( $fix ) {
 178          $dbw = wfGetDB( DB_MASTER );
 179          $page = $dbw->tableName( 'page' );
 180          $revision = $dbw->tableName( 'revision' );
 181  
 182          if ( $fix ) {
 183              $this->lockTables( $dbw, array( 'user', 'text' ) );
 184          }
 185  
 186          $this->output( "\nChecking for pages whose page_latest links are incorrect... "
 187              . "(this may take a while on a large wiki)\n" );
 188          $result = $dbw->query( "
 189              SELECT *
 190              FROM $page LEFT OUTER JOIN $revision ON page_latest=rev_id
 191          " );
 192          $found = 0;
 193          foreach ( $result as $row ) {
 194              $result2 = $dbw->query( "
 195                  SELECT MAX(rev_timestamp) as max_timestamp
 196                  FROM $revision
 197                  WHERE rev_page=$row->page_id
 198              " );
 199              $row2 = $dbw->fetchObject( $result2 );
 200              if ( $row2 ) {
 201                  if ( $row->rev_timestamp != $row2->max_timestamp ) {
 202                      if ( $found == 0 ) {
 203                          $this->output( sprintf( "%10s %10s %14s %14s\n",
 204                              'page_id', 'rev_id', 'timestamp', 'max timestamp' ) );
 205                      }
 206                      ++$found;
 207                      $this->output( sprintf( "%10d %10d %14s %14s\n",
 208                          $row->page_id,
 209                          $row->page_latest,
 210                          $row->rev_timestamp,
 211                          $row2->max_timestamp ) );
 212                      if ( $fix ) {
 213                          # ...
 214                          $maxId = $dbw->selectField(
 215                              'revision',
 216                              'rev_id',
 217                              array(
 218                                  'rev_page' => $row->page_id,
 219                                  'rev_timestamp' => $row2->max_timestamp ) );
 220                          $this->output( "... updating to revision $maxId\n" );
 221                          $maxRev = Revision::newFromId( $maxId );
 222                          $title = Title::makeTitle( $row->page_namespace, $row->page_title );
 223                          $article = WikiPage::factory( $title );
 224                          $article->updateRevisionOn( $dbw, $maxRev );
 225                      }
 226                  }
 227              } else {
 228                  $this->output( "wtf\n" );
 229              }
 230          }
 231  
 232          if ( $found ) {
 233              $this->output( "Found $found pages with incorrect latest revision.\n" );
 234          } else {
 235              $this->output( "No pages with incorrect latest revision. Yay!\n" );
 236          }
 237          if ( !$fix && $found > 0 ) {
 238              $this->output( "Run again with --fix to remove these entries automatically.\n" );
 239          }
 240  
 241          if ( $fix ) {
 242              $dbw->unlockTables( __METHOD__ );
 243          }
 244      }
 245  }
 246  
 247  $maintClass = "Orphans";
 248  require_once RUN_MAINTENANCE_IF_MAIN;


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