Commit 550e914c authored by larowlan's avatar larowlan

Issue #2677532 by alexpott, Mile23, kim.pepper, dawehner, andypost, Eric_A,...

Issue #2677532 by alexpott, Mile23, kim.pepper, dawehner, andypost, Eric_A, xjm, Mixologic, larowlan, phenaproxima, markcarver, borisson_: Move drupal_check_incompatibility() functionality to a new Dependency class and Version component
parent 8861a546
......@@ -109,6 +109,7 @@
"drupal/core-transliteration": "self.version",
"drupal/core-utility": "self.version",
"drupal/core-uuid": "self.version",
"drupal/core-version": "self.version",
"drupal/datetime": "self.version",
"drupal/datetime_range": "self.version",
"drupal/dblog": "self.version",
......@@ -196,7 +197,8 @@
"core/lib/Drupal/Component/Serialization/composer.json",
"core/lib/Drupal/Component/Transliteration/composer.json",
"core/lib/Drupal/Component/Utility/composer.json",
"core/lib/Drupal/Component/Uuid/composer.json"
"core/lib/Drupal/Component/Uuid/composer.json",
"core/lib/Drupal/Component/Version/composer.json"
],
"recurse": false,
"replace": false,
......
......@@ -1214,9 +1214,13 @@ function debug($data, $label = NULL, $print_r = TRUE) {
* NULL if compatible, otherwise the original dependency version string that
* caused the incompatibility.
*
* @see \Drupal\Core\Extension\ModuleHandler::parseDependency()
* @deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use
* \Drupal\Core\Extension\Dependency::isCompatible() instead.
*
* @see https://www.drupal.org/node/2756875
*/
function drupal_check_incompatibility($v, $current_version) {
@trigger_error(__FUNCTION__ . '() is deprecated. Use \Drupal\Core\Extension\Dependency::isCompatible() instead. See https://www.drupal.org/node/2756875', E_USER_DEPRECATED);
if (!empty($v['versions'])) {
foreach ($v['versions'] as $required_version) {
if ((isset($required_version['op']) && !version_compare($current_version, $required_version['version'], $required_version['op']))) {
......
......@@ -5,6 +5,7 @@
* API functions for installing modules and themes.
*/
use Drupal\Core\Extension\Dependency;
use Drupal\Component\Utility\Unicode;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Component\Utility\Crypt;
......@@ -1120,15 +1121,14 @@ function install_profile_info($profile, $langcode = 'en') {
$info = \Drupal::service('info_parser')->parse("$profile_path/$profile.info.yml");
$info += $defaults;
$dependency_name_function = function ($dependency) {
return Dependency::createFromString($dependency)->getName();
};
// Convert dependencies in [project:module] format.
$info['dependencies'] = array_map(function ($dependency) {
return ModuleHandler::parseDependency($dependency)['name'];
}, $info['dependencies']);
$info['dependencies'] = array_map($dependency_name_function, $info['dependencies']);
// Convert install key in [project:module] format.
$info['install'] = array_map(function ($dependency) {
return ModuleHandler::parseDependency($dependency)['name'];
}, $info['install']);
$info['install'] = array_map($dependency_name_function, $info['install']);
// drupal_required_modules() includes the current profile as a dependency.
// Remove that dependency, since a module cannot depend on itself.
......
<?php
namespace Drupal\Component\Version;
/**
* A value object representing a Drupal version constraint.
*/
class Constraint {
/**
* The constraint represented as a string. For example '>=8.x-5.x'.
*
* @var string
*/
protected $constraint;
/**
* A list of associative arrays representing the constraint.
*
* Each containing the keys:
* - 'op': can be one of: '=', '==', '!=', '<>', '<', '<=', '>', or '>='.
* - 'version': A complete version, e.g. '4.5-beta3'.
*
* @var array[]
*/
protected $constraintArray = [];
/**
* Constraint constructor.
*
* @param string $constraint
* The constraint string to create the object from. For example, '>8.x-1.1'.
* @param string $core_compatibility
* Core compatibility declared for the current version of Drupal core.
* Normally this is set to \Drupal::CORE_COMPATIBILITY by the caller.
*/
public function __construct($constraint, $core_compatibility) {
$this->constraint = $constraint;
$this->parseConstraint($constraint, $core_compatibility);
}
/**
* Gets the constraint as a string.
*
* Can be used in the UI for reporting incompatibilities.
*
* @return string
* The constraint as a string.
*/
public function __toString() {
return $this->constraint;
}
/**
* A list of associative arrays representing the constraint.
*
* Each containing the keys:
* - 'op': can be one of: '=', '==', '!=', '<>', '<', '<=', '>', or '>='.
* - 'version': A complete version, e.g. '4.5-beta3'.
*
* @return array[]
* The constraint represented as an array.
*
* @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
* Only exists to provide a backwards compatibility layer.
*
* @see https://www.drupal.org/node/2756875
*/
public function toArray() {
@trigger_error(sprintf('%s() only exists to provide a backwards compatibility layer. See https://www.drupal.org/node/2756875', __METHOD__), E_USER_DEPRECATED);
return $this->constraintArray;
}
/**
* Determines if the provided version is satisfied by this constraint.
*
* @param string $version
* The version to check, for example '4.2'.
*
* @return bool
* TRUE if the provided version is satisfied by this constraint, FALSE if
* not.
*/
public function isCompatible($version) {
foreach ($this->constraintArray as $constraint) {
if (!version_compare($version, $constraint['version'], $constraint['op'])) {
return FALSE;
}
}
return TRUE;
}
/**
* Parses a constraint string.
*
* @param string $constraint_string
* The constraint string to parse.
* @param string $core_compatibility
* Core compatibility declared for the current version of Drupal core.
* Normally this is set to \Drupal::CORE_COMPATIBILITY by the caller.
*/
private function parseConstraint($constraint_string, $core_compatibility) {
// We use named subpatterns and support every op that version_compare
// supports. Also, op is optional and defaults to equals.
$p_op = '(?<operation>!=|==|=|<|<=|>|>=|<>)?';
// Core version is always optional: 8.x-2.x and 2.x is treated the same.
$p_core = '(?:' . preg_quote($core_compatibility) . '-)?';
$p_major = '(?<major>\d+)';
// By setting the minor version to x, branches can be matched.
$p_minor = '(?<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
foreach (explode(',', $constraint_string) as $constraint) {
if (preg_match("/^\s*$p_op\s*$p_core$p_major\.$p_minor/", $constraint, $matches)) {
$op = !empty($matches['operation']) ? $matches['operation'] : '=';
if ($matches['minor'] == 'x') {
// Drupal considers "2.x" to mean any version that begins with
// "2" (e.g. 2.0, 2.9 are all "2.x"). PHP's version_compare(),
// on the other hand, treats "x" as a string; so to
// version_compare(), "2.x" is considered less than 2.0. This
// means that >=2.x and <2.x are handled by version_compare()
// as we need, but > and <= are not.
if ($op == '>' || $op == '<=') {
$matches['major']++;
}
// Equivalence can be checked by adding two restrictions.
if ($op == '=' || $op == '==') {
$this->constraintArray[] = ['op' => '<', 'version' => ($matches['major'] + 1) . '.x'];
$op = '>=';
}
}
$this->constraintArray[] = ['op' => $op, 'version' => $matches['major'] . '.' . $matches['minor']];
}
}
}
}
This diff is collapsed.
The Drupal Version Component
Thanks for using this Drupal component.
You can participate in its development on Drupal.org, through our issue system:
https://www.drupal.org/project/issues/drupal
You can get the full Drupal repo here:
https://www.drupal.org/project/drupal/git-instructions
You can browse the full Drupal repo here:
http://cgit.drupalcode.org/drupal
HOW-TO: Test this Drupal component
In order to test this component, you'll need to get the entire Drupal repo and
run the tests there.
You'll find the tests under core/tests/Drupal/Tests/Component.
You can get the full Drupal repo here:
https://www.drupal.org/project/drupal/git-instructions
You can find more information about running PHPUnit tests with Drupal here:
https://www.drupal.org/node/2116263
Each component in the Drupal\Component namespace has its own annotated test
group. You can use this group to run only the tests for this component. Like
this:
$ ./vendor/bin/phpunit -c core --group Version
{
"name": "drupal/core-version",
"description": "Utility classes for process Drupal specific version information.",
"keywords": ["drupal"],
"homepage": "https://www.drupal.org/project/drupal",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=5.5.9"
},
"autoload": {
"psr-4": {
"Drupal\\Component\\Version\\": ""
}
}
}
<?php
namespace Drupal\Core\Extension;
use Drupal\Component\Version\Constraint;
/**
* A value object representing dependency information.
*
* This class implements \ArrayAccess to provide a backwards compatibility layer
* for Drupal 8.x. This will be removed before Drupal 9.x.
*
* @see https://www.drupal.org/node/2756875
*/
class Dependency implements \ArrayAccess {
/**
* The name of the dependency.
*
* @var string
*/
protected $name;
/**
* The project namespace for the dependency.
*
* @var string
*/
protected $project;
/**
* The constraint string.
*
* @var \Drupal\Component\Version\Constraint
*/
protected $constraintString;
/**
* The Constraint object from the constraint string.
*
* @var \Drupal\Component\Version\Constraint
*/
protected $constraint;
/**
* Dependency constructor.
*
* @param string $name
* The name of the dependency.
* @param string $project
* The project namespace for the dependency.
* @param string $constraint
* The constraint string. For example, '>8.x-1.1'.
*/
public function __construct($name, $project, $constraint) {
$this->name = $name;
$this->project = $project;
$this->constraintString = $constraint;
}
/**
* Gets the dependency's name.
*
* @return string
* The dependency's name.
*/
public function getName() {
return $this->name;
}
/**
* Gets the dependency's project namespace.
*
* @return string
* The dependency's project namespace.
*/
public function getProject() {
return $this->project;
}
/**
* Gets constraint string from the dependency.
*
* @return string
* The constraint string.
*/
public function getConstraintString() {
return $this->constraintString;
}
/**
* Gets the Constraint object.
*
* @return \Drupal\Component\Version\Constraint
* The Constraint object.
*/
protected function getConstraint() {
if (!$this->constraint) {
$this->constraint = new Constraint($this->constraintString, \Drupal::CORE_COMPATIBILITY);
}
return $this->constraint;
}
/**
* Determines if the provided version is compatible with this dependency.
*
* @param string $version
* The version to check, for example '4.2'.
*
* @return bool
* TRUE if compatible with the provided version, FALSE if not.
*/
public function isCompatible($version) {
return $this->getConstraint()->isCompatible($version);
}
/**
* {@inheritdoc}
*/
public function offsetExists($offset) {
@trigger_error(sprintf('Array access to %s properties is deprecated. Use accessor methods instead. See https://www.drupal.org/node/2756875', __CLASS__), E_USER_DEPRECATED);
return in_array($offset, ['name', 'project', 'original_version', 'versions'], TRUE);
}
/**
* {@inheritdoc}
*/
public function offsetGet($offset) {
switch ($offset) {
case 'name':
@trigger_error(sprintf('Array access to the %s name property is deprecated. Use %s::getName() instead. See https://www.drupal.org/node/2756875', __CLASS__, __CLASS__), E_USER_DEPRECATED);
return $this->getName();
case 'project':
@trigger_error(sprintf('Array access to the %s project property is deprecated. Use %s::getProject() instead. See https://www.drupal.org/node/2756875', __CLASS__, __CLASS__), E_USER_DEPRECATED);
return $this->getProject();
case 'original_version':
@trigger_error(sprintf('Array access to the %s original_version property is deprecated. Use %s::getConstraintString() instead. See https://www.drupal.org/node/2756875', __CLASS__, __CLASS__), E_USER_DEPRECATED);
$constraint = $this->getConstraintString();
if ($constraint) {
$constraint = ' (' . $constraint . ')';
}
return $constraint;
case 'versions':
@trigger_error(sprintf('Array access to the %s versions property is deprecated. See https://www.drupal.org/node/2756875', __CLASS__), E_USER_DEPRECATED);
return $this->getConstraint()->toArray();
}
throw new \InvalidArgumentException("The $offset key is not supported");
}
/**
* {@inheritdoc}
*/
public function offsetSet($offset, $value) {
throw new \BadMethodCallException(sprintf('%s() is not supported', __METHOD__));
}
/**
* {@inheritdoc}
*/
public function offsetUnset($offset) {
throw new \BadMethodCallException(sprintf('%s() is not supported', __METHOD__));
}
/**
* Creates a new instance of this class from a dependency string.
*
* @param string $dependency
* A dependency string, which specifies a module or theme dependency, and
* optionally the project it comes from and a constraint string that
* determines the versions that are supported. Supported formats include:
* - 'module'
* - 'project:module'
* - 'project:module (>=version, <=version)'.
*
* @return static
*/
public static function createFromString($dependency) {
if (strpos($dependency, ':') !== FALSE) {
list($project, $dependency) = explode(':', $dependency);
}
else {
$project = '';
}
$parts = explode('(', $dependency, 2);
$name = trim($parts[0]);
$version_string = isset($parts[1]) ? rtrim($parts[1], ") ") : '';
return new static($name, $project, $version_string);
}
}
......@@ -214,7 +214,7 @@ protected function getInstalledExtensionNames() {
protected function ensureRequiredDependencies(Extension $module, array $modules = []) {
if (!empty($module->info['required'])) {
foreach ($module->info['dependencies'] as $dependency) {
$dependency_name = ModuleHandler::parseDependency($dependency)['name'];
$dependency_name = Dependency::createFromString($dependency)->getName();
if (!isset($modules[$dependency_name]->info['required'])) {
$modules[$dependency_name]->info['required'] = TRUE;
$modules[$dependency_name]->info['explanation'] = $this->t('Dependency of required module @module', ['@module' => $module->info['name']]);
......
......@@ -225,8 +225,8 @@ public function buildModuleDependencies(array $modules) {
$graph[$module->getName()]['edges'] = [];
if (isset($module->info['dependencies']) && is_array($module->info['dependencies'])) {
foreach ($module->info['dependencies'] as $dependency) {
$dependency_data = static::parseDependency($dependency);
$graph[$module->getName()]['edges'][$dependency_data['name']] = $dependency_data;
$dependency_data = Dependency::createFromString($dependency);
$graph[$module->getName()]['edges'][$dependency_data->getName()] = $dependency_data;
}
}
}
......@@ -697,15 +697,15 @@ protected function verifyImplementations(&$implementations, $hook) {
/**
* Parses a dependency for comparison by drupal_check_incompatibility().
*
* @param $dependency
* @param string $dependency
* A dependency string, which specifies a module dependency, and optionally
* the project it comes from and versions that are supported. Supported
* formats include:
* - 'module'
* - 'project:module'
* - 'project:module (>=version, version)'
* - 'project:module (>=version, version)'.
*
* @return
* @return array
* An associative array with three keys:
* - 'name' includes the name of the thing to depend on (e.g. 'foo').
* - 'original_version' contains the original version string (which can be
......@@ -715,51 +715,21 @@ protected function verifyImplementations(&$implementations, $hook) {
* '<=', '>', or '>='. 'version' is one piece like '4.5-beta3'.
* Callers should pass this structure to drupal_check_incompatibility().
*
* @see drupal_check_incompatibility()
* @deprecated in Drupal 8.7.0, will be removed before Drupal 9.0.0.
* Use \Drupal\Core\Extension\Dependency::createFromString() instead.
*
* @see https://www.drupal.org/node/2756875
*/
public static function parseDependency($dependency) {
$value = [];
// Split out the optional project name.
if (strpos($dependency, ':') !== FALSE) {
list($project_name, $dependency) = explode(':', $dependency);
$value['project'] = $project_name;
}
// We use named subpatterns and support every op that version_compare
// supports. Also, op is optional and defaults to equals.
$p_op = '(?<operation>!=|==|=|<|<=|>|>=|<>)?';
// Core version is always optional: 8.x-2.x and 2.x is treated the same.
$p_core = '(?:' . preg_quote(\Drupal::CORE_COMPATIBILITY) . '-)?';
$p_major = '(?<major>\d+)';
// By setting the minor version to x, branches can be matched.
$p_minor = '(?<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
$parts = explode('(', $dependency, 2);
$value['name'] = trim($parts[0]);
if (isset($parts[1])) {
$value['original_version'] = ' (' . $parts[1];
foreach (explode(',', $parts[1]) as $version) {
if (preg_match("/^\s*$p_op\s*$p_core$p_major\.$p_minor/", $version, $matches)) {
$op = !empty($matches['operation']) ? $matches['operation'] : '=';
if ($matches['minor'] == 'x') {
// Drupal considers "2.x" to mean any version that begins with
// "2" (e.g. 2.0, 2.9 are all "2.x"). PHP's version_compare(),
// on the other hand, treats "x" as a string; so to
// version_compare(), "2.x" is considered less than 2.0. This
// means that >=2.x and <2.x are handled by version_compare()
// as we need, but > and <= are not.
if ($op == '>' || $op == '<=') {
$matches['major']++;
}
// Equivalence can be checked by adding two restrictions.
if ($op == '=' || $op == '==') {
$value['versions'][] = ['op' => '<', 'version' => ($matches['major'] + 1) . '.x'];
$op = '>=';
}
}
$value['versions'][] = ['op' => $op, 'version' => $matches['major'] . '.' . $matches['minor']];
}
}
}
return $value;
@trigger_error(__METHOD__ . ' is deprecated. Use \Drupal\Core\Extension\Dependency::createFromString() instead. See https://www.drupal.org/node/2756875', E_USER_DEPRECATED);
$dependency = Dependency::createFromString($dependency);
$result = [
'name' => $dependency->getName(),
'project' => $dependency->getProject(),
'original_version' => $dependency['original_version'],
'versions' => $dependency['versions'],
];
return array_filter($result);
}
/**
......
......@@ -307,7 +307,8 @@ protected function buildRow(array $modules, Extension $module, $distribution) {
}
// If this module requires other modules, add them to the array.
foreach ($module->requires as $dependency => $version) {
/** @var \Drupal\Core\Extension\Dependency $dependency_object */
foreach ($module->requires as $dependency => $dependency_object) {
if (!isset($modules[$dependency])) {
$row['#requires'][$dependency] = $this->t('@module (<span class="admin-missing">missing</span>)', ['@module' => Unicode::ucfirst($dependency)]);
$row['enable']['#disabled'] = TRUE;
......@@ -317,9 +318,10 @@ protected function buildRow(array $modules, Extension $module, $distribution) {
$name = $modules[$dependency]->info['name'];
// Disable the module's checkbox if it is incompatible with the
// dependency's version.
if ($incompatible_version = drupal_check_incompatibility($version, str_replace(\Drupal::CORE_COMPATIBILITY . '-', '', $modules[$dependency]->info['version']))) {
$row['#requires'][$dependency] = $this->t('@module (<span class="admin-missing">incompatible with</span> version @version)', [
'@module' => $name . $incompatible_version,
if (!$dependency_object->isCompatible(str_replace(\Drupal::CORE_COMPATIBILITY . '-', '', $modules[$dependency]->info['version']))) {
$row['#requires'][$dependency] = $this->t('@module (@constraint) (<span class="admin-missing">incompatible with</span> version @version)', [
'@module' => $name,
'@constraint' => $dependency_object->getConstraintString(),
'@version' => $modules[$dependency]->info['version'],
]);
$row['enable']['#disabled'] = TRUE;
......
......@@ -803,8 +803,9 @@ function system_requirements($phase) {
$requirements['php']['severity'] = REQUIREMENT_ERROR;
}
// Check the module's required modules.
/** @var \Drupal\Core\Extension\Dependency $requirement */
foreach ($file->requires as $requirement) {
$required_module = $requirement['name'];
$required_module = $requirement->getName();
// Check if the module exists.
if (!isset($files[$required_module])) {
$requirements["$module-$required_module"] = [
......@@ -819,13 +820,11 @@ function system_requirements($phase) {
$required_file = $files[$required_module];
$required_name = $required_file->info['name'];
$version = str_replace(\Drupal::CORE_COMPATIBILITY . '-', '', $required_file->info['version']);
$compatibility = drupal_check_incompatibility($requirement, $version);
if ($compatibility) {
$compatibility = rtrim(substr($compatibility, 2), ')');
if (!$requirement->isCompatible($version)) {
$requirements["$module-$required_module"] = [
'title' => t('Unresolved dependency'),
'description' => t('@name requires this module and version. Currently using @required_name version @version', ['@name' => $name, '@required_name' => $required_name, '@version' => $version]),
'value' => t('@required_name (Version @compatibility required)', ['@required_name' => $required_name, '@compatibility' => $compatibility]),
'value' => t('@required_name (Version @compatibility required)', ['@required_name' => $required_name, '@compatibility' => $requirement->getConstraintString()]),
'severity' => REQUIREMENT_ERROR,
];
continue;
......
......@@ -5,6 +5,7 @@
* Configuration system that lets administrators modify the workings of the site.
*/
use Drupal\Core\Extension\Dependency;
use Drupal\Component\Render\PlainTextOutput;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Asset\AttachedAssetsInterface;
......@@ -21,7 +22,6 @@
use Drupal\Core\Routing\StackedRouteMatchInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Menu\MenuTreeParameters;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\Core\Url;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\user\UserInterface;
......@@ -1014,7 +1014,7 @@ function _system_rebuild_module_data_ensure_required($module, &$modules) {
@trigger_error("_system_rebuild_module_data_ensure_required() is deprecated in Drupal 8.5.0 and will be removed before Drupal 9.0.0. This function is no longer used in Drupal core. See https://www.drupal.org/node/2709919", E_USER_DEPRECATED);
if (!empty($module->info['required'])) {
foreach ($module->info['dependencies'] as $dependency) {
$dependency_name = ModuleHandler::parseDependency($dependency)['name'];
$dependency_name = Dependency::createFromString($dependency)->getName();
if (!isset($modules[$dependency_name]->info['required'])) {
$modules[$dependency_name]->info['required'] = TRUE;
$modules[$dependency_name]->info['explanation'] = t('Dependency of required module @module', ['@module' => $module->info['name']]);
......
......@@ -5,6 +5,8 @@
* This file provides testing functionality for update.php.
*/
use Drupal\Core\Extension\Extension;
/**
* Implements hook_cache_flush().
*
......@@ -16,3 +18,15 @@
function update_script_test_cache_flush() {
\Drupal::messenger()->addStatus(t('hook_cache_flush() invoked for update_script_test.module.'));
}
/**
* Implements hook_system_info_alter().
*/
function update_script_test_system_info_alter(array &$info, Extension $file, $type) {
$new_info = \Drupal::state()->get('update_script_test.system_info_alter');
if ($new_info) {
if ($file->getName() == 'update_script_test') {
$info = $new_info + $info;
}
}
}
......@@ -142,6 +142,19 @@ public function testRequirements() {
$this->assertText('This is a requirements error provided by the update_script_test module.');
$this->clickLink('try again');
$this->assertText('This is a requirements error provided by the update_script_test module.');
// Ensure that changes to a module's requirements that would cause errors
// are displayed correctly.
$update_script_test_config->set('requirement_type', REQUIREMENT_OK)->save();
\Drupal::state()->set('update_script_test.system_info_alter', ['dependencies' => ['a_module_that_does_not_exist']]);
$this->drupalGet($this->updateUrl, ['external' => TRUE]);
$this->assertSession()->responseContains('a_module_that_does_not_exist (Missing)');
$this->assertSession()->responseContains('Update script test requires this module.');
\Drupal::state()->set('update_script_test.system_info_alter', ['dependencies' => ['node (<7.x-0.0-dev)']]);
$this->drupalGet($this->updateUrl, ['external' => TRUE]);
$this->assertSession()->assertEscaped('Node (Version <7.x-0.0-dev required)');
$this->assertSession()->responseContains('Update script test requires this module and version. Currently using Node version ' . \Drupal::VERSION);
}
/**
......
<?php
namespace Drupal\KernelTests\Core\Common;
use Drupal\Core\Extension\Dependency;
use Drupal\KernelTests\KernelTestBase;
/**
* Parse a predefined amount of bytes and compare the output with the expected
* value.
*
* @group Common
* @group legacy
*/
class DrupalCheckIncompatibilityTest extends KernelTestBase {
/**
* Tests drupal_check_incompatibility().
*
* @dataProvider providerDrupalCheckIncompatibility
* @expectedDeprecation drupal_check_incompatibility() is deprecated. Use \Drupal\Core\Extension\Dependency::isCompatible() instead. See https://www.drupal.org/node/2756875
*/
public function testDrupalCheckIncompatibility($version_info, $version_to_check, $result) {
$this->assertSame($result, drupal_check_incompatibility($version_info, $version_to_check));
}
/**
* Data provider for testDrupalCheckIncompatibility.
*/
public function providerDrupalCheckIncompatibility() {
$module_data = [
'name' => 'views_ui',
'original_version' => ' (8.x-1.0)',
'versions' => [['op' => '=', 'version' => '1.0']],
];