MediaWiki
REL1_20
|
00001 <?php 00028 class LinksUpdate extends SqlDataUpdate { 00029 00030 // @todo: make members protected, but make sure extensions don't break 00031 00032 public $mId, 00033 $mTitle, 00034 $mParserOutput, 00035 $mLinks, 00036 $mImages, 00037 $mTemplates, 00038 $mExternals, 00039 $mCategories, 00040 $mInterlangs, 00041 $mProperties, 00042 $mDb, 00043 $mOptions, 00044 $mRecursive; 00045 00053 function __construct( $title, $parserOutput, $recursive = true ) { 00054 parent::__construct( false ); // no implicit transaction 00055 00056 if ( !( $title instanceof Title ) ) { 00057 throw new MWException( "The calling convention to LinksUpdate::LinksUpdate() has changed. " . 00058 "Please see Article::editUpdates() for an invocation example.\n" ); 00059 } 00060 00061 if ( !( $parserOutput instanceof ParserOutput ) ) { 00062 throw new MWException( "The calling convention to LinksUpdate::__construct() has changed. " . 00063 "Please see WikiPage::doEditUpdates() for an invocation example.\n" ); 00064 } 00065 00066 $this->mTitle = $title; 00067 $this->mId = $title->getArticleID(); 00068 00069 if ( !$this->mId ) { 00070 throw new MWException( "The Title object did not provide an article ID. Perhaps the page doesn't exist?" ); 00071 } 00072 00073 $this->mParserOutput = $parserOutput; 00074 $this->mLinks = $parserOutput->getLinks(); 00075 $this->mImages = $parserOutput->getImages(); 00076 $this->mTemplates = $parserOutput->getTemplates(); 00077 $this->mExternals = $parserOutput->getExternalLinks(); 00078 $this->mCategories = $parserOutput->getCategories(); 00079 $this->mProperties = $parserOutput->getProperties(); 00080 $this->mInterwikis = $parserOutput->getInterwikiLinks(); 00081 00082 # Convert the format of the interlanguage links 00083 # I didn't want to change it in the ParserOutput, because that array is passed all 00084 # the way back to the skin, so either a skin API break would be required, or an 00085 # inefficient back-conversion. 00086 $ill = $parserOutput->getLanguageLinks(); 00087 $this->mInterlangs = array(); 00088 foreach ( $ill as $link ) { 00089 list( $key, $title ) = explode( ':', $link, 2 ); 00090 $this->mInterlangs[$key] = $title; 00091 } 00092 00093 foreach ( $this->mCategories as &$sortkey ) { 00094 # If the sortkey is longer then 255 bytes, 00095 # it truncated by DB, and then doesn't get 00096 # matched when comparing existing vs current 00097 # categories, causing bug 25254. 00098 # Also. substr behaves weird when given "". 00099 if ( $sortkey !== '' ) { 00100 $sortkey = substr( $sortkey, 0, 255 ); 00101 } 00102 } 00103 00104 $this->mRecursive = $recursive; 00105 00106 wfRunHooks( 'LinksUpdateConstructed', array( &$this ) ); 00107 } 00108 00112 public function doUpdate() { 00113 global $wgUseDumbLinkUpdate; 00114 00115 wfRunHooks( 'LinksUpdate', array( &$this ) ); 00116 if ( $wgUseDumbLinkUpdate ) { 00117 $this->doDumbUpdate(); 00118 } else { 00119 $this->doIncrementalUpdate(); 00120 } 00121 wfRunHooks( 'LinksUpdateComplete', array( &$this ) ); 00122 } 00123 00124 protected function doIncrementalUpdate() { 00125 wfProfileIn( __METHOD__ ); 00126 00127 # Page links 00128 $existing = $this->getExistingLinks(); 00129 $this->incrTableUpdate( 'pagelinks', 'pl', $this->getLinkDeletions( $existing ), 00130 $this->getLinkInsertions( $existing ) ); 00131 00132 # Image links 00133 $existing = $this->getExistingImages(); 00134 00135 $imageDeletes = $this->getImageDeletions( $existing ); 00136 $this->incrTableUpdate( 'imagelinks', 'il', $imageDeletes, 00137 $this->getImageInsertions( $existing ) ); 00138 00139 # Invalidate all image description pages which had links added or removed 00140 $imageUpdates = $imageDeletes + array_diff_key( $this->mImages, $existing ); 00141 $this->invalidateImageDescriptions( $imageUpdates ); 00142 00143 # External links 00144 $existing = $this->getExistingExternals(); 00145 $this->incrTableUpdate( 'externallinks', 'el', $this->getExternalDeletions( $existing ), 00146 $this->getExternalInsertions( $existing ) ); 00147 00148 # Language links 00149 $existing = $this->getExistingInterlangs(); 00150 $this->incrTableUpdate( 'langlinks', 'll', $this->getInterlangDeletions( $existing ), 00151 $this->getInterlangInsertions( $existing ) ); 00152 00153 # Inline interwiki links 00154 $existing = $this->getExistingInterwikis(); 00155 $this->incrTableUpdate( 'iwlinks', 'iwl', $this->getInterwikiDeletions( $existing ), 00156 $this->getInterwikiInsertions( $existing ) ); 00157 00158 # Template links 00159 $existing = $this->getExistingTemplates(); 00160 $this->incrTableUpdate( 'templatelinks', 'tl', $this->getTemplateDeletions( $existing ), 00161 $this->getTemplateInsertions( $existing ) ); 00162 00163 # Category links 00164 $existing = $this->getExistingCategories(); 00165 00166 $categoryDeletes = $this->getCategoryDeletions( $existing ); 00167 00168 $this->incrTableUpdate( 'categorylinks', 'cl', $categoryDeletes, 00169 $this->getCategoryInsertions( $existing ) ); 00170 00171 # Invalidate all categories which were added, deleted or changed (set symmetric difference) 00172 $categoryInserts = array_diff_assoc( $this->mCategories, $existing ); 00173 $categoryUpdates = $categoryInserts + $categoryDeletes; 00174 $this->invalidateCategories( $categoryUpdates ); 00175 $this->updateCategoryCounts( $categoryInserts, $categoryDeletes ); 00176 00177 # Page properties 00178 $existing = $this->getExistingProperties(); 00179 00180 $propertiesDeletes = $this->getPropertyDeletions( $existing ); 00181 00182 $this->incrTableUpdate( 'page_props', 'pp', $propertiesDeletes, 00183 $this->getPropertyInsertions( $existing ) ); 00184 00185 # Invalidate the necessary pages 00186 $changed = $propertiesDeletes + array_diff_assoc( $this->mProperties, $existing ); 00187 $this->invalidateProperties( $changed ); 00188 00189 # Refresh links of all pages including this page 00190 # This will be in a separate transaction 00191 if ( $this->mRecursive ) { 00192 $this->queueRecursiveJobs(); 00193 } 00194 00195 wfProfileOut( __METHOD__ ); 00196 } 00197 00203 protected function doDumbUpdate() { 00204 wfProfileIn( __METHOD__ ); 00205 00206 # Refresh category pages and image description pages 00207 $existing = $this->getExistingCategories(); 00208 $categoryInserts = array_diff_assoc( $this->mCategories, $existing ); 00209 $categoryDeletes = array_diff_assoc( $existing, $this->mCategories ); 00210 $categoryUpdates = $categoryInserts + $categoryDeletes; 00211 $existing = $this->getExistingImages(); 00212 $imageUpdates = array_diff_key( $existing, $this->mImages ) + array_diff_key( $this->mImages, $existing ); 00213 00214 $this->dumbTableUpdate( 'pagelinks', $this->getLinkInsertions(), 'pl_from' ); 00215 $this->dumbTableUpdate( 'imagelinks', $this->getImageInsertions(), 'il_from' ); 00216 $this->dumbTableUpdate( 'categorylinks', $this->getCategoryInsertions(), 'cl_from' ); 00217 $this->dumbTableUpdate( 'templatelinks', $this->getTemplateInsertions(), 'tl_from' ); 00218 $this->dumbTableUpdate( 'externallinks', $this->getExternalInsertions(), 'el_from' ); 00219 $this->dumbTableUpdate( 'langlinks', $this->getInterlangInsertions(),'ll_from' ); 00220 $this->dumbTableUpdate( 'iwlinks', $this->getInterwikiInsertions(),'iwl_from' ); 00221 $this->dumbTableUpdate( 'page_props', $this->getPropertyInsertions(), 'pp_page' ); 00222 00223 # Update the cache of all the category pages and image description 00224 # pages which were changed, and fix the category table count 00225 $this->invalidateCategories( $categoryUpdates ); 00226 $this->updateCategoryCounts( $categoryInserts, $categoryDeletes ); 00227 $this->invalidateImageDescriptions( $imageUpdates ); 00228 00229 # Refresh links of all pages including this page 00230 # This will be in a separate transaction 00231 if ( $this->mRecursive ) { 00232 $this->queueRecursiveJobs(); 00233 } 00234 00235 wfProfileOut( __METHOD__ ); 00236 } 00237 00238 function queueRecursiveJobs() { 00239 global $wgUpdateRowsPerJob; 00240 wfProfileIn( __METHOD__ ); 00241 00242 $cache = $this->mTitle->getBacklinkCache(); 00243 $batches = $cache->partition( 'templatelinks', $wgUpdateRowsPerJob ); 00244 if ( !$batches ) { 00245 wfProfileOut( __METHOD__ ); 00246 return; 00247 } 00248 $jobs = array(); 00249 foreach ( $batches as $batch ) { 00250 list( $start, $end ) = $batch; 00251 $params = array( 00252 'table' => 'templatelinks', 00253 'start' => $start, 00254 'end' => $end, 00255 ); 00256 $jobs[] = new RefreshLinksJob2( $this->mTitle, $params ); 00257 } 00258 Job::batchInsert( $jobs ); 00259 00260 wfProfileOut( __METHOD__ ); 00261 } 00262 00266 function invalidateCategories( $cats ) { 00267 $this->invalidatePages( NS_CATEGORY, array_keys( $cats ) ); 00268 } 00269 00275 function updateCategoryCounts( $added, $deleted ) { 00276 $a = WikiPage::factory( $this->mTitle ); 00277 $a->updateCategoryCounts( 00278 array_keys( $added ), array_keys( $deleted ) 00279 ); 00280 } 00281 00285 function invalidateImageDescriptions( $images ) { 00286 $this->invalidatePages( NS_FILE, array_keys( $images ) ); 00287 } 00288 00294 private function dumbTableUpdate( $table, $insertions, $fromField ) { 00295 $this->mDb->delete( $table, array( $fromField => $this->mId ), __METHOD__ ); 00296 if ( count( $insertions ) ) { 00297 # The link array was constructed without FOR UPDATE, so there may 00298 # be collisions. This may cause minor link table inconsistencies, 00299 # which is better than crippling the site with lock contention. 00300 $this->mDb->insert( $table, $insertions, __METHOD__, array( 'IGNORE' ) ); 00301 } 00302 } 00303 00311 function incrTableUpdate( $table, $prefix, $deletions, $insertions ) { 00312 if ( $table == 'page_props' ) { 00313 $fromField = 'pp_page'; 00314 } else { 00315 $fromField = "{$prefix}_from"; 00316 } 00317 $where = array( $fromField => $this->mId ); 00318 if ( $table == 'pagelinks' || $table == 'templatelinks' || $table == 'iwlinks' ) { 00319 if ( $table == 'iwlinks' ) { 00320 $baseKey = 'iwl_prefix'; 00321 } else { 00322 $baseKey = "{$prefix}_namespace"; 00323 } 00324 $clause = $this->mDb->makeWhereFrom2d( $deletions, $baseKey, "{$prefix}_title" ); 00325 if ( $clause ) { 00326 $where[] = $clause; 00327 } else { 00328 $where = false; 00329 } 00330 } else { 00331 if ( $table == 'langlinks' ) { 00332 $toField = 'll_lang'; 00333 } elseif ( $table == 'page_props' ) { 00334 $toField = 'pp_propname'; 00335 } else { 00336 $toField = $prefix . '_to'; 00337 } 00338 if ( count( $deletions ) ) { 00339 $where[] = "$toField IN (" . $this->mDb->makeList( array_keys( $deletions ) ) . ')'; 00340 } else { 00341 $where = false; 00342 } 00343 } 00344 if ( $where ) { 00345 $this->mDb->delete( $table, $where, __METHOD__ ); 00346 } 00347 if ( count( $insertions ) ) { 00348 $this->mDb->insert( $table, $insertions, __METHOD__, 'IGNORE' ); 00349 } 00350 } 00351 00358 private function getLinkInsertions( $existing = array() ) { 00359 $arr = array(); 00360 foreach( $this->mLinks as $ns => $dbkeys ) { 00361 $diffs = isset( $existing[$ns] ) 00362 ? array_diff_key( $dbkeys, $existing[$ns] ) 00363 : $dbkeys; 00364 foreach ( $diffs as $dbk => $id ) { 00365 $arr[] = array( 00366 'pl_from' => $this->mId, 00367 'pl_namespace' => $ns, 00368 'pl_title' => $dbk 00369 ); 00370 } 00371 } 00372 return $arr; 00373 } 00374 00380 private function getTemplateInsertions( $existing = array() ) { 00381 $arr = array(); 00382 foreach( $this->mTemplates as $ns => $dbkeys ) { 00383 $diffs = isset( $existing[$ns] ) ? array_diff_key( $dbkeys, $existing[$ns] ) : $dbkeys; 00384 foreach ( $diffs as $dbk => $id ) { 00385 $arr[] = array( 00386 'tl_from' => $this->mId, 00387 'tl_namespace' => $ns, 00388 'tl_title' => $dbk 00389 ); 00390 } 00391 } 00392 return $arr; 00393 } 00394 00401 private function getImageInsertions( $existing = array() ) { 00402 $arr = array(); 00403 $diffs = array_diff_key( $this->mImages, $existing ); 00404 foreach( $diffs as $iname => $dummy ) { 00405 $arr[] = array( 00406 'il_from' => $this->mId, 00407 'il_to' => $iname 00408 ); 00409 } 00410 return $arr; 00411 } 00412 00418 private function getExternalInsertions( $existing = array() ) { 00419 $arr = array(); 00420 $diffs = array_diff_key( $this->mExternals, $existing ); 00421 foreach( $diffs as $url => $dummy ) { 00422 foreach( wfMakeUrlIndexes( $url ) as $index ) { 00423 $arr[] = array( 00424 'el_from' => $this->mId, 00425 'el_to' => $url, 00426 'el_index' => $index, 00427 ); 00428 } 00429 } 00430 return $arr; 00431 } 00432 00441 private function getCategoryInsertions( $existing = array() ) { 00442 global $wgContLang, $wgCategoryCollation; 00443 $diffs = array_diff_assoc( $this->mCategories, $existing ); 00444 $arr = array(); 00445 foreach ( $diffs as $name => $prefix ) { 00446 $nt = Title::makeTitleSafe( NS_CATEGORY, $name ); 00447 $wgContLang->findVariantLink( $name, $nt, true ); 00448 00449 if ( $this->mTitle->getNamespace() == NS_CATEGORY ) { 00450 $type = 'subcat'; 00451 } elseif ( $this->mTitle->getNamespace() == NS_FILE ) { 00452 $type = 'file'; 00453 } else { 00454 $type = 'page'; 00455 } 00456 00457 # Treat custom sortkeys as a prefix, so that if multiple 00458 # things are forced to sort as '*' or something, they'll 00459 # sort properly in the category rather than in page_id 00460 # order or such. 00461 $sortkey = Collation::singleton()->getSortKey( 00462 $this->mTitle->getCategorySortkey( $prefix ) ); 00463 00464 $arr[] = array( 00465 'cl_from' => $this->mId, 00466 'cl_to' => $name, 00467 'cl_sortkey' => $sortkey, 00468 'cl_timestamp' => $this->mDb->timestamp(), 00469 'cl_sortkey_prefix' => $prefix, 00470 'cl_collation' => $wgCategoryCollation, 00471 'cl_type' => $type, 00472 ); 00473 } 00474 return $arr; 00475 } 00476 00484 private function getInterlangInsertions( $existing = array() ) { 00485 $diffs = array_diff_assoc( $this->mInterlangs, $existing ); 00486 $arr = array(); 00487 foreach( $diffs as $lang => $title ) { 00488 $arr[] = array( 00489 'll_from' => $this->mId, 00490 'll_lang' => $lang, 00491 'll_title' => $title 00492 ); 00493 } 00494 return $arr; 00495 } 00496 00502 function getPropertyInsertions( $existing = array() ) { 00503 $diffs = array_diff_assoc( $this->mProperties, $existing ); 00504 $arr = array(); 00505 foreach ( $diffs as $name => $value ) { 00506 $arr[] = array( 00507 'pp_page' => $this->mId, 00508 'pp_propname' => $name, 00509 'pp_value' => $value, 00510 ); 00511 } 00512 return $arr; 00513 } 00514 00521 private function getInterwikiInsertions( $existing = array() ) { 00522 $arr = array(); 00523 foreach( $this->mInterwikis as $prefix => $dbkeys ) { 00524 $diffs = isset( $existing[$prefix] ) ? array_diff_key( $dbkeys, $existing[$prefix] ) : $dbkeys; 00525 foreach ( $diffs as $dbk => $id ) { 00526 $arr[] = array( 00527 'iwl_from' => $this->mId, 00528 'iwl_prefix' => $prefix, 00529 'iwl_title' => $dbk 00530 ); 00531 } 00532 } 00533 return $arr; 00534 } 00535 00542 private function getLinkDeletions( $existing ) { 00543 $del = array(); 00544 foreach ( $existing as $ns => $dbkeys ) { 00545 if ( isset( $this->mLinks[$ns] ) ) { 00546 $del[$ns] = array_diff_key( $existing[$ns], $this->mLinks[$ns] ); 00547 } else { 00548 $del[$ns] = $existing[$ns]; 00549 } 00550 } 00551 return $del; 00552 } 00553 00560 private function getTemplateDeletions( $existing ) { 00561 $del = array(); 00562 foreach ( $existing as $ns => $dbkeys ) { 00563 if ( isset( $this->mTemplates[$ns] ) ) { 00564 $del[$ns] = array_diff_key( $existing[$ns], $this->mTemplates[$ns] ); 00565 } else { 00566 $del[$ns] = $existing[$ns]; 00567 } 00568 } 00569 return $del; 00570 } 00571 00578 private function getImageDeletions( $existing ) { 00579 return array_diff_key( $existing, $this->mImages ); 00580 } 00581 00588 private function getExternalDeletions( $existing ) { 00589 return array_diff_key( $existing, $this->mExternals ); 00590 } 00591 00598 private function getCategoryDeletions( $existing ) { 00599 return array_diff_assoc( $existing, $this->mCategories ); 00600 } 00601 00608 private function getInterlangDeletions( $existing ) { 00609 return array_diff_assoc( $existing, $this->mInterlangs ); 00610 } 00611 00617 function getPropertyDeletions( $existing ) { 00618 return array_diff_assoc( $existing, $this->mProperties ); 00619 } 00620 00627 private function getInterwikiDeletions( $existing ) { 00628 $del = array(); 00629 foreach ( $existing as $prefix => $dbkeys ) { 00630 if ( isset( $this->mInterwikis[$prefix] ) ) { 00631 $del[$prefix] = array_diff_key( $existing[$prefix], $this->mInterwikis[$prefix] ); 00632 } else { 00633 $del[$prefix] = $existing[$prefix]; 00634 } 00635 } 00636 return $del; 00637 } 00638 00644 private function getExistingLinks() { 00645 $res = $this->mDb->select( 'pagelinks', array( 'pl_namespace', 'pl_title' ), 00646 array( 'pl_from' => $this->mId ), __METHOD__, $this->mOptions ); 00647 $arr = array(); 00648 foreach ( $res as $row ) { 00649 if ( !isset( $arr[$row->pl_namespace] ) ) { 00650 $arr[$row->pl_namespace] = array(); 00651 } 00652 $arr[$row->pl_namespace][$row->pl_title] = 1; 00653 } 00654 return $arr; 00655 } 00656 00662 private function getExistingTemplates() { 00663 $res = $this->mDb->select( 'templatelinks', array( 'tl_namespace', 'tl_title' ), 00664 array( 'tl_from' => $this->mId ), __METHOD__, $this->mOptions ); 00665 $arr = array(); 00666 foreach ( $res as $row ) { 00667 if ( !isset( $arr[$row->tl_namespace] ) ) { 00668 $arr[$row->tl_namespace] = array(); 00669 } 00670 $arr[$row->tl_namespace][$row->tl_title] = 1; 00671 } 00672 return $arr; 00673 } 00674 00680 private function getExistingImages() { 00681 $res = $this->mDb->select( 'imagelinks', array( 'il_to' ), 00682 array( 'il_from' => $this->mId ), __METHOD__, $this->mOptions ); 00683 $arr = array(); 00684 foreach ( $res as $row ) { 00685 $arr[$row->il_to] = 1; 00686 } 00687 return $arr; 00688 } 00689 00695 private function getExistingExternals() { 00696 $res = $this->mDb->select( 'externallinks', array( 'el_to' ), 00697 array( 'el_from' => $this->mId ), __METHOD__, $this->mOptions ); 00698 $arr = array(); 00699 foreach ( $res as $row ) { 00700 $arr[$row->el_to] = 1; 00701 } 00702 return $arr; 00703 } 00704 00710 private function getExistingCategories() { 00711 $res = $this->mDb->select( 'categorylinks', array( 'cl_to', 'cl_sortkey_prefix' ), 00712 array( 'cl_from' => $this->mId ), __METHOD__, $this->mOptions ); 00713 $arr = array(); 00714 foreach ( $res as $row ) { 00715 $arr[$row->cl_to] = $row->cl_sortkey_prefix; 00716 } 00717 return $arr; 00718 } 00719 00726 private function getExistingInterlangs() { 00727 $res = $this->mDb->select( 'langlinks', array( 'll_lang', 'll_title' ), 00728 array( 'll_from' => $this->mId ), __METHOD__, $this->mOptions ); 00729 $arr = array(); 00730 foreach ( $res as $row ) { 00731 $arr[$row->ll_lang] = $row->ll_title; 00732 } 00733 return $arr; 00734 } 00735 00740 protected function getExistingInterwikis() { 00741 $res = $this->mDb->select( 'iwlinks', array( 'iwl_prefix', 'iwl_title' ), 00742 array( 'iwl_from' => $this->mId ), __METHOD__, $this->mOptions ); 00743 $arr = array(); 00744 foreach ( $res as $row ) { 00745 if ( !isset( $arr[$row->iwl_prefix] ) ) { 00746 $arr[$row->iwl_prefix] = array(); 00747 } 00748 $arr[$row->iwl_prefix][$row->iwl_title] = 1; 00749 } 00750 return $arr; 00751 } 00752 00758 private function getExistingProperties() { 00759 $res = $this->mDb->select( 'page_props', array( 'pp_propname', 'pp_value' ), 00760 array( 'pp_page' => $this->mId ), __METHOD__, $this->mOptions ); 00761 $arr = array(); 00762 foreach ( $res as $row ) { 00763 $arr[$row->pp_propname] = $row->pp_value; 00764 } 00765 return $arr; 00766 } 00767 00772 public function getTitle() { 00773 return $this->mTitle; 00774 } 00775 00781 public function getParserOutput() { 00782 return $this->mParserOutput; 00783 } 00784 00789 public function getImages() { 00790 return $this->mImages; 00791 } 00792 00797 private function invalidateProperties( $changed ) { 00798 global $wgPagePropLinkInvalidations; 00799 00800 foreach ( $changed as $name => $value ) { 00801 if ( isset( $wgPagePropLinkInvalidations[$name] ) ) { 00802 $inv = $wgPagePropLinkInvalidations[$name]; 00803 if ( !is_array( $inv ) ) { 00804 $inv = array( $inv ); 00805 } 00806 foreach ( $inv as $table ) { 00807 $update = new HTMLCacheUpdate( $this->mTitle, $table ); 00808 $update->doUpdate(); 00809 } 00810 } 00811 } 00812 } 00813 } 00814 00818 class LinksDeletionUpdate extends SqlDataUpdate { 00819 00820 protected $mPage; 00821 00827 function __construct( WikiPage $page ) { 00828 parent::__construct( false ); // no implicit transaction 00829 00830 $this->mPage = $page; 00831 } 00832 00836 public function doUpdate() { 00837 $title = $this->mPage->getTitle(); 00838 $id = $this->mPage->getId(); 00839 00840 # Delete restrictions for it 00841 $this->mDb->delete( 'page_restrictions', array ( 'pr_page' => $id ), __METHOD__ ); 00842 00843 # Fix category table counts 00844 $cats = array(); 00845 $res = $this->mDb->select( 'categorylinks', 'cl_to', array( 'cl_from' => $id ), __METHOD__ ); 00846 00847 foreach ( $res as $row ) { 00848 $cats [] = $row->cl_to; 00849 } 00850 00851 $this->mPage->updateCategoryCounts( array(), $cats ); 00852 00853 # If using cascading deletes, we can skip some explicit deletes 00854 if ( !$this->mDb->cascadingDeletes() ) { 00855 $this->mDb->delete( 'revision', array( 'rev_page' => $id ), __METHOD__ ); 00856 00857 # Delete outgoing links 00858 $this->mDb->delete( 'pagelinks', array( 'pl_from' => $id ), __METHOD__ ); 00859 $this->mDb->delete( 'imagelinks', array( 'il_from' => $id ), __METHOD__ ); 00860 $this->mDb->delete( 'categorylinks', array( 'cl_from' => $id ), __METHOD__ ); 00861 $this->mDb->delete( 'templatelinks', array( 'tl_from' => $id ), __METHOD__ ); 00862 $this->mDb->delete( 'externallinks', array( 'el_from' => $id ), __METHOD__ ); 00863 $this->mDb->delete( 'langlinks', array( 'll_from' => $id ), __METHOD__ ); 00864 $this->mDb->delete( 'iwlinks', array( 'iwl_from' => $id ), __METHOD__ ); 00865 $this->mDb->delete( 'redirect', array( 'rd_from' => $id ), __METHOD__ ); 00866 $this->mDb->delete( 'page_props', array( 'pp_page' => $id ), __METHOD__ ); 00867 } 00868 00869 # If using cleanup triggers, we can skip some manual deletes 00870 if ( !$this->mDb->cleanupTriggers() ) { 00871 # Clean up recentchanges entries... 00872 $this->mDb->delete( 'recentchanges', 00873 array( 'rc_type != ' . RC_LOG, 00874 'rc_namespace' => $title->getNamespace(), 00875 'rc_title' => $title->getDBkey() ), 00876 __METHOD__ ); 00877 $this->mDb->delete( 'recentchanges', 00878 array( 'rc_type != ' . RC_LOG, 'rc_cur_id' => $id ), 00879 __METHOD__ ); 00880 } 00881 } 00882 }