Index: branches/iwtransclusion/phase3v3/includes/parser/Parser.php |
— | — | @@ -3268,8 +3268,9 @@ |
3269 | 3269 | } |
3270 | 3270 | } elseif ( $title->isTrans() ) { |
3271 | 3271 | // TODO: Work by Peter17 in progress |
3272 | | - |
| 3272 | + |
3273 | 3273 | $text = Interwiki::interwikiTransclude( $title ); |
| 3274 | + $this->registerDistantTemplate( $title ); |
3274 | 3275 | |
3275 | 3276 | if ( $text !== false ) { |
3276 | 3277 | # Preprocess it like a template |
— | — | @@ -3423,6 +3424,21 @@ |
3424 | 3425 | } |
3425 | 3426 | return array( $text, $finalTitle ); |
3426 | 3427 | } |
| 3428 | + |
| 3429 | + /** |
| 3430 | + * Register a distant template as used |
| 3431 | + */ |
| 3432 | + function registerDistantTemplate( $title ) { |
| 3433 | + $templateCb = array( 'Parser', 'distantTemplateCallback' ); |
| 3434 | + $stuff = call_user_func( $templateCb, $title, $this ); |
| 3435 | + $text = $stuff['text']; |
| 3436 | + $finalTitle = isset( $stuff['finalTitle'] ) ? $stuff['finalTitle'] : $title; |
| 3437 | + if ( isset( $stuff['deps'] ) ) { |
| 3438 | + foreach ( $stuff['deps'] as $dep ) { |
| 3439 | + $this->mOutput->addDistantTemplate( $dep['title'], $dep['page_id'], $dep['rev_id'] ); |
| 3440 | + } |
| 3441 | + } |
| 3442 | + } |
3427 | 3443 | |
3428 | 3444 | /** |
3429 | 3445 | * Fetch the unparsed text of a template and register a reference to it. |
— | — | @@ -3510,6 +3526,22 @@ |
3511 | 3527 | 'deps' => $deps ); |
3512 | 3528 | } |
3513 | 3529 | |
| 3530 | + static function distantTemplateCallback( $title, $parser=false ) { |
| 3531 | + $text = ''; |
| 3532 | + $rev_id = null; |
| 3533 | + $deps[] = array( |
| 3534 | + 'title' => $title, |
| 3535 | + 'page_id' => $title->getArticleID(), |
| 3536 | + 'rev_id' => $rev_id ); |
| 3537 | + |
| 3538 | + $finalTitle = $title; |
| 3539 | + |
| 3540 | + return array( |
| 3541 | + 'text' => $text, |
| 3542 | + 'finalTitle' => $finalTitle, |
| 3543 | + 'deps' => $deps ); |
| 3544 | + } |
| 3545 | + |
3514 | 3546 | /** |
3515 | 3547 | * Triple brace replacement -- used for template arguments |
3516 | 3548 | * @private |
Index: branches/iwtransclusion/phase3v3/includes/parser/ParserOutput.php |
— | — | @@ -121,6 +121,8 @@ |
122 | 122 | $mLinks = array(), # 2-D map of NS/DBK to ID for the links in the document. ID=zero for broken. |
123 | 123 | $mTemplates = array(), # 2-D map of NS/DBK to ID for the template references. ID=zero for broken. |
124 | 124 | $mTemplateIds = array(), # 2-D map of NS/DBK to rev ID for the template references. ID=zero for broken. |
| 125 | + $mDistantTemplates = array(), # 3-D map of WIKIID/NS/DBK to ID for the template references. ID=zero for broken. |
| 126 | + $mDistantTemplateIds = array(), # 3-D map of WIKIID/NS/DBK to rev ID for the template references. ID=zero for broken. |
125 | 127 | $mImages = array(), # DB keys of the images used, in the array key only |
126 | 128 | $mImageTimeKeys = array(), # DB keys of the images used mapped to sha1 and MW timestamp |
127 | 129 | $mExternalLinks = array(), # External link URLs, in the key only |
— | — | @@ -188,6 +190,8 @@ |
189 | 191 | function getEditSectionTokens() { return $this->mEditSectionTokens; } |
190 | 192 | function &getLinks() { return $this->mLinks; } |
191 | 193 | function &getTemplates() { return $this->mTemplates; } |
| 194 | + function &getDistantTemplates() { return $this->mDistantTemplates; } |
| 195 | + function &getDistantTemplateIds() { return $this->mDistantTemplateIds; } |
192 | 196 | function &getTemplateIds() { return $this->mTemplateIds; } |
193 | 197 | function &getImages() { return $this->mImages; } |
194 | 198 | function &getImageTimeKeys() { return $this->mImageTimeKeys; } |
— | — | @@ -306,6 +310,25 @@ |
307 | 311 | $this->mTemplateIds[$ns][$dbk] = $rev_id; // For versioning |
308 | 312 | } |
309 | 313 | |
| 314 | + function addDistantTemplate( $title, $page_id, $rev_id ) { |
| 315 | + $wikiid = $title->getTransWikiID(); |
| 316 | + if ( $wikiid !=='' ) { |
| 317 | + $ns = $title->getNamespace(); |
| 318 | + $dbk = $title->getDBkey(); |
| 319 | + if ( !isset( $this->mDistantTemplates[$wikiid] ) ) { |
| 320 | + $this->mDistantTemplates[$wikiid] = array(); |
| 321 | + } |
| 322 | + if ( !isset( $this->mDistantTemplates[$wikiid][$ns] ) ) { |
| 323 | + $this->mDistantTemplates[$wikiid][$ns] = array(); |
| 324 | + } |
| 325 | + $this->mDistantTemplates[$wikiid][$ns][$dbk] = $page_id; |
| 326 | + if ( !isset( $this->mDistantTemplateIds[$wikiid][$ns] ) ) { |
| 327 | + $this->mDistantTemplateIds[$wikiid][$ns] = array(); |
| 328 | + } |
| 329 | + $this->mDistantTemplateIds[$wikiid][$ns][$dbk] = $rev_id; // For versioning |
| 330 | + } |
| 331 | + } |
| 332 | + |
310 | 333 | /** |
311 | 334 | * @param $title Title object, must be an interwiki link |
312 | 335 | * @throws MWException if given invalid input |
Index: branches/iwtransclusion/phase3v3/includes/db/Database.php |
— | — | @@ -1777,7 +1777,37 @@ |
1778 | 1778 | return false; |
1779 | 1779 | } |
1780 | 1780 | } |
| 1781 | + |
| 1782 | + /** |
| 1783 | + * Build a partial where clause from a 3-d array |
| 1784 | + * The keys on each level may be either integers or strings. |
| 1785 | + * |
| 1786 | + * @param $data Array: organized as 3-d array(baseKeyVal => array(middleKeyVal => array(subKeyVal => <ignored>, ...), ...), ...) |
| 1787 | + * @param $baseKey String: field name to match the base-level keys to (eg 'gtl_to_wikiid') |
| 1788 | + * @param $middleKey String: field name to match the middle-level keys to (eg 'gtl_to_namespace') |
| 1789 | + * @param $subKey String: field name to match the sub-level keys to (eg 'gtl_to_title') |
| 1790 | + * @return Mixed: string SQL fragment, or false if no items in array. |
| 1791 | + */ |
| 1792 | + function makeWhereFrom3d( $data, $baseKey, $middleKey, $subKey ) { |
| 1793 | + $conds = array(); |
| 1794 | + foreach ( $data as $base => $subdata ) { |
| 1795 | + foreach ( $subdata as $middle => $sub ) { |
| 1796 | + if ( count( $sub ) ) { |
| 1797 | + $conds[] = $this->makeList( |
| 1798 | + array( $baseKey => $base, $middleKey => $middle, $subKey => array_keys( $sub ) ), |
| 1799 | + LIST_AND); |
| 1800 | + } |
| 1801 | + } |
| 1802 | + } |
1781 | 1803 | |
| 1804 | + if ( $conds ) { |
| 1805 | + return $this->makeList( $conds, LIST_OR ); |
| 1806 | + } else { |
| 1807 | + // Nothing to search for... |
| 1808 | + return false; |
| 1809 | + } |
| 1810 | + } |
| 1811 | + |
1782 | 1812 | /** |
1783 | 1813 | * Bitwise operations |
1784 | 1814 | */ |
Property changes on: branches/iwtransclusion/phase3v3/includes/db/Database.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
1785 | 1815 | Merged /branches/iwtransclusion/phase3/includes/db/Database.php:r70576 |
Index: branches/iwtransclusion/phase3v3/includes/LinksUpdate.php |
— | — | @@ -29,6 +29,7 @@ |
30 | 30 | $mLinks, //!< Map of title strings to IDs for the links in the document |
31 | 31 | $mImages, //!< DB keys of the images used, in the array key only |
32 | 32 | $mTemplates, //!< Map of title strings to IDs for the template references, including broken ones |
| 33 | + $mDistantTemplates,//!< Map of title strings to IDs for the distant template references, including broken ones |
33 | 34 | $mExternals, //!< URLs of external links, array key only |
34 | 35 | $mCategories, //!< Map of category names to sort keys |
35 | 36 | $mInterlangs, //!< Map of language codes to titles |
— | — | @@ -66,6 +67,7 @@ |
67 | 68 | $this->mLinks = $parserOutput->getLinks(); |
68 | 69 | $this->mImages = $parserOutput->getImages(); |
69 | 70 | $this->mTemplates = $parserOutput->getTemplates(); |
| 71 | + $this->mDistantTemplates = $parserOutput->getDistantTemplates(); |
70 | 72 | $this->mExternals = $parserOutput->getExternalLinks(); |
71 | 73 | $this->mCategories = $parserOutput->getCategories(); |
72 | 74 | $this->mProperties = $parserOutput->getProperties(); |
— | — | @@ -151,6 +153,15 @@ |
152 | 154 | $existing = $this->getExistingTemplates(); |
153 | 155 | $this->incrTableUpdate( 'templatelinks', 'tl', $this->getTemplateDeletions( $existing ), |
154 | 156 | $this->getTemplateInsertions( $existing ) ); |
| 157 | + |
| 158 | + # Distant template links |
| 159 | + global $wgGlobalDB; |
| 160 | + if ( $wgGlobalDB ) { |
| 161 | + $existing = $this->getDistantExistingTemplates(); |
| 162 | + $this->incrSharedTableUpdate( 'globaltemplatelinks', 'gtl', |
| 163 | + $this->getDistantTemplateDeletions( $existing ), |
| 164 | + $this->getDistantTemplateInsertions( $existing ) ); |
| 165 | + } |
155 | 166 | |
156 | 167 | # Category links |
157 | 168 | $existing = $this->getExistingCategories(); |
— | — | @@ -370,7 +381,39 @@ |
371 | 382 | $this->mDb->insert( $table, $insertions, __METHOD__, 'IGNORE' ); |
372 | 383 | } |
373 | 384 | } |
| 385 | + |
| 386 | + /** |
| 387 | + * Update a shared table by doing a delete query then an insert query |
| 388 | + * @private |
| 389 | + */ |
| 390 | + function incrSharedTableUpdate( $table, $prefix, $deletions, $insertions ) { |
374 | 391 | |
| 392 | + global $wgWikiID; |
| 393 | + global $wgGlobalDB; |
| 394 | + |
| 395 | + if ( $wgGlobalDB ) { |
| 396 | + $dbw = wfGetDB( DB_MASTER, array(), $wgGlobalDB ); |
| 397 | + $where = array( "{$prefix}_from_wiki" => $wgWikiID, |
| 398 | + "{$prefix}_from_page" => $this->mId |
| 399 | + ); |
| 400 | + $baseKey = "{$prefix}_to_wiki"; |
| 401 | + $middleKey = "{$prefix}_to_namespace"; |
| 402 | + |
| 403 | + $clause = $dbw->makeWhereFrom3d( $deletions, $baseKey, $middleKey, "{$prefix}_to_title" ); |
| 404 | + if ( $clause ) { |
| 405 | + $where[] = $clause; |
| 406 | + } else { |
| 407 | + $where = false; |
| 408 | + } |
| 409 | + |
| 410 | + if ( $where ) { |
| 411 | + $dbw->delete( $table, $where, __METHOD__ ); |
| 412 | + } |
| 413 | + if ( count( $insertions ) ) { |
| 414 | + $dbw->insert( $table, $insertions, __METHOD__, 'IGNORE' ); |
| 415 | + } |
| 416 | + } |
| 417 | + } |
375 | 418 | |
376 | 419 | /** |
377 | 420 | * Get an array of pagelinks insertions for passing to the DB |
— | — | @@ -412,6 +455,32 @@ |
413 | 456 | } |
414 | 457 | return $arr; |
415 | 458 | } |
| 459 | + |
| 460 | + /** |
| 461 | + * Get an array of distant template insertions. Like getLinkInsertions() |
| 462 | + * @private |
| 463 | + */ |
| 464 | + function getDistantTemplateInsertions( $existing = array() ) { |
| 465 | + global $wgWikiID; |
| 466 | + $arr = array(); |
| 467 | + foreach( $this->mDistantTemplates as $wikiid => $templatesToNS ) { |
| 468 | + foreach( $templatesToNS as $ns => $dbkeys ) { |
| 469 | + $diffs = isset( $existing[$wikiid] ) && isset( $existing[$wikiid][$ns] ) ? array_diff_key( $dbkeys, $existing[$wikiid][$ns] ) : $dbkeys; |
| 470 | + foreach ( $diffs as $dbk => $id ) { |
| 471 | + $arr[] = array( |
| 472 | + 'gtl_from_wiki' => $wgWikiID, |
| 473 | + 'gtl_from_page' => $this->mId, |
| 474 | + 'gtl_from_namespace' => $this->mTitle->getNsText(), |
| 475 | + 'gtl_from_title' => $this->mTitle->getText(), |
| 476 | + 'gtl_to_wiki' => $wikiid, |
| 477 | + 'gtl_to_namespace' => $ns, |
| 478 | + 'gtl_to_title' => $dbk |
| 479 | + ); |
| 480 | + } |
| 481 | + } |
| 482 | + } |
| 483 | + return $arr; |
| 484 | + } |
416 | 485 | |
417 | 486 | /** |
418 | 487 | * Get an array of image insertions |
— | — | @@ -578,6 +647,30 @@ |
579 | 648 | } |
580 | 649 | return $del; |
581 | 650 | } |
| 651 | + |
| 652 | + /** |
| 653 | + * Given an array of existing templates, returns those templates which are not in $this |
| 654 | + * and thus should be deleted. |
| 655 | + * @private |
| 656 | + */ |
| 657 | + function getDistantTemplateDeletions( $existing ) { |
| 658 | + $del = array(); |
| 659 | + foreach ( $existing as $wikiid => $templatesForNS ) { |
| 660 | + if ( isset( $this->mDistantTemplates[$wikiid] ) ) { |
| 661 | + $del[$wikiid] = array_diff_key( $existing[$wikiid], $this->mDistantTemplates[$wikiid] ); |
| 662 | + } else { |
| 663 | + $del[$wikiid] = $existing[$wikiid]; |
| 664 | + } |
| 665 | + foreach ( $templatesForNS as $ns => $dbkeys ) { |
| 666 | + if ( isset( $this->mDistantTemplates[$wikiid][$ns] ) ) { |
| 667 | + $del[$wikiid][$ns] = array_diff_key( $existing[$wikiid][$ns], $this->mDistantTemplates[$wikiid][$ns] ); |
| 668 | + } else { |
| 669 | + $del[$wikiid][$ns] = $existing[$wikiid][$ns]; |
| 670 | + } |
| 671 | + } |
| 672 | + } |
| 673 | + return $del; |
| 674 | + } |
582 | 675 | |
583 | 676 | /** |
584 | 677 | * Given an array of existing images, returns those images which are not in $this |
— | — | @@ -673,6 +766,33 @@ |
674 | 767 | } |
675 | 768 | return $arr; |
676 | 769 | } |
| 770 | + |
| 771 | + /** |
| 772 | + * Get an array of existing distant templates, as a 3-D array |
| 773 | + * @private |
| 774 | + */ |
| 775 | + function getDistantExistingTemplates() { |
| 776 | + global $wgWikiID; |
| 777 | + global $wgGlobalDB; |
| 778 | + |
| 779 | + $arr = array(); |
| 780 | + if ( $wgGlobalDB ) { |
| 781 | + $dbr = wfGetDB( DB_SLAVE, array(), $wgGlobalDB ); |
| 782 | + $res = $dbr->select( 'globaltemplatelinks', array( 'gtl_to_wiki', 'gtl_to_namespace', 'gtl_to_title' ), |
| 783 | + array( 'gtl_from_wiki' => $wgWikiID, 'gtl_from_page' => $this->mId ), __METHOD__, $this->mOptions ); |
| 784 | + while ( $row = $dbr->fetchObject( $res ) ) { |
| 785 | + if ( !isset( $arr[$row->gtl_to_wiki] ) ) { |
| 786 | + $arr[$row->gtl_to_wiki] = array(); |
| 787 | + } |
| 788 | + if ( !isset( $arr[$row->gtl_to_wiki][$row->gtl_to_namespace] ) ) { |
| 789 | + $arr[$row->gtl_to_wiki][$row->gtl_to_namespace] = array(); |
| 790 | + } |
| 791 | + $arr[$row->gtl_to_wiki][$row->gtl_to_namespace][$row->gtl_to_title] = 1; |
| 792 | + } |
| 793 | + $dbr->freeResult( $res ); |
| 794 | + } |
| 795 | + return $arr; |
| 796 | + } |
677 | 797 | |
678 | 798 | /** |
679 | 799 | * Get an array of existing images, image names in the keys |
Index: branches/iwtransclusion/phase3v3/includes/Title.php |
— | — | @@ -3132,6 +3132,8 @@ |
3133 | 3133 | * @return Mixed true on success, getUserPermissionsErrors()-like array on failure |
3134 | 3134 | */ |
3135 | 3135 | public function moveTo( &$nt, $auth = true, $reason = '', $createRedirect = true ) { |
| 3136 | + global $wgContLang, $wgGlobalDB, $wgWikiID; |
| 3137 | + |
3136 | 3138 | $err = $this->isValidMoveOperation( $nt, $auth, $reason ); |
3137 | 3139 | if ( is_array( $err ) ) { |
3138 | 3140 | return $err; |
— | — | @@ -3187,6 +3189,15 @@ |
3188 | 3190 | __METHOD__ |
3189 | 3191 | ); |
3190 | 3192 | } |
| 3193 | + |
| 3194 | + if ( $wgGlobalDB ) { |
| 3195 | + $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDB ); |
| 3196 | + $dbw2->update( 'globaltemplatelinks', |
| 3197 | + array( 'gtl_from_namespace' => $nt->getNsText(), |
| 3198 | + 'gtl_from_title' => $nt->getText() ), |
| 3199 | + array ( 'gtl_from_page' => $pageid ), |
| 3200 | + __METHOD__ ); |
| 3201 | + } |
3191 | 3202 | |
3192 | 3203 | if ( $protected ) { |
3193 | 3204 | # Protect the redirect title as the title used to be... |
— | — | @@ -3280,8 +3291,8 @@ |
3281 | 3292 | * @param $createRedirect Bool Whether to leave a redirect at the old title. Ignored |
3282 | 3293 | * if the user doesn't have the suppressredirect right |
3283 | 3294 | */ |
3284 | | - private function moveToInternal( &$nt, $reason = '', $createRedirect = true ) { |
3285 | | - global $wgUser, $wgContLang; |
| 3295 | + private function moveOverExistingRedirect( &$nt, $reason = '', $createRedirect = true ) { |
| 3296 | + global $wgUseSquid, $wgUser, $wgContLang, $wgWikiID, $wgGlobalDB; |
3286 | 3297 | |
3287 | 3298 | $moveOverRedirect = $nt->exists(); |
3288 | 3299 | |
— | — | @@ -3333,6 +3344,14 @@ |
3334 | 3345 | array( 'rc_timestamp' => $rcts, 'rc_namespace' => $newns, 'rc_title' => $newdbk, 'rc_new' => 1 ), |
3335 | 3346 | __METHOD__ |
3336 | 3347 | ); |
| 3348 | + |
| 3349 | + if ( $wgGlobalDB ) { |
| 3350 | + $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDB ); |
| 3351 | + $dbw2->delete( 'globaltemplatelinks', |
| 3352 | + array( 'gtl_from_wiki' => $wgWikiID, |
| 3353 | + 'gtl_from_page' => $newid ), |
| 3354 | + __METHOD__ ); |
| 3355 | + } |
3337 | 3356 | } |
3338 | 3357 | |
3339 | 3358 | # Save a null revision in the page's history notifying of the move |
Property changes on: branches/iwtransclusion/phase3v3/includes/Title.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
3340 | 3359 | Merged /branches/iwtransclusion/phase3/includes/Title.php:r70576 |
Index: branches/iwtransclusion/phase3v3/includes/WikiPage.php |
— | — | @@ -1571,7 +1571,7 @@ |
1572 | 1572 | public function doDeleteArticle( |
1573 | 1573 | $reason, $suppress = false, $id = 0, $commit = true, &$error = '', User $user = null |
1574 | 1574 | ) { |
1575 | | - global $wgDeferredUpdateList, $wgUseTrackbacks, $wgUser; |
| 1575 | + global $wgDeferredUpdateList, $wgUseTrackbacks, $wgUser, $wgEnableInterwikiTemplatesTracking, $wgGlobalDatabase; |
1576 | 1576 | $user = is_null( $user ) ? $wgUser : $user; |
1577 | 1577 | |
1578 | 1578 | wfDebug( __METHOD__ . "\n" ); |
— | — | @@ -1673,6 +1673,13 @@ |
1674 | 1674 | $dbw->delete( 'langlinks', array( 'll_from' => $id ) ); |
1675 | 1675 | $dbw->delete( 'iwlinks', array( 'iwl_from' => $id ) ); |
1676 | 1676 | $dbw->delete( 'redirect', array( 'rd_from' => $id ) ); |
| 1677 | + if ( $wgGlobalDB ) { |
| 1678 | + $dbw2 = wfGetDB( DB_MASTER, array(), $wgGlobalDB ); |
| 1679 | + $dbw2->delete( 'globaltemplatelinks', |
| 1680 | + array( 'gtl_from_wiki' => $wgWikiID, |
| 1681 | + 'gtl_from_page' => $id ) |
| 1682 | + ); |
| 1683 | + } |
1677 | 1684 | } |
1678 | 1685 | |
1679 | 1686 | # If using cleanup triggers, we can skip some manual deletes |