From: This, that and the other Date: Wed, 23 Sep 2015 07:54:31 +0000 (+1000) Subject: Add hook to allow lazy loading of import sources X-Git-Tag: 1.31.0-rc.0~9893^2 X-Git-Url: https://git.cyclocoop.org/%28%28?a=commitdiff_plain;h=d3b85592ead7fc1348c20c565fd21375da5417de;p=lhc%2Fweb%2Fwiklou.git Add hook to allow lazy loading of import sources Currently import sources have to be set into $wgImportSources as part of wiki startup. This is not practical for the WMF cluster, where we need some reasonably complex logic to set up the import source structure. This change allows the import source list to be populated from a new "ImportSources" hook. This hook is only called when the list of import sources is actually needed (namely, when a user with relevant permissions loads Special:Import). Bug: T17583 Change-Id: Ice9a19cb6dfe53ae72aa71353d0553ee9338f233 --- diff --git a/docs/hooks.txt b/docs/hooks.txt index 65ae988426..ab8dbedff8 100644 --- a/docs/hooks.txt +++ b/docs/hooks.txt @@ -1628,6 +1628,11 @@ Return false to stop further processing of the tag $reader: XMLReader object $revisionInfo: Array of information +'ImportSources': Called when reading from the $wgImportSources configuration +variable. Can be used to lazy-load the import sources list. +&$importSources: The value of $wgImportSources. Modify as necessary. See the +comment in DefaultSettings.php for the detail of how to structure this array. + 'InfoAction': When building information to display on the action=info page. $context: IContextSource object &$pageInfo: Array of information diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 19d4b89dfb..c15c0901f0 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -6369,8 +6369,8 @@ $wgShowCreditsIfMax = true; /** * List of interwiki prefixes for wikis we'll accept as sources for - * Special:Import (for sysops). Since complete page history can be imported, - * these should be 'trusted'. + * Special:Import and API action=import. Since complete page history can be + * imported, these should be 'trusted'. * * This can either be a regular array, or an associative map specifying * subprojects on the interwiki map of the target wiki, or a mix of the two, @@ -6383,6 +6383,9 @@ $wgShowCreditsIfMax = true; * ); * @endcode * + * If you have a very complex import sources setup, you can lazy-load it using + * the ImportSources hook. + * * If a user has the 'import' permission but not the 'importupload' permission, * they will only be able to run imports through this transwiki interface. */ diff --git a/includes/api/ApiImport.php b/includes/api/ApiImport.php index 41540836ef..f4f56d0d0d 100644 --- a/includes/api/ApiImport.php +++ b/includes/api/ApiImport.php @@ -90,6 +90,30 @@ class ApiImport extends ApiBase { $result->addValue( null, $this->getModuleName(), $resultData ); } + /** + * Returns a list of interwiki prefixes corresponding to each defined import + * source. + * + * @return array + * @since 1.26 + */ + public function getAllowedImportSources() { + $importSources = $this->getConfig()->get( 'ImportSources' ); + Hooks::run( 'ImportSources', array( &$importSources ) ); + + $result = array(); + foreach ( $importSources as $key => $value ) { + if ( is_int( $key ) ) { + $result[] = $value; + } else { + foreach ( $value as $subproject ) { + $result[] = "$key:$subproject"; + } + } + } + return $result; + } + public function mustBePosted() { return true; } @@ -105,7 +129,7 @@ class ApiImport extends ApiBase { ApiBase::PARAM_TYPE => 'upload', ), 'interwikisource' => array( - ApiBase::PARAM_TYPE => $this->getConfig()->get( 'ImportSources' ), + ApiBase::PARAM_TYPE => $this->getAllowedImportSources(), ), 'interwikipage' => null, 'fullhistory' => false, diff --git a/includes/specials/SpecialImport.php b/includes/specials/SpecialImport.php index f9b8ac3be4..28ae05d00b 100644 --- a/includes/specials/SpecialImport.php +++ b/includes/specials/SpecialImport.php @@ -42,6 +42,7 @@ class SpecialImport extends SpecialPage { private $history = true; private $includeTemplates = false; private $pageLinkDepth; + private $importSources; /** * Constructor @@ -64,6 +65,9 @@ class SpecialImport extends SpecialPage { $this->getOutput()->addModules( 'mediawiki.special.import' ); + $this->importSources = $this->getConfig()->get( 'ImportSources' ); + Hooks::run( 'ImportSources', array( &$this->importSources ) ); + $user = $this->getUser(); if ( !$user->isAllowedAny( 'import', 'importupload' ) ) { throw new PermissionsError( 'import' ); @@ -134,16 +138,17 @@ class SpecialImport extends SpecialPage { } $this->interwiki = $this->fullInterwikiPrefix = $request->getVal( 'interwiki' ); // does this interwiki have subprojects? - $importSources = $this->getConfig()->get( 'ImportSources' ); - $hasSubprojects = array_key_exists( $this->interwiki, $importSources ); - if ( !$hasSubprojects && !in_array( $this->interwiki, $importSources ) ) { + $hasSubprojects = array_key_exists( $this->interwiki, $this->importSources ); + if ( !$hasSubprojects && !in_array( $this->interwiki, $this->importSources ) ) { $source = Status::newFatal( "import-invalid-interwiki" ); } else { if ( $hasSubprojects ) { $this->subproject = $request->getVal( 'subproject' ); $this->fullInterwikiPrefix .= ':' . $request->getVal( 'subproject' ); } - if ( $hasSubprojects && !in_array( $this->subproject, $importSources[$this->interwiki] ) ) { + if ( $hasSubprojects && + !in_array( $this->subproject, $this->importSources[$this->interwiki] ) + ) { $source = Status::newFatal( "import-invalid-interwiki" ); } else { $this->history = $request->getCheck( 'interwikiHistory' ); @@ -304,7 +309,6 @@ class SpecialImport extends SpecialPage { $user = $this->getUser(); $out = $this->getOutput(); $this->addHelpLink( '//meta.wikimedia.org/wiki/Special:MyLanguage/Help:Import', true ); - $importSources = $this->getConfig()->get( 'ImportSources' ); if ( $user->isAllowed( 'importupload' ) ) { $mappingSelection = $this->getMappingFormPart( 'upload' ); @@ -354,12 +358,12 @@ class SpecialImport extends SpecialPage { Xml::closeElement( 'fieldset' ) ); } else { - if ( empty( $importSources ) ) { + if ( empty( $this->importSources ) ) { $out->addWikiMsg( 'importnosources' ); } } - if ( $user->isAllowed( 'import' ) && !empty( $importSources ) ) { + if ( $user->isAllowed( 'import' ) && !empty( $this->importSources ) ) { # Show input field for import depth only if $wgExportMaxLinkDepth > 0 $importDepth = ''; if ( $this->getConfig()->get( 'ExportMaxLinkDepth' ) > 0 ) { @@ -401,7 +405,7 @@ class SpecialImport extends SpecialPage { ); $needSubprojectField = false; - foreach ( $importSources as $key => $value ) { + foreach ( $this->importSources as $key => $value ) { if ( is_int( $key ) ) { $key = $value; } elseif ( $value !== $key ) { @@ -433,7 +437,7 @@ class SpecialImport extends SpecialPage { ); $subprojectsToAdd = array(); - foreach ( $importSources as $key => $value ) { + foreach ( $this->importSources as $key => $value ) { if ( is_array( $value ) ) { $subprojectsToAdd = array_merge( $subprojectsToAdd, $value ); }