2016-12-03 18:06:46 +00:00
|
|
|
<?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
|
|
|
|
|
*
|
2023-03-25 02:11:36 +00:00
|
|
|
* @file
|
2016-12-03 18:06:46 +00:00
|
|
|
*/
|
|
|
|
|
|
2024-08-10 05:17:59 +00:00
|
|
|
namespace MediaWiki\Registration;
|
|
|
|
|
|
2016-12-03 18:06:46 +00:00
|
|
|
use Composer\Semver\Constraint\Constraint;
|
2020-01-10 00:00:51 +00:00
|
|
|
use Composer\Semver\VersionParser;
|
2024-08-10 05:17:59 +00:00
|
|
|
use UnexpectedValueException;
|
2016-12-03 18:06:46 +00:00
|
|
|
|
|
|
|
|
/**
|
2023-03-25 02:11:36 +00:00
|
|
|
* Check whether extensions and their dependencies meet certain version requirements.
|
2016-12-03 18:06:46 +00:00
|
|
|
*
|
|
|
|
|
* @since 1.29
|
2023-03-25 02:11:36 +00:00
|
|
|
* @ingroup ExtensionRegistry
|
|
|
|
|
* @author Legoktm
|
|
|
|
|
* @author Florian Schmidt
|
2016-12-03 18:06:46 +00:00
|
|
|
*/
|
|
|
|
|
class VersionChecker {
|
|
|
|
|
/**
|
2020-02-25 01:33:18 +00:00
|
|
|
* @var Constraint|bool representing MediaWiki core
|
2016-12-03 18:06:46 +00:00
|
|
|
*/
|
|
|
|
|
private $coreVersion = false;
|
|
|
|
|
|
2018-09-08 00:02:53 +00:00
|
|
|
/**
|
2020-02-25 01:33:18 +00:00
|
|
|
* @var Constraint|bool representing the PHP engine
|
2018-09-08 00:02:53 +00:00
|
|
|
*/
|
|
|
|
|
private $phpVersion = false;
|
|
|
|
|
|
2018-09-24 21:55:16 +00:00
|
|
|
/**
|
|
|
|
|
* @var string[] List of installed PHP extensions
|
|
|
|
|
*/
|
2021-05-12 08:47:18 +00:00
|
|
|
private $phpExtensions;
|
2018-09-24 21:55:16 +00:00
|
|
|
|
2018-10-13 22:24:31 +00:00
|
|
|
/**
|
|
|
|
|
* @var bool[] List of provided abilities
|
|
|
|
|
*/
|
2021-05-12 08:47:18 +00:00
|
|
|
private $abilities;
|
2018-10-13 22:24:31 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var string[] List of provided ability errors
|
|
|
|
|
*/
|
2021-05-12 08:47:18 +00:00
|
|
|
private $abilityErrors;
|
2018-10-13 22:24:31 +00:00
|
|
|
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
/**
|
|
|
|
|
* @var array Loaded extensions
|
|
|
|
|
*/
|
|
|
|
|
private $loaded = [];
|
|
|
|
|
|
2016-12-03 18:06:46 +00:00
|
|
|
/**
|
|
|
|
|
* @var VersionParser
|
|
|
|
|
*/
|
|
|
|
|
private $versionParser;
|
|
|
|
|
|
2016-12-15 23:09:26 +00:00
|
|
|
/**
|
|
|
|
|
* @param string $coreVersion Current version of core
|
2018-09-24 21:55:16 +00:00
|
|
|
* @param string $phpVersion Current PHP version
|
|
|
|
|
* @param string[] $phpExtensions List of installed PHP extensions
|
2018-10-13 22:24:31 +00:00
|
|
|
* @param bool[] $abilities List of provided abilities
|
|
|
|
|
* @param string[] $abilityErrors Error messages for the abilities
|
2016-12-15 23:09:26 +00:00
|
|
|
*/
|
2018-10-13 22:24:31 +00:00
|
|
|
public function __construct(
|
|
|
|
|
$coreVersion, $phpVersion, array $phpExtensions,
|
|
|
|
|
array $abilities = [], array $abilityErrors = []
|
|
|
|
|
) {
|
2016-12-03 18:06:46 +00:00
|
|
|
$this->versionParser = new VersionParser();
|
2016-12-15 23:09:26 +00:00
|
|
|
$this->setCoreVersion( $coreVersion );
|
2018-09-08 00:02:53 +00:00
|
|
|
$this->setPhpVersion( $phpVersion );
|
2018-09-24 21:55:16 +00:00
|
|
|
$this->phpExtensions = $phpExtensions;
|
2018-10-13 22:24:31 +00:00
|
|
|
$this->abilities = $abilities;
|
|
|
|
|
$this->abilityErrors = $abilityErrors;
|
2016-12-03 18:06:46 +00:00
|
|
|
}
|
|
|
|
|
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
/**
|
|
|
|
|
* Set an array with credits of all loaded extensions and skins.
|
|
|
|
|
*
|
|
|
|
|
* @param array $credits An array of installed extensions with credits of them
|
2024-08-10 05:17:59 +00:00
|
|
|
*
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
* @return VersionChecker $this
|
|
|
|
|
*/
|
|
|
|
|
public function setLoadedExtensionsAndSkins( array $credits ) {
|
|
|
|
|
$this->loaded = $credits;
|
|
|
|
|
|
|
|
|
|
return $this;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-03 18:06:46 +00:00
|
|
|
/**
|
|
|
|
|
* Set MediaWiki core version.
|
|
|
|
|
*
|
|
|
|
|
* @param string $coreVersion Current version of core
|
|
|
|
|
*/
|
2016-12-15 23:09:26 +00:00
|
|
|
private function setCoreVersion( $coreVersion ) {
|
2016-12-03 18:06:46 +00:00
|
|
|
try {
|
|
|
|
|
$this->coreVersion = new Constraint(
|
|
|
|
|
'==',
|
|
|
|
|
$this->versionParser->normalize( $coreVersion )
|
|
|
|
|
);
|
|
|
|
|
$this->coreVersion->setPrettyString( $coreVersion );
|
|
|
|
|
} catch ( UnexpectedValueException $e ) {
|
|
|
|
|
// Non-parsable version, don't fatal.
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-08 00:02:53 +00:00
|
|
|
/**
|
|
|
|
|
* @param string $phpVersion Current PHP version. Must be well-formed.
|
2024-08-10 05:17:59 +00:00
|
|
|
*
|
2018-09-08 00:02:53 +00:00
|
|
|
* @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 );
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-03 18:06:46 +00:00
|
|
|
/**
|
|
|
|
|
* Check all given dependencies if they are compatible with the named
|
|
|
|
|
* installed extensions in the $credits array.
|
|
|
|
|
*
|
|
|
|
|
* Example $extDependencies:
|
2017-02-25 21:53:36 +00:00
|
|
|
* {
|
|
|
|
|
* 'FooBar' => {
|
|
|
|
|
* 'MediaWiki' => '>= 1.25.0',
|
2018-09-08 00:02:53 +00:00
|
|
|
* 'platform': {
|
2018-09-24 21:55:16 +00:00
|
|
|
* 'php': '>= 7.0.0',
|
2018-10-13 22:24:31 +00:00
|
|
|
* 'ext-foo': '*',
|
|
|
|
|
* 'ability-bar': true
|
2018-09-08 00:02:53 +00:00
|
|
|
* },
|
2017-02-25 21:53:36 +00:00
|
|
|
* 'extensions' => {
|
|
|
|
|
* 'FooBaz' => '>= 1.25.0'
|
|
|
|
|
* },
|
|
|
|
|
* 'skins' => {
|
|
|
|
|
* 'BazBar' => '>= 1.0.0'
|
|
|
|
|
* }
|
|
|
|
|
* }
|
|
|
|
|
* }
|
2016-12-03 18:06:46 +00:00
|
|
|
*
|
|
|
|
|
* @param array $extDependencies All extensions that depend on other ones
|
2024-08-10 05:17:59 +00:00
|
|
|
*
|
2020-01-23 08:21:24 +00:00
|
|
|
* @return array[] List of errors
|
2016-12-03 18:06:46 +00:00
|
|
|
*/
|
|
|
|
|
public function checkArray( array $extDependencies ) {
|
|
|
|
|
$errors = [];
|
|
|
|
|
foreach ( $extDependencies as $extension => $dependencies ) {
|
|
|
|
|
foreach ( $dependencies as $dependencyType => $values ) {
|
|
|
|
|
switch ( $dependencyType ) {
|
|
|
|
|
case ExtensionRegistry::MEDIAWIKI_CORE:
|
2018-09-08 00:02:53 +00:00
|
|
|
$mwError = $this->handleDependency(
|
|
|
|
|
$this->coreVersion,
|
2023-02-05 19:21:50 +00:00
|
|
|
$values
|
2018-09-08 00:02:53 +00:00
|
|
|
);
|
2016-12-15 23:09:26 +00:00
|
|
|
if ( $mwError !== false ) {
|
2018-04-08 23:26:01 +00:00
|
|
|
$errors[] = [
|
2018-09-08 00:02:53 +00:00
|
|
|
'msg' =>
|
|
|
|
|
"{$extension} is not compatible with the current MediaWiki "
|
|
|
|
|
. "core (version {$this->coreVersion->getPrettyString()}), "
|
2023-10-24 22:49:24 +00:00
|
|
|
. "it requires: $values.",
|
2018-04-08 23:26:01 +00:00
|
|
|
'type' => 'incompatible-core',
|
|
|
|
|
];
|
2016-12-15 23:09:26 +00:00
|
|
|
}
|
2016-12-03 18:06:46 +00:00
|
|
|
break;
|
2018-09-08 00:02:53 +00:00
|
|
|
case 'platform':
|
|
|
|
|
foreach ( $values as $dependency => $constraint ) {
|
|
|
|
|
if ( $dependency === 'php' ) {
|
2018-09-24 21:55:16 +00:00
|
|
|
// PHP version
|
2018-09-08 00:02:53 +00:00
|
|
|
$phpError = $this->handleDependency(
|
|
|
|
|
$this->phpVersion,
|
2023-02-05 19:21:50 +00:00
|
|
|
$constraint
|
2018-09-08 00:02:53 +00:00
|
|
|
);
|
|
|
|
|
if ( $phpError !== false ) {
|
|
|
|
|
$errors[] = [
|
|
|
|
|
'msg' =>
|
|
|
|
|
"{$extension} is not compatible with the current PHP "
|
|
|
|
|
. "version {$this->phpVersion->getPrettyString()}), "
|
2023-10-24 22:49:24 +00:00
|
|
|
. "it requires: $constraint.",
|
2018-09-08 00:02:53 +00:00
|
|
|
'type' => 'incompatible-php',
|
|
|
|
|
];
|
|
|
|
|
}
|
2018-09-24 21:55:16 +00:00
|
|
|
} elseif ( substr( $dependency, 0, 4 ) === 'ext-' ) {
|
|
|
|
|
// PHP extensions
|
|
|
|
|
$phpExtension = substr( $dependency, 4 );
|
|
|
|
|
if ( $constraint !== '*' ) {
|
|
|
|
|
throw new UnexpectedValueException( 'Version constraints for '
|
|
|
|
|
. 'PHP extensions are not supported in ' . $extension );
|
|
|
|
|
}
|
|
|
|
|
if ( !in_array( $phpExtension, $this->phpExtensions, true ) ) {
|
|
|
|
|
$errors[] = [
|
|
|
|
|
'msg' =>
|
|
|
|
|
"{$extension} requires {$phpExtension} PHP extension "
|
2023-10-24 22:49:24 +00:00
|
|
|
. "to be installed.",
|
2018-09-24 21:55:16 +00:00
|
|
|
'type' => 'missing-phpExtension',
|
|
|
|
|
'missing' => $phpExtension,
|
|
|
|
|
];
|
|
|
|
|
}
|
2018-10-13 22:24:31 +00:00
|
|
|
} elseif ( substr( $dependency, 0, 8 ) === 'ability-' ) {
|
|
|
|
|
// Other abilities the environment might provide.
|
|
|
|
|
$ability = substr( $dependency, 8 );
|
|
|
|
|
if ( !isset( $this->abilities[$ability] ) ) {
|
|
|
|
|
throw new UnexpectedValueException( 'Dependency type '
|
|
|
|
|
. $dependency . ' unknown in ' . $extension );
|
|
|
|
|
}
|
|
|
|
|
if ( !is_bool( $constraint ) ) {
|
|
|
|
|
throw new UnexpectedValueException( 'Only booleans are '
|
|
|
|
|
. 'allowed to to indicate the presence of abilities '
|
|
|
|
|
. 'in ' . $extension );
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-17 19:52:34 +00:00
|
|
|
if ( $constraint &&
|
2018-10-13 22:24:31 +00:00
|
|
|
$this->abilities[$ability] !== true
|
|
|
|
|
) {
|
|
|
|
|
// add custom error message for missing ability if specified
|
|
|
|
|
$customMessage = '';
|
|
|
|
|
if ( isset( $this->abilityErrors[$ability] ) ) {
|
|
|
|
|
$customMessage = ': ' . $this->abilityErrors[$ability];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$errors[] = [
|
|
|
|
|
'msg' =>
|
|
|
|
|
"{$extension} requires \"{$ability}\" ability"
|
2023-10-24 22:49:24 +00:00
|
|
|
. $customMessage,
|
2018-10-13 22:24:31 +00:00
|
|
|
'type' => 'missing-ability',
|
|
|
|
|
'missing' => $ability,
|
|
|
|
|
];
|
|
|
|
|
}
|
2018-09-08 00:02:53 +00:00
|
|
|
} else {
|
|
|
|
|
// add other platform dependencies here
|
|
|
|
|
throw new UnexpectedValueException( 'Dependency type ' . $dependency .
|
|
|
|
|
' unknown in ' . $extension );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
case 'extensions':
|
2018-06-15 15:51:22 +00:00
|
|
|
case 'skins':
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
foreach ( $values as $dependency => $constraint ) {
|
2018-04-08 23:26:01 +00:00
|
|
|
$extError = $this->handleExtensionDependency(
|
|
|
|
|
$dependency, $constraint, $extension, $dependencyType
|
|
|
|
|
);
|
2016-12-15 23:09:26 +00:00
|
|
|
if ( $extError !== false ) {
|
|
|
|
|
$errors[] = $extError;
|
|
|
|
|
}
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2016-12-03 18:06:46 +00:00
|
|
|
default:
|
|
|
|
|
throw new UnexpectedValueException( 'Dependency type ' . $dependencyType .
|
|
|
|
|
' unknown in ' . $extension );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $errors;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2018-09-08 00:02:53 +00:00
|
|
|
* Handle a simple dependency to MediaWiki core or PHP. See handleMediaWikiDependency and
|
|
|
|
|
* handlePhpDependency for details.
|
2016-12-03 18:06:46 +00:00
|
|
|
*
|
2022-11-09 00:11:22 +00:00
|
|
|
* @param Constraint|false $version The version installed
|
2016-12-03 18:06:46 +00:00
|
|
|
* @param string $constraint The required version constraint for this dependency
|
2024-08-10 05:17:59 +00:00
|
|
|
*
|
2018-09-08 00:02:53 +00:00
|
|
|
* @return bool false if no error, true else
|
2016-12-03 18:06:46 +00:00
|
|
|
*/
|
2023-02-05 19:21:50 +00:00
|
|
|
private function handleDependency( $version, $constraint ) {
|
2018-09-08 00:02:53 +00:00
|
|
|
if ( $version === false ) {
|
|
|
|
|
// Couldn't parse the version, so we can't check anything
|
2016-12-15 23:09:26 +00:00
|
|
|
return false;
|
2016-12-03 18:06:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the installed and required version are compatible, return an empty array
|
|
|
|
|
if ( $this->versionParser->parseConstraints( $constraint )
|
2018-09-08 00:02:53 +00:00
|
|
|
->matches( $version ) ) {
|
2016-12-15 23:09:26 +00:00
|
|
|
return false;
|
2016-12-03 18:06:46 +00:00
|
|
|
}
|
2018-09-08 00:02:53 +00:00
|
|
|
|
|
|
|
|
return true;
|
2016-12-03 18:06:46 +00:00
|
|
|
}
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle a dependency to another extension.
|
|
|
|
|
*
|
|
|
|
|
* @param string $dependencyName The name of the dependency
|
|
|
|
|
* @param string $constraint The required version constraint for this dependency
|
|
|
|
|
* @param string $checkedExt The Extension, which depends on this dependency
|
2018-06-15 15:51:22 +00:00
|
|
|
* @param string $type Either 'extensions' or 'skins'
|
2024-08-10 05:17:59 +00:00
|
|
|
*
|
2018-04-08 23:26:01 +00:00
|
|
|
* @return bool|array false for no errors, or an array of info
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
*/
|
2018-04-08 23:26:01 +00:00
|
|
|
private function handleExtensionDependency( $dependencyName, $constraint, $checkedExt,
|
|
|
|
|
$type
|
|
|
|
|
) {
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
// Check if the dependency is even installed
|
|
|
|
|
if ( !isset( $this->loaded[$dependencyName] ) ) {
|
2018-04-08 23:26:01 +00:00
|
|
|
return [
|
|
|
|
|
'msg' => "{$checkedExt} requires {$dependencyName} to be installed.",
|
|
|
|
|
'type' => "missing-$type",
|
|
|
|
|
'missing' => $dependencyName,
|
|
|
|
|
];
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
}
|
2018-08-28 19:29:04 +00:00
|
|
|
if ( $constraint === '*' ) {
|
|
|
|
|
// short-circuit since any version is OK.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
// Check if the dependency has specified a version
|
|
|
|
|
if ( !isset( $this->loaded[$dependencyName]['version'] ) ) {
|
2018-08-28 19:29:04 +00:00
|
|
|
$msg = "{$dependencyName} does not expose its version, but {$checkedExt}"
|
|
|
|
|
. " requires: {$constraint}.";
|
|
|
|
|
return [
|
|
|
|
|
'msg' => $msg,
|
|
|
|
|
'type' => "incompatible-$type",
|
|
|
|
|
'incompatible' => $checkedExt,
|
|
|
|
|
];
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
} else {
|
|
|
|
|
// Try to get a constraint for the dependency version
|
|
|
|
|
try {
|
|
|
|
|
$installedVersion = new Constraint(
|
|
|
|
|
'==',
|
|
|
|
|
$this->versionParser->normalize( $this->loaded[$dependencyName]['version'] )
|
|
|
|
|
);
|
|
|
|
|
} catch ( UnexpectedValueException $e ) {
|
2016-12-15 23:09:26 +00:00
|
|
|
// Non-parsable version, output an error message that the version
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
// string is invalid
|
2018-04-08 23:26:01 +00:00
|
|
|
return [
|
|
|
|
|
'msg' => "$dependencyName does not have a valid version string.",
|
|
|
|
|
'type' => 'invalid-version',
|
|
|
|
|
];
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
}
|
|
|
|
|
// Check if the constraint actually matches...
|
|
|
|
|
if (
|
|
|
|
|
!$this->versionParser->parseConstraints( $constraint )->matches( $installedVersion )
|
|
|
|
|
) {
|
2018-04-08 23:26:01 +00:00
|
|
|
$msg = "{$checkedExt} is not compatible with the current "
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
. "installed version of {$dependencyName} "
|
|
|
|
|
. "({$this->loaded[$dependencyName]['version']}), "
|
|
|
|
|
. "it requires: " . $constraint . '.';
|
2018-04-08 23:26:01 +00:00
|
|
|
return [
|
|
|
|
|
'msg' => $msg,
|
|
|
|
|
'type' => "incompatible-$type",
|
|
|
|
|
'incompatible' => $checkedExt,
|
|
|
|
|
];
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-15 23:09:26 +00:00
|
|
|
return false;
|
registration: Allow specifying extension dependencies
There are some extensoins that depend upon another extension or skin,
usually in different ways:
* A constant that is added in the dependency extension, and the
existence of is checked for. This is problematic because it requires a
specific load order.
* Checking whether a specific class exists. This is problematic because
it is extremely fragile, and breaks whenever the class is renamed.
* Checking ExtensionRegistry::isLoaded(). This is mostly there, but it
only checks at runtime, and doesn't provide any machine readable data.
Furthermore, developers implement each one differently, with very little
standardization.
With this, extensions may now specify what other extensions they depend
on. This is for explicit *hard* dependencies that must be installed.
For example:
"requires": {
"MediaWiki": ">= 1.25.0",
"extensions": {
"FakeExtension": "*"
},
"skins": {
"FakeSkin": "*"
}
}
This would add a minimum requirement on MediaWiki 1.25.0+ (already
implemented), as well as the requirement that the FakeExtension extension
needs to be installed, as well as the FakeSkin skin. A wildcard (*) is
used instead of an explicit version requirement as many extensions do
not actually version themselves, and there is no consistent versioning
scheme yet.
Bug: T117277
Change-Id: If1cccee1a16a867a71bb0285691c400443d8a30a
2016-12-03 18:19:25 +00:00
|
|
|
}
|
2016-12-03 18:06:46 +00:00
|
|
|
}
|
2024-08-10 05:17:59 +00:00
|
|
|
|
|
|
|
|
/** @deprecated class alias since 1.43 */
|
|
|
|
|
class_alias( VersionChecker::class, 'VersionChecker' );
|