jenkins-bot has submitted this change and it was merged.

Change subject: registration: Allow extensions to specify which MW core 
versions they require
......................................................................


registration: Allow extensions to specify which MW core versions they require

This adds a "requires" property to extension.json, which extensions and
skins can use to indicate which versions of MediaWiki core they support.
The hacky wfUseMW() is now deprecated in favor of this.

Rather than writing our own version constraint and parser library, we
can re-use composer's, which was recently split out into a separate
library named "composer/semver" for this patch.

Any syntax accepted by composer[1] is available for usage here. Test
cases have been provided to demonstrate how versions are parsed. For now
it is recommended that people stick to expressing compatability with
stable versions (e.g. ">= 1.26").

This patch does not support requiring specific MediaWiki core WMF
branches, since those do not follow the standard semver format that
composer parses. If we are unable to parse $wgVersion, all checking will
be skipped and reported as compatible.

[1] https://getcomposer.org/doc/01-basic-usage.md#package-versions

Bug: T99084
Change-Id: I7785827216e16c596356d0ae42d6b30f3f179f10
---
M autoload.php
M composer.json
M docs/extension.schema.json
M includes/GlobalFunctions.php
A includes/registration/CoreVersionChecker.php
M includes/registration/ExtensionProcessor.php
M includes/registration/ExtensionRegistry.php
M includes/registration/Processor.php
A tests/phpunit/includes/registration/CoreVersionCheckerTest.php
9 files changed, 166 insertions(+), 0 deletions(-)

Approvals:
  Parent5446: Looks good to me, approved
  Jforrester: Looks good to me, but someone else must approve
  Florianschmidtwelzow: Looks good to me, but someone else must approve
  jenkins-bot: Verified



diff --git a/autoload.php b/autoload.php
index 82a45b4..b97e190 100644
--- a/autoload.php
+++ b/autoload.php
@@ -273,6 +273,7 @@
        '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',
diff --git a/composer.json b/composer.json
index 852f2d2..adfe01b 100644
--- a/composer.json
+++ b/composer.json
@@ -16,6 +16,7 @@
                "wiki": "https://www.mediawiki.org/";
        },
        "require": {
+               "composer/semver": "0.1.0",
                "cssjanus/cssjanus": "1.1.1",
                "ext-iconv": "*",
                "leafo/lessphp": "0.5.0",
diff --git a/docs/extension.schema.json b/docs/extension.schema.json
index 1d78ecc..ece38fe 100644
--- a/docs/extension.schema.json
+++ b/docs/extension.schema.json
@@ -270,6 +270,16 @@
                                "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",
diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php
index 9d89633..5e8b2c3 100644
--- a/includes/GlobalFunctions.php
+++ b/includes/GlobalFunctions.php
@@ -3202,6 +3202,7 @@
  *
  * @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
  */
diff --git a/includes/registration/CoreVersionChecker.php 
b/includes/registration/CoreVersionChecker.php
new file mode 100644
index 0000000..a7a926c
--- /dev/null
+++ b/includes/registration/CoreVersionChecker.php
@@ -0,0 +1,68 @@
+<?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 );
+       }
+}
diff --git a/includes/registration/ExtensionProcessor.php 
b/includes/registration/ExtensionProcessor.php
index dc35347..1ceded1 100644
--- a/includes/registration/ExtensionProcessor.php
+++ b/includes/registration/ExtensionProcessor.php
@@ -192,6 +192,16 @@
                );
        }
 
+       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 ) {
diff --git a/includes/registration/ExtensionRegistry.php 
b/includes/registration/ExtensionRegistry.php
index b89518a..63bee07 100644
--- a/includes/registration/ExtensionRegistry.php
+++ b/includes/registration/ExtensionRegistry.php
@@ -12,6 +12,11 @@
 class ExtensionRegistry {
 
        /**
+        * "requires" key that applies to MediaWiki core/$wgVersion
+        */
+       const MEDIAWIKI_CORE = 'MediaWiki';
+
+       /**
         * Version of the highest supported manifest version
         */
        const MANIFEST_VERSION = 1;
@@ -156,8 +161,11 @@
         * @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 ) {
@@ -179,8 +187,27 @@
                        // 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();
diff --git a/includes/registration/Processor.php 
b/includes/registration/Processor.php
index e1aaca7..e5669d2 100644
--- a/includes/registration/Processor.php
+++ b/includes/registration/Processor.php
@@ -30,4 +30,14 @@
         *              '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 );
 }
diff --git a/tests/phpunit/includes/registration/CoreVersionCheckerTest.php 
b/tests/phpunit/includes/registration/CoreVersionCheckerTest.php
new file mode 100644
index 0000000..bc154b3
--- /dev/null
+++ b/tests/phpunit/includes/registration/CoreVersionCheckerTest.php
@@ -0,0 +1,38 @@
+<?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 ),
+               );
+       }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/210856
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I7785827216e16c596356d0ae42d6b30f3f179f10
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Legoktm <legoktm.wikipe...@gmail.com>
Gerrit-Reviewer: BryanDavis <bda...@wikimedia.org>
Gerrit-Reviewer: Daniel Friesen <dan...@nadir-seen-fire.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com>
Gerrit-Reviewer: GWicke <gwi...@wikimedia.org>
Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org>
Gerrit-Reviewer: Krinkle <krinklem...@gmail.com>
Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com>
Gerrit-Reviewer: Mattflaschen <mflasc...@wikimedia.org>
Gerrit-Reviewer: Ori.livneh <o...@wikimedia.org>
Gerrit-Reviewer: Paladox <thomasmulhall...@yahoo.com>
Gerrit-Reviewer: Parent5446 <tylerro...@gmail.com>
Gerrit-Reviewer: Tim Starling <tstarl...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to