diff options
Diffstat (limited to 'includes/common.inc')
-rw-r--r-- | includes/common.inc | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/includes/common.inc b/includes/common.inc index bd41d283c..df885d362 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -4917,3 +4917,83 @@ function _drupal_flush_css_js() { } variable_set('css_js_query_string', $new_character . substr($string_history, 0, 19)); } + +/** + * Parse a dependency for comparison by drupal_check_incompatibility(). + * + * @param $dependency + * A dependency string, for example 'foo (>=7.x-4.5-beta5, 3.x)'. + * @return + * 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 + * used in the UI for reporting incompatibilities). + * - 'versions' is a list of associative arrays, each containing the keys + * 'op' and 'version'. 'op' can be one of: '=', '==', '!=', '<>', '<', + * '<=', '>', or '>='. 'version' is one piece like '4.5-beta3'. + * Callers should pass this structure to drupal_check_incompatibility(). + * + * @see drupal_check_incompatibility() + */ +function drupal_parse_dependency($dependency) { + // We use named subpatterns and support every op that version_compare + // supports. Also, op is optional and defaults to equals. + $p_op = '(?P<operation>!=|==|=|<|<=|>|>=|<>)?'; + // Core version is always optional: 7.x-2.x and 2.x is treated the same. + $p_core = '(?:' . preg_quote(DRUPAL_CORE_COMPATIBILITY) . '-)?'; + $p_major = '(?P<major>\d+)'; + // By setting the minor version to x, branches can be matched. + $p_minor = '(?P<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)'; + $value = array(); + $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'][] = array('op' => '<', 'version' => ($matches['major'] + 1) . '.x'); + $op = '>='; + } + } + $value['versions'][] = array('op' => $op, 'version' => $matches['major'] . '.' . $matches['minor']); + } + } + } + return $value; +} + +/** + * Check whether a version is compatible with a given dependency. + * + * @param $v + * The parsed dependency structure from drupal_parse_dependency(). + * @param $current_version + * The version to check against (like 4.2). + * @return + * NULL if compatible, otherwise the original dependency version string that + * caused the incompatiblity. + * + * @see drupal_parse_dependency() + */ +function drupal_check_incompatibility($v, $current_version) { + 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']))) { + return $v['original_version']; + } + } + } +} |