Allow importing pages as subpage
authorumherirrender <umherirrender_de.wp@web.de>
Wed, 15 Aug 2012 08:07:26 +0000 (10:07 +0200)
committerumherirrender <umherirrender_de.wp@web.de>
Wed, 15 Aug 2012 08:10:46 +0000 (10:10 +0200)
Adding a "root page" input to Special:Import, which is used as prefix
before each imported page. With this option, it is possible to import
pages as subpage of a user or a project page.

On de.wp the import is often done into a low used namespace (100 or 101)
and than moved to the user space. Doing this in one step, makes things
easier.

Change-Id: Id5dbf742295a1bbddd8cb6eaa09fb28051f26613

RELEASE-NOTES-1.20
includes/Import.php
includes/api/ApiBase.php
includes/api/ApiImport.php
includes/specials/SpecialImport.php
languages/messages/MessagesEn.php
languages/messages/MessagesQqq.php

index 6f45cf0..54554c9 100644 (file)
@@ -122,6 +122,7 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki.
   API upload errors due to the file extension blacklist.
 * jsMessage: Redesigned in Vector/Monobook as floating bubble with auto-hide.
 * New hook 'ParserTestGlobals' allows to set globals before running parser tests.
+* Allow importing pages as subpage.
 
 === Bug fixes in 1.20 ===
 * (bug 30245) Use the correct way to construct a log page title.
index 491ec09..11f3795 100644 (file)
@@ -33,7 +33,7 @@
 class WikiImporter {
        private $reader = null;
        private $mLogItemCallback, $mUploadCallback, $mRevisionCallback, $mPageCallback;
-       private $mSiteInfoCallback, $mTargetNamespace, $mPageOutCallback;
+       private $mSiteInfoCallback, $mTargetNamespace, $mTargetRootPage, $mPageOutCallback;
        private $mNoticeCallback, $mDebug;
        private $mImportUploads, $mImageBasePath;
        private $mNoUpdates = false;
@@ -199,6 +199,39 @@ class WikiImporter {
                }
        }
 
+       /**
+        * Set a target root page under which all pages are imported
+        * @param $rootpage
+        * @return status object
+        */
+       public function setTargetRootPage( $rootpage ) {
+               $status = Status::newGood();
+               if( is_null( $rootpage ) ) {
+                       // No rootpage
+                       $this->mTargetRootPage = null;
+               } elseif( $rootpage !== '' ) {
+                       $rootpage = rtrim( $rootpage, '/' ); //avoid double slashes
+                       $title = Title::newFromText( $rootpage, !is_null( $this->mTargetNamespace ) ? $this->mTargetNamespace : NS_MAIN );
+                       if( !$title || $title->isExternal() ) {
+                               $status->fatal( 'import-rootpage-invalid' );
+                       } else {
+                               if( !MWNamespace::hasSubpages( $title->getNamespace() ) ) {
+                                       global $wgContLang;
+
+                                       $displayNSText = $title->getNamespace() == NS_MAIN
+                                               ? wfMessage( 'blanknamespace' )->text()
+                                               : $wgContLang->getNsText( $title->getNamespace() );
+                                       $status->fatal( 'import-rootpage-nosubpage', $displayNSText );
+                               } else {
+                                       // set namespace to 'all', so the namespace check in processTitle() can passed
+                                       $this->setTargetNamespace( null );
+                                       $this->mTargetRootPage = $title->getPrefixedDBKey();
+                               }
+                       }
+               }
+               return $status;
+       }
+
        /**
         * @param $dir
         */
@@ -791,6 +824,9 @@ class WikiImporter {
                        $title = Title::makeTitleSafe( $this->mTargetNamespace,
                                $origTitle->getDBkey() );
                } else {
+                       if( !is_null( $this->mTargetRootPage ) ) {
+                               $workTitle = $this->mTargetRootPage . '/' . $workTitle;
+                       }
                        $title = Title::newFromText( $workTitle );
                }
 
