pagetranslation-check-database.php

Go to the documentation of this file.
00001 <?php
00012 // Standard boilerplate to define $IP
00013 if ( getenv( 'MW_INSTALL_PATH' ) !== false ) {
00014     $IP = getenv( 'MW_INSTALL_PATH' );
00015 } else {
00016     $dir = dirname( __FILE__ ); $IP = "$dir/../../..";
00017 }
00018 require_once( "$IP/maintenance/Maintenance.php" );
00019 
00025 class PTCheckDB extends Maintenance {
00026     public function __construct() {
00027         parent::__construct();
00028         $this->mDescription = 'Check the consistency of the databases of the page translation feature and fix problems.';
00029         $this->addOption( 'fix', 'Fix the found problems if possible' );
00030     }
00031 
00032     public function execute() {
00033         $fixes = $this->checkSectionTable();
00034         $fixes += $this->checkRevTagTable();
00035 
00036         $dbw = wfGetDB( DB_MASTER );
00037         if ( $this->getOption( 'fix' ) ) {
00038             $this->output( "Performing the following fixes:\n" );
00039 
00040             foreach ( $fixes as $name => $data ) {
00041                 $this->output( "$name: $data[0]...", $name );
00042                 $dbw->delete( $data[1], '*', $data[2], __METHOD__ );
00043             }
00044         } else {
00045             $this->output( "Use --fix to perform following fixes:\n" );
00046 
00047             foreach ( $fixes as $name => $data ) {
00048                 $sql = $dbw->selectSQLtext( $data[1], '*', $data[2] );
00049                 $sql = preg_replace( '~^SELECT~', 'DELETE', $sql );
00050                 $this->output( "$name: $data[0] - $sql\n" );
00051             }
00052         }
00053     }
00054 
00055     protected function checkSectionTable() {
00056         $fixes = array();
00057 
00058         $dbr = wfGetDB( DB_SLAVE );
00059         $pages = $dbr->select( 'translate_sections', 'trs_page', null, __METHOD__, array( 'GROUP BY' => 'trs_page' ) );
00060 
00061         $this->output( "Found {$pages->numRows()} pages in the section table\n" );
00062         $this->output( "Checking that they match a valid translatable page...\n\n" );
00063 
00064         foreach ( $pages as $row ) {
00065             $id = $row->trs_page;
00066             $sections = $dbr->select( 'translate_sections', 'trs_key', array( 'trs_page' => $id ), __METHOD__ );
00067             $title = Title::newFromID( $id );
00068             $sectionNames = $this->getSectionNames( $sections );
00069 
00070             $name = $title ? $title->getPrefixedText() : "#$id";
00071             $this->output( "Page $name has {$sections->numRows()} sections [$sectionNames]\n" );
00072 
00073             if ( !$title ) {
00074                 $name = "#$id";
00075                 $deleted = $this->findDeletedPage( $id );
00076                 if ( $deleted === false ) {
00077                     $this->output( "Page id $id does not correspond to any page\n" );
00078                 } else {
00079                     $name .= "<$deleted>";
00080                     $this->output( "Page id $id corresponds to a deleted page $deleted\n" );
00081                 }
00082                 $fixes["$name <sections>"] = array( 'delete sections', 'translate_section', array( 'trs_page' => $id ) );
00083             } else {
00084                 $name = $title->getPrefixedText();
00085                 $page = TranslatablePage::newFromTitle( $title );
00086                 $tagged = $page->getReadyTag();
00087                 $marked = $page->getMarkedTag();
00088                 $latest = $title->getLatestRevId();
00089                 $this->output( "Revision numbers: <tagged, marked, latest> <$tagged, $marked, $latest>\n" );
00090                 if ( strval( $marked ) === '' ) {
00091                     $this->output( "These sections do not belong the current page (anymore?)\n" );
00092                     $fixes["$name <sections>"] = array( 'delete sections', 'translate_section', array( 'trs_page' => $id ) );
00093                 }
00094             }
00095 
00096             $this->output( "\n" );
00097         }
00098 
00099         return $fixes;
00100     }
00101 
00102     protected function checkRevTagTable() {
00103         $fixes = array();
00104 
00105         $dbr = wfGetDB( DB_SLAVE );
00106 
00107         $tags = array( 'tp:mark', 'tp:tag', 'tp:transver', 'fuzzy' );
00108 
00109         $pages = $dbr->select( 'revtag', 'rt_page', null, __METHOD__, array( 'GROUP BY' => 'rt_page' ) );
00110         $this->output( "Checking that tags match a valid page...\n\n" );
00111 
00112         foreach ( $pages as $row ) {
00113             $id = $row->rt_page;
00114             $title = Title::newFromID( $id );
00115             $name = $title ? $title->getPrefixedText() : "#$id";
00116 
00117             if ( !$title ) {
00118                 $name = "#$id";
00119                 $deleted = $this->findDeletedPage( $id );
00120                 if ( $deleted === false ) {
00121                     $this->output( "Page id $id does not correspond to any page\n" );
00122                     $fixes["$name <revtag>"] = array( 'delete tags', 'revtag', array( 'rt_page' => $id ) );
00123                 } else {
00124                     $name .= "<$deleted>";
00125                 }
00126             }
00127         }
00128 
00129         $this->output( "Checked {$pages->numRows()} pages in the revtag table\n" );
00130         $this->output( "\n\nValidating tags...\n" );
00131 
00132         $result = $dbr->select( 'revtag', '*', null, __METHOD__ );
00133         foreach ( $result as $_ ) {
00134             if ( !isset( $tags[$_->rt_type] ) ) {
00135                 $name = $this->idToName( $_->rt_page );
00136                 $this->output( "Page $name has unknown tag {$_->rt_type}\n" );
00137                 $fixes["$name <revtag:unknown:{$_->rt_type}>"] =
00138                     array( 'delete tag', 'revtag', array( 'rt_page' => $id, 'rt_type' => $_->rt_type ) );
00139                 continue;
00140             } elseif ( $_->rt_type === RevTag::getType( 'tp:transver' ) ) {
00141                 $check = $this->checkTransrevRevision( $rev ); // FIXME: $rev is undefined
00142                 if ( $check !== true ) {
00143                     $name = $this->idToName( $_->rt_page );
00144                     $this->output( "Page $name has invalid tp:transver: $check\n" );
00145                     $fixes["$name <revtag:transver>"] =
00146                         array( 'delete tag', 'revtag', array( 'rt_page' => $id, 'rt_type' => $_->rt_type ) );
00147                 }
00148             }
00149         }
00150 
00151         $this->output( "Checked {$result->numRows()} tags in the revtag table\n\n\n" );
00152 
00153         return $fixes;
00154     }
00155 
00156     protected function idToName( $id ) {
00157         $title = Title::newFromID( $id );
00158         $name = $title ? $title->getPrefixedText() : "#$id";
00159 
00160         if ( !$title ) {
00161             $name .= $this->findDeletedPage( $id );
00162         }
00163 
00164         return $name;
00165     }
00166 
00167     protected function getSectionNames( $result ) {
00168         $names = array();
00169 
00170         foreach ( $result as $section ) {
00171             $names[] = $section->trs_key;
00172         }
00173 
00174         return implode( ', ', $names );
00175     }
00176 
00177     protected function findDeletedPage( $id ) {
00178         $dbr = wfGetDB( DB_SLAVE );
00179         $page = $dbr->selectRow( 'archive', array( 'ar_namespace', 'ar_title' ),
00180             array( 'ar_page_id' => $id ), __METHOD__ );
00181 
00182         if ( $page ) {
00183             $title = Title::makeTitleSafe( $page->ar_namespace, $page->ar_title );
00184             if ( $title ) {
00185                 return $title->getPrefixedText();
00186             }
00187         }
00188 
00189         return false;
00190     }
00191 
00192     protected function checkTransrevRevision( $revId ) {
00193         static $cache = array();
00194 
00195         if ( isset( $cache[$revId] ) ) {
00196             return $cache[$revId];
00197         }
00198 
00199         $revision = Revision::newFromId( $revId );
00200         if ( !$revision ) {
00201             $cache[$revId] = 'no such revision';
00202         } else {
00203             $title = $revision->getTitle();
00204             if ( !$title ) {
00205                 $cache[$revId] = 'no title for the revision';
00206             } else {
00207                 $page = TranslatablePage::newFromTitle( $title );
00208                 if ( $page->getMarkedTag() === false ) {
00209                     $cache[$revId] = 'revision belongs to a page that is not marked for translation';
00210                 } else {
00211                     $cache[$revId] = true;
00212                 }
00213             }
00214         }
00215 
00216         return $cache[$revId];
00217     }
00218 }
00219 
00220 $maintClass = 'PTCheckDB';
00221 require_once( DO_MAINTENANCE );
Generated on Thu Oct 11 00:00:38 2012 for MediaWiki Translate Extension by  doxygen 1.6.3