'CopyJobQueue' => __DIR__ . '/maintenance/copyJobQueue.php',
'CoreParserFunctions' => __DIR__ . '/includes/parser/CoreParserFunctions.php',
'CoreTagHooks' => __DIR__ . '/includes/parser/CoreTagHooks.php',
+ 'CoreVersionChecker' => __DIR__ . '/includes/registration/CoreVersionChecker.php',
'CreateAndPromote' => __DIR__ . '/maintenance/createAndPromote.php',
'CreateFileOp' => __DIR__ . '/includes/filebackend/FileOp.php',
'CreditsAction' => __DIR__ . '/includes/actions/CreditsAction.php',
"wiki": "https://www.mediawiki.org/"
},
"require": {
+ "composer/semver": "0.1.0",
"cssjanus/cssjanus": "1.1.1",
"ext-iconv": "*",
"leafo/lessphp": "0.5.0",
"Unlicense"
]
},
+ "requires": {
+ "type": "object",
+ "description": "Indicates what versions of MediaWiki core are required. This syntax may be extended in the future, for example to check dependencies between other extensions.",
+ "properties": {
+ "MediaWiki": {
+ "type": "string",
+ "description": "Version constraint string against MediaWiki core."
+ }
+ }
+ },
"ResourceFileModulePaths": {
"type": "object",
"description": "Default paths to use for all ResourceLoader file modules",
*
* @see perldoc -f use
*
+ * @deprecated since 1.26, use the "requires' property of extension.json
* @param string|int|float $req_ver The version to check, can be a string, an integer, or a float
* @throws MWException
*/
--- /dev/null
+<?php
+
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+use Composer\Semver\VersionParser;
+use Composer\Semver\Constraint\VersionConstraint;
+
+/**
+ * @since 1.26
+ */
+class CoreVersionChecker {
+
+ /**
+ * @var VersionConstraint|bool representing $wgVersion
+ */
+ private $coreVersion = false;
+
+ /**
+ * @var VersionParser
+ */
+ private $versionParser;
+
+ /**
+ * @param string $coreVersion Current version of core
+ */
+ public function __construct( $coreVersion ) {
+ $this->versionParser = new VersionParser();
+ try {
+ $this->coreVersion = new VersionConstraint(
+ '==',
+ $this->versionParser->normalize( $coreVersion )
+ );
+ } catch ( UnexpectedValueException $e ) {
+ // Non-parsable version, don't fatal.
+ }
+ }
+
+ /**
+ * Check that the provided constraint is compatible with the current version of core
+ *
+ * @param string $constraint Something like ">= 1.26"
+ * @return bool
+ */
+ public function check( $constraint ) {
+ if ( $this->coreVersion === false ) {
+ // Couldn't parse the core version, so we can't check anything
+ return true;
+ }
+
+ return $this->versionParser->parseConstraints( $constraint )
+ ->matches( $this->coreVersion );
+ }
+}
);
}
+ public function getRequirements( array $info ) {
+ $requirements = array();
+ $key = ExtensionRegistry::MEDIAWIKI_CORE;
+ if ( isset( $info['requires'][$key] ) ) {
+ $requirements[$key] = $info['requires'][$key];
+ }
+
+ return $requirements;
+ }
+
protected function extractHooks( array $info ) {
if ( isset( $info['Hooks'] ) ) {
foreach ( $info['Hooks'] as $name => $value ) {
*/
class ExtensionRegistry {
+ /**
+ * "requires" key that applies to MediaWiki core/$wgVersion
+ */
+ const MEDIAWIKI_CORE = 'MediaWiki';
+
/**
* Version of the highest supported manifest version
*/
* @throws Exception
*/
public function readFromQueue( array $queue ) {
+ global $wgVersion;
$autoloadClasses = array();
$processor = new ExtensionProcessor();
+ $incompatible = array();
+ $coreVersionParser = new CoreVersionChecker( $wgVersion );
foreach ( $queue as $path => $mtime ) {
$json = file_get_contents( $path );
if ( $json === false ) {
// Set up the autoloader now so custom processors will work
$GLOBALS['wgAutoloadClasses'] += $autoload;
$autoloadClasses += $autoload;
+ // Check any constraints against MediaWiki core
+ $requires = $processor->getRequirements( $info );
+ if ( isset( $requires[self::MEDIAWIKI_CORE] )
+ && !$coreVersionParser->check( $requires[self::MEDIAWIKI_CORE] )
+ ) {
+ // Doesn't match, mark it as incompatible.
+ $incompatible[] = "{$info['name']} is not compatible with the current "
+ . "MediaWiki core (version {$wgVersion}), it requires: ". $requires[self::MEDIAWIKI_CORE]
+ . '.';
+ continue;
+ }
+ // Compatible, read and extract info
$processor->extractInfo( $path, $info, $version );
}
+ if ( $incompatible ) {
+ if ( count( $incompatible ) === 1 ) {
+ throw new Exception( $incompatible[0] );
+ } else {
+ throw new Exception( implode( "\n", $incompatible ) );
+ }
+ }
$data = $processor->getExtractedInfo();
// Need to set this so we can += to it later
$data['globals']['wgAutoloadClasses'] = array();
* 'attributes' - registration info which isn't a global variable
*/
public function getExtractedInfo();
+
+ /**
+ * Get the requirements for the provided info
+ *
+ * @since 1.26
+ * @param array $info
+ * @return array Where keys are the name to have a constraint on,
+ * like 'MediaWiki'. Values are a constraint string like "1.26.1".
+ */
+ public function getRequirements( array $info );
}
--- /dev/null
+<?php
+
+/**
+ * @covers CoreVersionChecker
+ */
+class CoreVersionCheckerTest extends PHPUnit_Framework_TestCase {
+ /**
+ * @dataProvider provideCheck
+ */
+ public function testCheck( $coreVersion, $constraint, $expected ) {
+ $checker = new CoreVersionChecker( $coreVersion );
+ $this->assertEquals( $expected, $checker->check( $constraint ) );
+ }
+
+ public static function provideCheck() {
+ return array(
+ // array( $wgVersion, constraint, expected )
+ array( '1.25alpha', '>= 1.26', false ),
+ array( '1.25.0', '>= 1.26', false ),
+ array( '1.26alpha', '>= 1.26', true ),
+ array( '1.26alpha', '>= 1.26.0', true ),
+ array( '1.26alpha', '>= 1.26.0-stable', false ),
+ array( '1.26.0', '>= 1.26.0-stable', true ),
+ array( '1.26.1', '>= 1.26.0-stable', true ),
+ array( '1.27.1', '>= 1.26.0-stable', true ),
+ array( '1.26alpha', '>= 1.26.1', false ),
+ array( '1.26alpha', '>= 1.26alpha', true ),
+ array( '1.26alpha', '>= 1.25', true ),
+ array( '1.26.0-alpha.14', '>= 1.26.0-alpha.15', false ),
+ array( '1.26.0-alpha.14', '>= 1.26.0-alpha.10', true ),
+ array( '1.26.1', '>= 1.26.2, <=1.26.0', false ),
+ array( '1.26.1', '^1.26.2', false ),
+ // Accept anything for un-parsable version strings
+ array( '1.26mwf14', '== 1.25alpha', true ),
+ array( 'totallyinvalid', '== 1.0', true ),
+ );
+ }
+}