index 59a4ef9..ca9f738 100644 (file)
@@ -1270,6 +1270,8 @@ abstract class ApiBase extends ContextSource {
                'nouserspecified' => array( 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ),
                'noname' => array( 'code' => 'invaliduser', 'info' => "Invalid username \"\$1\"" ),
                'summaryrequired' => array( 'code' => 'summaryrequired', 'info' => 'Summary required' ),
+               'import-rootpage-invalid' => array( 'code' => 'import-rootpage-invalid', 'info' => 'Root page is an invalid title' ),
+               'import-rootpage-nosubpage' => array( 'code' => 'import-rootpage-nosubpage', 'info' => 'Namespace "$1" of the root page does not allow subpages' ),
 
                // API-specific messages
                'readrequired' => array( 'code' => 'readapidenied', 'info' => "You need read permission to use this module" ),
index abd2777..637c1ff 100644 (file)
@@ -68,6 +68,12 @@ class ApiImport extends ApiBase {
                if ( isset( $params['namespace'] ) ) {
                        $importer->setTargetNamespace( $params['namespace'] );
                }
+               if ( isset( $params['rootpage'] ) ) {
+                       $statusRootPage = $importer->setTargetRootPage( $params['rootpage'] );
+                       if( !$statusRootPage->isGood() ) {
+                               $this->dieUsageMsg( $statusRootPage->getErrorsArray() );
+                       }
+               }
                $reporter = new ApiImportReporter(
                        $importer,
                        $isUpload,
@@ -112,7 +118,8 @@ class ApiImport extends ApiBase {
                        'templates' => false,
                        'namespace' => array(
                                ApiBase::PARAM_TYPE => 'namespace'
-                       )
+                       ),
+                       'rootpage' => null,
                );
        }
 
@@ -126,6 +133,7 @@ class ApiImport extends ApiBase {
                        'fullhistory' => 'For interwiki imports: import the full history, not just the current version',
                        'templates' => 'For interwiki imports: import all included templates as well',
                        'namespace' => 'For interwiki imports: import to this namespace',
+                       'rootpage' => 'Import as subpage of this page',
                );
        }
 
@@ -155,6 +163,8 @@ class ApiImport extends ApiBase {
                        array( 'cantimport-upload' ),
                        array( 'import-unknownerror', 'source' ),
                        array( 'import-unknownerror', 'result' ),
+                       array( 'import-rootpage-nosubpage', 'namespace' ),
+                       array( 'import-rootpage-invalid' ),
                ) );
        }
 
