ShoutWiki/Patches/Interwiki
Contents |
Patch description [edit]
MediaWiki's interwiki/interlanguage link handling just plain sucks. Why? Because both interwikis (links to other wikis, such as wikipedia:foo) and interlanguage links (links between the different language versions of the same wiki) are stored in the same table.
Due to this, we cannot add the interwiki table into $wgSharedTables — that would mean that ShoutWiki Hub's interlanguage links (i.e. fr or fi) would work outside ShoutWiki Hub. Obviously on fi.24, fr: should link to fr.24.shoutwiki.com and not to fr.shoutwiki.com.
To work around these limitations, we have written an extension and patched Special:Interwiki extension code.
The interwiki prefixes will always be fetched from the shared DB, $wgSharedDB. The interwiki table in this database should never be empty! Interlanguage links, such as en, fi or fr will be fetched from local interwiki table. Local interwiki tables can be and in most cases, are empty.
includes/Interwiki.php [edit]
| This patch is outdated and unnecessary as of MediaWiki 1.18+ as it was built against MediaWiki 1.15. For MediaWiki 1.18.0+, you can use the ShoutWiki Interwiki Magic extension. You can also use it against earlier versions of MediaWiki if you manually apply r84173 against your codebase. |
Index: trunk/includes/Interwiki.php =================================================================== --- trunk/includes/Interwiki.php (revision 1103) +++ trunk/includes/Interwiki.php (revision 1104) @@ -151,9 +151,24 @@ } $db = wfGetDB( DB_SLAVE ); - - $row = $db->fetchRow( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ), - __METHOD__ ) ); + // Begin ShoutWiki patch + // Handle global interwikis + // and local interlanguage links + // By Jack Phoenix <jack@shoutwiki.com> + // @date July 12/13, 2009 + // @see http://bugzilla.shoutwiki.com/show_bug.cgi?id=12 + global $wgSharedDB, $wgDBname, $wgContLang; + if( $wgContLang->getLanguageName( $prefix ) ){ + $db->selectDB( $wgDBname ); + $row = $db->fetchRow( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ), + __METHOD__ ) ); + } else { + $db->selectDB( $wgSharedDB ); + $row = $db->fetchRow( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ), + __METHOD__ ) ); + $db->selectDB( $wgDBname ); // necessary - if this is missing then things *will* fuck up. Creating a new article with [[someinterwiki:some page]] will create it on wgSharedDB and such... + } + // End ShoutWiki patch $iw = Interwiki::loadFromArray( $row ); if ( $iw ) { $mc = array( 'iw_url' => $iw->mURL, 'iw_local' => $iw->mLocal, 'iw_trans' => $iw->mTrans );
extensions/Interwiki/ [edit]
ShoutWiki uses the SpecialInterwiki extension for managing interwiki and interlanguage links, so we also had to patch that.
This patch was built against a recent version of the Interwiki extension and should be perfectly up-to-date.
extensions/Interwiki/Interwiki_body.php [edit]
Index: extensions/Interwiki/Interwiki_body.php =================================================================== --- extensions/Interwiki/Interwiki_body.php (revision 1861) +++ extensions/Interwiki/Interwiki_body.php (revision 1862) @@ -110,7 +110,19 @@ $formContent = ''; } elseif ( $action == 'edit' ) { $dbr = wfGetDB( DB_SLAVE ); - $row = $dbr->selectRow( 'interwiki', '*', array( 'iw_prefix' => $prefix ), __METHOD__ ); + // ShoutWiki patch begin + global $wgContLang, $wgDBname, $wgSharedDB; + if( $wgContLang->getLanguageName( $prefix ) ) { + // It's an interlanguage link -> fetch from local table + $dbr->selectDB( $wgDBname ); + $row = $dbr->selectRow( 'interwiki', '*', array( 'iw_prefix' => $prefix ), __METHOD__ ); + } else { + // It's an ordinary interwiki -> fetch from global table + $dbr->selectDB( $wgSharedDB ); + $row = $dbr->selectRow( 'interwiki', '*', array( 'iw_prefix' => $prefix ), __METHOD__ ); + $dbr->selectDB( $wgDBname ); + } + // End ShoutWiki patch if ( !$row ) { $this->error( 'interwiki_editerror', $prefix ); @@ -177,6 +189,7 @@ function doSubmit() { global $wgContLang, $wgMemc; + global $wgDBname, $wgSharedDB; // ShoutWiki $request = $this->getRequest(); $prefix = $request->getVal( 'wpInterwikiPrefix' ); @@ -192,7 +205,18 @@ $dbw = wfGetDB( DB_MASTER ); switch( $do ) { case 'delete': - $dbw->delete( 'interwiki', array( 'iw_prefix' => $prefix ), __METHOD__ ); + // ShoutWiki patch begin + if( $wgContLang->getLanguageName( $prefix ) ) { + // Interlanguage link -> delete from local table + $dbw->selectDB( $wgDBname ); + $dbw->delete( 'interwiki', array( 'iw_prefix' => $prefix ), __METHOD__ ); + } else { + // Normal interwiki -> delete from global table + $dbw->selectDB( $wgSharedDB ); + $dbw->delete( 'interwiki', array( 'iw_prefix' => $prefix ), __METHOD__ ); + $dbw->selectDB( $wgDBname ); + } + // ShoutWiki patch end if ( $dbw->affectedRows() == 0 ) { $this->error( 'interwiki_delfailed', $prefix ); @@ -223,11 +247,23 @@ return; } - if ( $do == 'add' ) { + // ShoutWiki patch begin + if( $do == 'add' && $wgContLang->getLanguageName( $prefix ) ) { + $dbw->selectDB( $wgDBname ); $dbw->insert( 'interwiki', $data, __METHOD__, 'IGNORE' ); + } elseif( $do == 'add' && !$wgContLang->getLanguageName( $prefix ) ) { + $dbw->selectDB( $wgSharedDB ); + $dbw->insert( 'interwiki', $data, __METHOD__, 'IGNORE' ); + $dbw->selectDB( $wgDBname ); + } elseif( $do !== 'add' && $wgContLang->getLanguageName( $prefix ) ) { + $dbw->selectDB( $wgDBname ); + $dbw->update( 'interwiki', $data, array( 'iw_prefix' => $prefix ), __METHOD__, 'IGNORE' ); } else { + $dbw->selectDB( $wgSharedDB ); $dbw->update( 'interwiki', $data, array( 'iw_prefix' => $prefix ), __METHOD__, 'IGNORE' ); + $dbw->selectDB( $wgDBname ); } + // ShoutWiki patch end if ( $dbw->affectedRows() == 0 ) { $this->error( "interwiki_{$do}failed", $prefix ); @@ -271,6 +307,8 @@ $this->error( 'interwiki_error' ); return; } + + /* ShoutWiki patch begin $iwPrefixes = Interwiki::getAllPrefixes( null ); if ( !is_array( $iwPrefixes ) || count( $iwPrefixes ) == 0 ) { @@ -278,10 +316,27 @@ $this->error( 'interwiki_error' ); return; } + */ + // Unconditionally load this data from the shared table, no exceptions + // We assume that the shared interwiki table will always have some rows + // and will never be empty, because that's the way it should be + global $wgContLang, $wgSharedDB; + $dbr_shared = wfGetDB( DB_SLAVE, array(), $wgSharedDB ); + $res = $dbr_shared->select( 'interwiki', '*', false, __METHOD__ ); + $retval = array(); + foreach ( $res as $row ) { + $retval[] = (array)$row; + } + $iwPrefixes = $retval; + // ShoutWiki patch end + $out = ''; # Output the table header + // ShoutWiki patch begin + $out .= '<h2>' . wfMsgHtml( 'interwiki-global-header' ) . '</h2>'; + // ShoutWiki patch end $out .= Html::openElement( 'table', array( 'class' => 'mw-interwikitable wikitable sortable body' ) ) . "\n"; $out .= Html::openElement( 'tr', array( 'id' => 'interwikitable-header' ) ) . Html::element( 'th', null, $this->msg( 'interwiki_prefix' ) ) . @@ -294,27 +349,90 @@ $selfTitle = $this->getTitle(); foreach ( $iwPrefixes as $i => $iwPrefix ) { - $out .= Html::openElement( 'tr', array( 'class' => 'mw-interwikitable-row' ) ); - $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-prefix' ), - htmlspecialchars( $iwPrefix['iw_prefix'] ) ); - $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-url' ), $iwPrefix['iw_url'] ); - $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-local' ), - ( isset( $iwPrefix['iw_local'] ) ? $this->msg( 'interwiki_' . $iwPrefix['iw_local'] ) : '-' ) ); - $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-trans' ), - ( isset( $iwPrefix['iw_trans'] ) ? $this->msg( 'interwiki_' . $iwPrefix['iw_trans'] ) : '-' ) ); - if ( $canModify ) { - $out .= Html::rawElement( 'td', array( 'class' => 'mw-interwikitable-modify' ), - Linker::linkKnown( $selfTitle, $this->msg( 'edit' )->escaped(), array(), - array( 'action' => 'edit', 'prefix' => $iwPrefix['iw_prefix'] ) ) . - $this->msg( 'comma-separator' ) . - Linker::linkKnown( $selfTitle, $this->msg( 'delete' )->escaped(), array(), - array( 'action' => 'delete', 'prefix' => $iwPrefix['iw_prefix'] ) ) - ); + // ShoutWiki patch begin + // I did, however, reindent the code below the if() by one level + if( !$wgContLang->getLanguageName( $iwPrefix['iw_prefix'] ) ) { + // ShoutWiki patch end + $out .= Html::openElement( 'tr', array( 'class' => 'mw-interwikitable-row' ) ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-prefix' ), + htmlspecialchars( $iwPrefix['iw_prefix'] ) ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-url' ), $iwPrefix['iw_url'] ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-local' ), + ( isset( $iwPrefix['iw_local'] ) ? $this->msg( 'interwiki_' . $iwPrefix['iw_local'] ) : '-' ) ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-trans' ), + ( isset( $iwPrefix['iw_trans'] ) ? $this->msg( 'interwiki_' . $iwPrefix['iw_trans'] ) : '-' ) ); + if ( $canModify ) { + $out .= Html::rawElement( 'td', array( 'class' => 'mw-interwikitable-modify' ), + Linker::linkKnown( $selfTitle, $this->msg( 'edit' )->escaped(), array(), + array( 'action' => 'edit', 'prefix' => $iwPrefix['iw_prefix'] ) ) . + $this->msg( 'comma-separator' ) . + Linker::linkKnown( $selfTitle, $this->msg( 'delete' )->escaped(), array(), + array( 'action' => 'delete', 'prefix' => $iwPrefix['iw_prefix'] ) ) + ); + } + $out .= Html::closeElement( 'tr' ) . "\n"; + // ShoutWiki patch begin } - $out .= Html::closeElement( 'tr' ) . "\n"; + // ShoutWiki patch end } $out .= Html::closeElement( 'table' ); + // ShoutWiki patch begin + // Build the list of local interlanguage prefixes + $dbr = wfGetDB( DB_SLAVE ); + $res = $dbr->select( 'interwiki', '*', false, __METHOD__ ); + $retval = array(); + foreach ( $res as $row ) { + $retval[] = (array)$row; + } + $interlanguagePrefixes = $retval; + $numRows = $res->numRows(); + + $out .= '<h2>' . wfMsgHtml( 'interwiki-local-interlanguage' ) . '</h2>'; + if ( $numRows == 0 ) { + // We can't use $this->error() here or else the red, scary error msg will be misplaced...sigh + $out .= '<p class="error">' . wfMsgHtml( 'interwiki-languagelinks-empty' ) . '</p>'; + } else { + // There is data in local interwiki table, we can safely open the table and fetch stuff + # Output the table header + $out .= Html::openElement( 'table', array( 'class' => 'mw-interwikitable wikitable sortable body shoutwiki-global-interwikis' ) ) . "\n"; + $out .= Html::openElement( 'tr', array( 'id' => 'interwikitable-header' ) ) . + Html::element( 'th', null, $this->msg( 'interwiki_prefix' ) ) . + Html::element( 'th', null, $this->msg( 'interwiki_url' ) ) . + Html::element( 'th', null, $this->msg( 'interwiki_local' ) ) . + Html::element( 'th', null, $this->msg( 'interwiki_trans' ) ) . + ( $canModify ? Html::element( 'th', array( 'class' => 'unsortable' ), $this->msg( 'interwiki_edit' ) ) : '' ); + $out .= Html::closeElement( 'tr' ) . "\n"; + + $selfTitle = $this->getTitle(); + + foreach ( $interlanguagePrefixes as $i => $iwPrefix ) { + // Only show stuff that are actually languages (i.e. don't duplicate IW list on hubwiki) + if( $wgContLang->getLanguageName( $iwPrefix['iw_prefix'] ) ) { + $out .= Html::openElement( 'tr', array( 'class' => 'mw-interwikitable-row' ) ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-prefix' ), + htmlspecialchars( $iwPrefix['iw_prefix'] ) ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-url' ), $iwPrefix['iw_url'] ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-local' ), + ( isset( $iwPrefix['iw_local'] ) ? $this->msg( 'interwiki_' . $iwPrefix['iw_local'] ) : '-' ) ); + $out .= Html::element( 'td', array( 'class' => 'mw-interwikitable-trans' ), + ( isset( $iwPrefix['iw_trans'] ) ? $this->msg( 'interwiki_' . $iwPrefix['iw_trans'] ) : '-' ) ); + if ( $canModify ) { + $out .= Html::rawElement( 'td', array( 'class' => 'mw-interwikitable-modify' ), + Linker::linkKnown( $selfTitle, $this->msg( 'edit' )->escaped(), array(), + array( 'action' => 'edit', 'prefix' => $iwPrefix['iw_prefix'] ) ) . + $this->msg( 'comma-separator' ) . + Linker::linkKnown( $selfTitle, $this->msg( 'delete' )->escaped(), array(), + array( 'action' => 'delete', 'prefix' => $iwPrefix['iw_prefix'] ) ) + ); + } + $out .= Html::closeElement( 'tr' ) . "\n"; + } // if $wgContLang->get... + } // foreach + $out .= Html::closeElement( 'table' ); + } + // ShoutWiki patch end + $this->getOutput()->addHTML( $out ); }
extensions/Interwiki/Interwiki.i18n.php [edit]
Index: Interwiki.i18n.php =================================================================== --- Interwiki.i18n.php (revision 83612) +++ Interwiki.i18n.php (working copy) @@ -92,6 +92,10 @@ # rights 'right-interwiki' => 'Edit interwiki data', 'action-interwiki' => 'change this interwiki entry', + // ShoutWiki + 'interwiki-global-header' => 'List of global interwiki prefixes', + 'interwiki-local-interlanguage' => 'List of local interlanguage prefixes', + 'interwiki-languagelinks-empty' => 'No local interlanguage prefixes defined.', // @todo FIXME: should be more descriptive. ); /** Message documentation (Message documentation)