registration: Add ability to check if a specific extension version is loaded
authorMGChecker <hgasuser@gmail.com>
Tue, 28 Aug 2018 02:39:16 +0000 (04:39 +0200)
committerKunal Mehta <legoktm@member.fsf.org>
Mon, 3 Sep 2018 21:37:33 +0000 (14:37 -0700)
As it's quite common that extensions and skins interact with each other, it's
useful to have a simple way to check if an extension version satisfies a
given constraint, as extensions change over time.

Bug: T202955
Change-Id: I19f9713caf89d647072a2bd7d598e739be383f4a

includes/registration/ExtensionRegistry.php
tests/phpunit/data/registration/good_with_version.json [new file with mode: 0644]
tests/phpunit/includes/registration/ExtensionRegistryTest.php

index d21ae41..8429afa 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Composer\Semver\Semver;
+
 /**
  * ExtensionRegistry class
  *
@@ -381,10 +383,24 @@ class ExtensionRegistry {
        /**
         * Whether a thing has been loaded
         * @param string $name
+        * @param string $constraint The required version constraint for this dependency
+        * @throws LogicException if a specific contraint is asked for,
+        *                        but the extension isn't versioned
         * @return bool
         */
-       public function isLoaded( $name ) {
-               return isset( $this->loaded[$name] );
+       public function isLoaded( $name, $constraint = '*' ) {
+               $isLoaded = isset( $this->loaded[$name] );
+               if ( $constraint === '*' || !$isLoaded ) {
+                       return $isLoaded;
+               }
+               // if a specific constraint is requested, but no version is set, throw an exception
+               if ( !isset( $this->loaded[$name]['version'] ) ) {
+                       $msg = "{$name} does not expose its version, but an extension or a skin"
+                                       . " requires: {$constraint}.";
+                       throw new LogicException( $msg );
+               }
+
+               return SemVer::satisfies( $this->loaded[$name]['version'], $constraint );
        }
 
        /**
diff --git a/tests/phpunit/data/registration/good_with_version.json b/tests/phpunit/data/registration/good_with_version.json
new file mode 100644 (file)
index 0000000..586ba7c
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "name": "FooBar",
+       "version": "1.2.3",
+       "attributes": {
+               "FooBar": {
+                       "Attr": [ "test" ]
+               },
+               "NotLoaded": {
+                       "Attr": [ "test2" ]
+               }
+       },
+       "manifest_version": 2
+}
index 7120a91..1baa79c 100644 (file)
@@ -57,10 +57,29 @@ class ExtensionRegistryTest extends MediaWikiTestCase {
                $registry->loadFromQueue();
                $this->assertArrayHasKey( 'FooBar', $registry->getAllThings() );
                $this->assertTrue( $registry->isLoaded( 'FooBar' ) );
+               $this->assertTrue( $registry->isLoaded( 'FooBar', '*' ) );
                $this->assertSame( [ 'test' ], $registry->getAttribute( 'FooBarAttr' ) );
                $this->assertSame( [], $registry->getAttribute( 'NotLoadedAttr' ) );
        }
 
+       public function testLoadFromQueueWithConstraintWithVersion() {
+               $registry = new ExtensionRegistry();
+               $registry->queue( "{$this->dataDir}/good_with_version.json" );
+               $registry->loadFromQueue();
+               $this->assertTrue( $registry->isLoaded( 'FooBar', '>= 1.2.0' ) );
+               $this->assertFalse( $registry->isLoaded( 'FooBar', '^1.3.0' ) );
+       }
+
+       /**
+        * @expectedException LogicException
+        */
+       public function testLoadFromQueueWithConstraintWithoutVersion() {
+               $registry = new ExtensionRegistry();
+               $registry->queue( "{$this->dataDir}/good.json" );
+               $registry->loadFromQueue();
+               $registry->isLoaded( 'FooBar', '>= 1.2.0' );
+       }
+
        /**
         * @expectedException PHPUnit_Framework_Error
         */