Use interwiki cache directly to resolve transwiki import sources
authorThis, that and the other <at.light@live.com.au>
Wed, 4 Nov 2015 23:42:14 +0000 (10:42 +1100)
committerThis, that and the other <at.light@live.com.au>
Wed, 4 Nov 2015 23:42:14 +0000 (10:42 +1100)
In order to resolve T17583, we will need to have a WMF-wide map of import
sources. This will most likely consist of a project dropdown, e.g.
"wikipedia", "wiktionary", "meta"... and a subproject dropdown, listing
each language edition of the selected project.

This would mean, if we wanted to import a page from French Wikipedia to
English Wikipedia, we would need to select project "wikipedia" and language
"fr". Currently, this causes the error "Bad interwiki link", because the
prefix "wikipedia:" maps to the local project namespace on enwiki, instead
of the relevant interwiki prefix.

To avoid this error we need to bypass Title and directly query the
interwiki map.

Change-Id: I68989203e367e7ea515e4ae2222c330b264a7cb1

includes/Import.php

index 6a0bfd0..efb37ae 100644 (file)
@@ -1940,23 +1940,38 @@ class ImportStreamSource implements ImportSource {
                if ( $page == '' ) {
                        return Status::newFatal( 'import-noarticle' );
                }
-               $link = Title::newFromText( "$interwiki:Special:Export/$page" );
-               if ( is_null( $link ) || !$link->isExternal() ) {
+
+               # Look up the first interwiki prefix, and let the foreign site handle
+               # subsequent interwiki prefixes
+               $firstIwPrefix = strtok( $interwiki, ':' );
+               $firstIw = Interwiki::fetch( $firstIwPrefix );
+               if ( !$firstIw ) {
                        return Status::newFatal( 'importbadinterwiki' );
-               } else {
-                       $params = array();
-                       if ( $history ) {
-                               $params['history'] = 1;
-                       }
-                       if ( $templates ) {
-                               $params['templates'] = 1;
-                       }
-                       if ( $pageLinkDepth ) {
-                               $params['pagelink-depth'] = $pageLinkDepth;
-                       }
-                       $url = $link->getFullURL( $params );
-                       # For interwikis, use POST to avoid redirects.
-                       return ImportStreamSource::newFromURL( $url, "POST" );
                }
+
+               $additionalIwPrefixes = strtok( '' );
+               if ( $additionalIwPrefixes ) {
+                       $additionalIwPrefixes .= ':';
+               }
+               # Have to do a DB-key replacement ourselves; otherwise spaces get
+               # URL-encoded to +, which is wrong in this case. Similar to logic in
+               # Title::getLocalURL
+               $link = $firstIw->getURL( strtr( "${additionalIwPrefixes}Special:Export/$page",
+                       ' ', '_' ) );
+
+               $params = array();
+               if ( $history ) {
+                       $params['history'] = 1;
+               }
+               if ( $templates ) {
+                       $params['templates'] = 1;
+               }
+               if ( $pageLinkDepth ) {
+                       $params['pagelink-depth'] = $pageLinkDepth;
+               }
+
+               $url = wfAppendQuery( $link, $params );
+               # For interwikis, use POST to avoid redirects.
+               return ImportStreamSource::newFromURL( $url, "POST" );
        }
 }