},
"requires": {
"type": "object",
- "description": "Indicates what versions of MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
+ "description": "Indicates what versions of PHP, MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
"additionalProperties": false,
"properties": {
"MediaWiki": {
"type": "string",
"description": "Version constraint string against MediaWiki core."
},
+ "platform": {
+ "type": "object",
+ "description": "Indicates version constraints against platform services.",
+ "additionalProperties": false,
+ "properties": {
+ "php": {
+ "type": "string",
+ "description": "Version constraint string against PHP."
+ }
+ }
+ },
"extensions": {
"type": "object",
"description": "Set of version constraint strings against specific extensions."
},
"requires": {
"type": "object",
- "description": "Indicates what versions of MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
+ "description": "Indicates what versions of PHP, MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
"additionalProperties": false,
"properties": {
"MediaWiki": {
"type": "string",
"description": "Version constraint string against MediaWiki core."
},
+ "platform": {
+ "type": "object",
+ "description": "Indicates version constraints against platform services.",
+ "additionalProperties": false,
+ "properties": {
+ "php": {
+ "type": "string",
+ "description": "Version constraint string against PHP."
+ }
+ }
+ },
"extensions": {
"type": "object",
"description": "Set of version constraint strings against specific extensions."
*/
public $incompatibleCore = false;
+ /**
+ * @var bool
+ */
+ public $incompatiblePhp = false;
+
/**
* @param array $errors Each error has a 'msg' and 'type' key at minimum
*/
case 'incompatible-core':
$this->incompatibleCore = true;
break;
+ case 'incompatible-php':
+ $this->incompatiblePhp = true;
+ break;
case 'missing-skins':
$this->missingSkins[] = $info['missing'];
break;
$autoloadNamespaces = [];
$autoloaderPaths = [];
$processor = new ExtensionProcessor();
- $versionChecker = new VersionChecker( $wgVersion );
+ $phpVersion = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
+ $versionChecker = new VersionChecker( $wgVersion, $phpVersion );
$extDependencies = [];
$incompatible = [];
$warnings = false;
*/
private $coreVersion = false;
+ /**
+ * @var Constraint|bool representing PHP version
+ */
+ private $phpVersion = false;
+
/**
* @var array Loaded extensions
*/
/**
* @param string $coreVersion Current version of core
*/
- public function __construct( $coreVersion ) {
+ public function __construct( $coreVersion, $phpVersion ) {
$this->versionParser = new VersionParser();
$this->setCoreVersion( $coreVersion );
+ $this->setPhpVersion( $phpVersion );
}
/**
}
}
+ /**
+ * Set PHP version.
+ *
+ * @param string $phpVersion Current PHP version. Must be well-formed.
+ * @throws UnexpectedValueException
+ */
+ private function setPhpVersion( $phpVersion ) {
+ // normalize to make this throw an exception if the version is invalid
+ $this->phpVersion = new Constraint(
+ '==',
+ $this->versionParser->normalize( $phpVersion )
+ );
+ $this->phpVersion->setPrettyString( $phpVersion );
+ }
+
/**
* Check all given dependencies if they are compatible with the named
* installed extensions in the $credits array.
* {
* 'FooBar' => {
* 'MediaWiki' => '>= 1.25.0',
+ * 'platform': {
+ * 'php': '>= 7.0.0'
+ * },
* 'extensions' => {
* 'FooBaz' => '>= 1.25.0'
* },
foreach ( $dependencies as $dependencyType => $values ) {
switch ( $dependencyType ) {
case ExtensionRegistry::MEDIAWIKI_CORE:
- $mwError = $this->handleMediaWikiDependency( $values, $extension );
+ $mwError = $this->handleDependency(
+ $this->coreVersion,
+ $values,
+ $extension
+ );
if ( $mwError !== false ) {
$errors[] = [
- 'msg' => $mwError,
+ 'msg' =>
+ "{$extension} is not compatible with the current MediaWiki "
+ . "core (version {$this->coreVersion->getPrettyString()}), "
+ . "it requires: $values."
+ ,
'type' => 'incompatible-core',
];
}
break;
+ case 'platform':
+ foreach ( $values as $dependency => $constraint ) {
+ if ( $dependency === 'php' ) {
+ $phpError = $this->handleDependency(
+ $this->phpVersion,
+ $constraint,
+ $extension
+ );
+ if ( $phpError !== false ) {
+ $errors[] = [
+ 'msg' =>
+ "{$extension} is not compatible with the current PHP "
+ . "version {$this->phpVersion->getPrettyString()}), "
+ . "it requires: $constraint."
+ ,
+ 'type' => 'incompatible-php',
+ ];
+ }
+ } else {
+ // add other platform dependencies here
+ throw new UnexpectedValueException( 'Dependency type ' . $dependency .
+ ' unknown in ' . $extension );
+ }
+ }
+ break;
case 'extensions':
case 'skins':
foreach ( $values as $dependency => $constraint ) {
}
/**
- * Handle a dependency to MediaWiki core. It will check, if a MediaWiki version constraint was
- * set with self::setCoreVersion before this call (if not, it will return an empty array) and
- * checks the version constraint given against it.
+ * Handle a simple dependency to MediaWiki core or PHP. See handleMediaWikiDependency and
+ * handlePhpDependency for details.
*
+ * @param Constraint|bool $version The version installed
* @param string $constraint The required version constraint for this dependency
* @param string $checkedExt The Extension, which depends on this dependency
- * @return bool|string false if no error, or a string with the message
+ * @return bool false if no error, true else
*/
- private function handleMediaWikiDependency( $constraint, $checkedExt ) {
- if ( $this->coreVersion === false ) {
- // Couldn't parse the core version, so we can't check anything
+ private function handleDependency( $version, $constraint, $checkedExt ) {
+ if ( $version === false ) {
+ // Couldn't parse the version, so we can't check anything
return false;
}
// if the installed and required version are compatible, return an empty array
if ( $this->versionParser->parseConstraints( $constraint )
- ->matches( $this->coreVersion ) ) {
+ ->matches( $version ) ) {
return false;
}
- // otherwise mark this as incompatible.
- return "{$checkedExt} is not compatible with the current "
- . "MediaWiki core (version {$this->coreVersion->getPrettyString()}), it requires: "
- . "$constraint.";
+
+ return true;
}
/**
$info = self::$default + [
'requires' => [
'MediaWiki' => '>= 1.25.0',
+ 'platform' => [
+ 'php' => '>= 5.5.9'
+ ],
'extensions' => [
'Bar' => '*'
]
use PHPUnit4And6Compat;
/**
- * @dataProvider provideCheck
+ * @dataProvider provideMediaWikiCheck
*/
- public function testCheck( $coreVersion, $constraint, $expected ) {
- $checker = new VersionChecker( $coreVersion );
+ public function testMediaWikiCheck( $coreVersion, $constraint, $expected ) {
+ $checker = new VersionChecker( $coreVersion, '7.0.0' );
$this->assertEquals( $expected, !(bool)$checker->checkArray( [
'FakeExtension' => [
'MediaWiki' => $constraint,
] ) );
}
- public static function provideCheck() {
+ public static function provideMediaWikiCheck() {
return [
// [ $wgVersion, constraint, expected ]
[ '1.25alpha', '>= 1.26', false ],
];
}
+ /**
+ * @dataProvider providePhpValidCheck
+ */
+ public function testPhpValidCheck( $phpVersion, $constraint, $expected ) {
+ $checker = new VersionChecker( '1.0.0', $phpVersion );
+ $this->assertEquals( $expected, !(bool)$checker->checkArray( [
+ 'FakeExtension' => [
+ 'platform' => [
+ 'php' => $constraint,
+ ],
+ ],
+ ] ) );
+ }
+
+ public static function providePhpValidCheck() {
+ return [
+ // [ phpVersion, constraint, expected ]
+ [ '7.0.23', '>= 7.0.0', true ],
+ [ '7.0.23', '^7.1.0', false ],
+ [ '7.0.23', '7.0.23', true ],
+ ];
+ }
+
+ /**
+ * @expectedException UnexpectedValueException
+ */
+ public function testPhpInvalidConstraint() {
+ $checker = new VersionChecker( '1.0.0', '7.0.0' );
+ $checker->checkArray( [
+ 'FakeExtension' => [
+ 'platform' => [
+ 'php' => 'totallyinvalid',
+ ],
+ ],
+ ] );
+ }
+
+ /**
+ * @dataProvider providePhpInvalidVersion
+ * @expectedException UnexpectedValueException
+ */
+ public function testPhpInvalidVersion( $phpVersion ) {
+ $checker = new VersionChecker( '1.0.0', $phpVersion );
+ }
+
+ public static function providePhpInvalidVersion() {
+ return [
+ // [ phpVersion ]
+ [ '7.abc' ],
+ [ '5.a.x' ],
+ ];
+ }
+
/**
* @dataProvider provideType
*/
public function testType( $given, $expected ) {
- $checker = new VersionChecker( '1.0.0' );
+ $checker = new VersionChecker( '1.0.0', '7.0.0' );
$checker->setLoadedExtensionsAndSkins( [
'FakeDependency' => [
'version' => '1.0.0',
* returns any error message.
*/
public function testInvalidConstraint() {
- $checker = new VersionChecker( '1.0.0' );
+ $checker = new VersionChecker( '1.0.0', '7.0.0' );
$checker->setLoadedExtensionsAndSkins( [
'FakeDependency' => [
'version' => 'not really valid',
],
] ) );
- $checker = new VersionChecker( '1.0.0' );
+ $checker = new VersionChecker( '1.0.0', '7.0.0' );
$checker->setLoadedExtensionsAndSkins( [
'FakeDependency' => [
'version' => '1.24.3',
] );
}
- /**
- * T197478
- */
- public function testInvalidDependency() {
- $checker = new VersionChecker( '1.0.0' );
- $this->setExpectedException( UnexpectedValueException::class,
- 'Dependency type skin unknown in FakeExtension' );
- $this->assertEquals( [
+ public function provideInvalidDependency() {
+ return [
[
- 'type' => 'invalid-version',
- 'msg' => 'FakeDependency does not have a valid version string.',
+ [
+ 'FakeExtension' => [
+ 'platform' => [
+ 'undefinedPlatformDependency' => '*',
+ ],
+ ],
+ ],
+ 'undefinedPlatformDependency',
],
- ], $checker->checkArray( [
- 'FakeExtension' => [
- 'skin' => [
- 'FakeSkin' => '*',
+ [
+ [
+ 'FakeExtension' => [
+ 'undefinedDependencyType' => '*',
+ ],
],
+ 'undefinedDependencyType',
],
- ] ) );
+ // T197478
+ [
+ [
+ 'FakeExtension' => [
+ 'skin' => [
+ 'FakeSkin' => '*',
+ ],
+ ],
+ ],
+ 'skin',
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideInvalidDependency
+ */
+ public function testInvalidDependency( $depencency, $type ) {
+ $checker = new VersionChecker( '1.0.0', '7.0.0' );
+ $this->setExpectedException(
+ UnexpectedValueException::class,
+ "Dependency type $type unknown in FakeExtension"
+ );
+ $checker->checkArray( $depencency );
}
}