index 873c9c6..362fc5c 100644 (file)
@@ -33,6 +33,7 @@ class SpecialImport extends SpecialPage {
 
        private $interwiki = false;
        private $namespace;
+       private $rootpage = '';
        private $frompage = '';
        private $logcomment= false;
        private $history = true;
@@ -100,6 +101,7 @@ class SpecialImport extends SpecialPage {
 
                $this->logcomment = $request->getText( 'log-comment' );
                $this->pageLinkDepth = $wgExportMaxLinkDepth == 0 ? 0 : $request->getIntOrNull( 'pagelink-depth' );
+               $this->rootpage = $request->getText( 'rootpage' );\r
 
                $user = $this->getUser();
                if ( !$user->matchEditToken( $request->getVal( 'editToken' ) ) ) {
@@ -137,12 +139,20 @@ class SpecialImport extends SpecialPage {
                if( !$source->isGood() ) {
                        $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'importfailed', $source->getWikiText() ) );
                } else {
-                       $out->addWikiMsg( "importstart" );
-
                        $importer = new WikiImporter( $source->value );
                        if( !is_null( $this->namespace ) ) {
                                $importer->setTargetNamespace( $this->namespace );
                        }
+                       if( !is_null( $this->rootpage ) ) {
+                               $statusRootPage = $importer->setTargetRootPage( $this->rootpage );
+                               if( !$statusRootPage->isGood() ) {
+                                       $out->wrapWikiMsg( "<p class=\"error\">\n$1\n</p>", array( 'import-options-wrong', $statusRootPage->getWikiText(), count( $statusRootPage->getErrorsArray() ) ) );
+                                       return;
+                               }
+                       }
+
+                       $out->addWikiMsg( "importstart" );
+
                        $reporter = new ImportReporter( $importer, $isUpload, $this->interwiki , $this->logcomment);
                        $reporter->setContext( $this->getContext() );
                        $exception = false;
@@ -203,6 +213,15 @@ class SpecialImport extends SpecialPage {
                                                        array( 'id' => 'mw-import-comment', 'type' => 'text' ) ) . ' ' .
                                        "</td>
                                </tr>
+                               <tr>
+                                       <td class='mw-label'>" .
+                                               Xml::label( $this->msg( 'import-interwiki-rootpage' )->text(), 'mw-interwiki-rootpage' ) .
+                                       "</td>
+                                       <td class='mw-input'>" .
+                                               Xml::input( 'rootpage', 50, $this->rootpage,
+                                                       array( 'id' => 'mw-interwiki-rootpage', 'type' => 'text' ) ) . ' ' .
+                                       "</td>
+                               </tr>
                                <tr>
                                        <td></td>
                                        <td class='mw-submit'>" .
@@ -300,6 +319,15 @@ class SpecialImport extends SpecialPage {
                                                        array( 'id' => 'mw-interwiki-comment', 'type' => 'text' ) ) . ' ' .
                                        "</td>
                                </tr>
+                               <tr>
+                                       <td class='mw-label'>" .
+                                               Xml::label( $this->msg( 'import-interwiki-rootpage' )->text(), 'mw-interwiki-rootpage' ) .
+                                       "</td>
+                                       <td class='mw-input'>" .
+                                               Xml::input( 'rootpage', 50, $this->rootpage,
+                                                       array( 'id' => 'mw-interwiki-rootpage', 'type' => 'text' ) ) . ' ' .
+                                       "</td>
+                               </tr>
                                <tr>
                                        <td>
                                        </td>
index 81b4f23..1857ed8 100644 (file)
@@ -3465,6 +3465,7 @@ All transwiki import actions are logged at the [[Special:Log/import|import log]]
 'import-interwiki-templates' => 'Include all templates',
 'import-interwiki-submit'    => 'Import',
 'import-interwiki-namespace' => 'Destination namespace:',
+'import-interwiki-rootpage'  => 'Destination root page (optional):',
 'import-upload-filename'     => 'Filename:',
 'import-comment'             => 'Comment:',
 'importtext'                 => 'Please export the file from the source wiki using the [[Special:Export|export utility]].
@@ -3501,6 +3502,9 @@ Please try again.',
 'import-error-interwiki'     => 'Page "$1" is not imported because its name is reserved for external linking (interwiki).',
 'import-error-special'       => 'Page "$1" is not imported because it belongs to a special namespace that does not allow pages.',
 'import-error-invalid'       => 'Page "$1" is not imported because its name is invalid.',
+'import-options-wrong'       => 'Wrong {{PLURAL:$2|option|options}}: <nowiki>$1</nowiki>',
+'import-rootpage-invalid'    => 'Given root page is an invalid title.',
+'import-rootpage-nosubpage'  => 'Namespace "$1" of the root page does not allow subpages.',
 
 # Import log
 'importlogpage'                    => 'Import log',
index 25e9d81..3a0f5d9 100644 (file)
@@ -3234,6 +3234,7 @@ Tooltip shown when hovering over a little sign of a thumb image, to go to the im
 'import' => 'The title of the special page [[Special:Import]];',
 'import-interwiki-history' => 'This is an option on [[Special:Import]]. Usually, when unchecked, only the first version of a page is imported. When you check the option, all versions are imported. This is important often to check for licensing reasons.',
 'import-interwiki-submit' => '{{Identical|Import}}',
+'import-interwiki-rootpage' => 'Used on [[Special:Import]] as label',
 'import-upload-filename' => 'Used on [[Special:Import]] as label for upload of an XML file containing the pages to import.',
 'xml-error-string' => ':$1: Some kind of message, perhaps name of the error?
 :$2: line number
@@ -3254,6 +3255,9 @@ See also:
 * $1 is a page name.
 See also:
 * {{msg-mw|import-error-edit}}',
+'import-options-wrong' => 'Used on [[Special:Import]], when one of the options has an error.',
+'import-rootpage-invalid' => 'Used on [[Special:Import]], when the root page is invalid.',
+'import-rootpage-nosubpage' => 'Used on [[Special:Import]], when the import namespace does not support subpages.',
 
 # Import log
 'importlogpage' => '{{doc-logpage}}',