versionParser = new VersionParser(); $this->setCoreVersion( $coreVersion ); } /** * Set an array with credits of all loaded extensions and skins. * * @param array $credits An array of installed extensions with credits of them * @return VersionChecker $this */ public function setLoadedExtensionsAndSkins( array $credits ) { $this->loaded = $credits; return $this; } /** * Set MediaWiki core version. * * @param string $coreVersion Current version of core */ private function setCoreVersion( $coreVersion ) { try { $this->coreVersion = new Constraint( '==', $this->versionParser->normalize( $coreVersion ) ); $this->coreVersion->setPrettyString( $coreVersion ); } catch ( UnexpectedValueException $e ) { // Non-parsable version, don't fatal. } } /** * Check all given dependencies if they are compatible with the named * installed extensions in the $credits array. * * Example $extDependencies: * { * 'FooBar' => { * 'MediaWiki' => '>= 1.25.0', * 'extensions' => { * 'FooBaz' => '>= 1.25.0' * }, * 'skins' => { * 'BazBar' => '>= 1.0.0' * } * } * } * * @param array $extDependencies All extensions that depend on other ones * @return array */ public function checkArray( array $extDependencies ) { $errors = []; foreach ( $extDependencies as $extension => $dependencies ) { foreach ( $dependencies as $dependencyType => $values ) { switch ( $dependencyType ) { case ExtensionRegistry::MEDIAWIKI_CORE: $mwError = $this->handleMediaWikiDependency( $values, $extension ); if ( $mwError !== false ) { $errors[] = $mwError; } break; case 'extensions': case 'skin': foreach ( $values as $dependency => $constraint ) { $extError = $this->handleExtensionDependency( $dependency, $constraint, $extension ); if ( $extError !== false ) { $errors[] = $extError; } } break; default: throw new UnexpectedValueException( 'Dependency type ' . $dependencyType . ' unknown in ' . $extension ); } } } return $errors; } /** * 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. * * @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 */ private function handleMediaWikiDependency( $constraint, $checkedExt ) { if ( $this->coreVersion === false ) { // Couldn't parse the core 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 ) ) { return false; } // otherwise mark this as incompatible. return "{$checkedExt} is not compatible with the current " . "MediaWiki core (version {$this->coreVersion->getPrettyString()}), it requires: " . "$constraint."; } /** * 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 * @return bool|string false for no errors, or a string message */ private function handleExtensionDependency( $dependencyName, $constraint, $checkedExt ) { // Check if the dependency is even installed if ( !isset( $this->loaded[$dependencyName] ) ) { return "{$checkedExt} requires {$dependencyName} to be installed."; } // Check if the dependency has specified a version if ( !isset( $this->loaded[$dependencyName]['version'] ) ) { // If we depend upon any version, and none is set, that's fine. if ( $constraint === '*' ) { wfDebug( "{$dependencyName} does not expose it's version, but {$checkedExt} mentions it with constraint '*'. Assume it's ok so." ); return false; } else { // Otherwise, mark it as incompatible. return "{$dependencyName} does not expose it's version, but {$checkedExt} requires: {$constraint}."; } } else { // Try to get a constraint for the dependency version try { $installedVersion = new Constraint( '==', $this->versionParser->normalize( $this->loaded[$dependencyName]['version'] ) ); } catch ( UnexpectedValueException $e ) { // Non-parsable version, output an error message that the version // string is invalid return "$dependencyName does not have a valid version string."; } // Check if the constraint actually matches... if ( !$this->versionParser->parseConstraints( $constraint )->matches( $installedVersion ) ) { return "{$checkedExt} is not compatible with the current " . "installed version of {$dependencyName} " . "({$this->loaded[$dependencyName]['version']}), " . "it requires: " . $constraint . '.'; } } return false; } }