summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2009-08-13 03:03:04 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2009-08-13 03:03:04 +0000
commit49699d5be129c467323fd469573df3fbf6dbc98e (patch)
tree40f53edd3ea9b67b08de9ad2f9840cc13b14e983 /includes
parent5327ed26c23b1620037031389e81d1a6ddebc410 (diff)
downloadbrdo-49699d5be129c467323fd469573df3fbf6dbc98e.tar.gz
brdo-49699d5be129c467323fd469573df3fbf6dbc98e.tar.bz2
#533586 by dww and chx: Refactor dependency checks into sharable helper functions.
Diffstat (limited to 'includes')
-rw-r--r--includes/common.inc80
-rw-r--r--includes/module.inc45
2 files changed, 84 insertions, 41 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'];
+ }
+ }
+ }
+}
diff --git a/includes/module.inc b/includes/module.inc
index 3e8d5339b..6cd246d7b 100644
--- a/includes/module.inc
+++ b/includes/module.inc
@@ -95,50 +95,13 @@ function module_list($refresh = FALSE, $sort = FALSE, $fixed_list = NULL) {
function _module_build_dependencies($files) {
require_once DRUPAL_ROOT . '/includes/graph.inc';
$roots = $files;
- // 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+)?)';
foreach ($files as $filename => $file) {
$graph[$file->name]['edges'] = array();
if (isset($file->info['dependencies']) && is_array($file->info['dependencies'])) {
- foreach ($file->info['dependencies'] as $dependency_name) {
- $value = array();
- $parts = explode('(', $dependency_name, 2);
- $dependency_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 is checked by preg.
- if ($op == '=' || $op == '==') {
- $value['versions'][] = array('preg' => '/^' . $matches['major'] . '\./');
- $op = '';
- }
- }
- if ($op) {
- $value['versions'][] = array('op' => $op, 'version' => $matches['major'] . '.' . $matches['minor']);
- }
- }
- }
- }
- $graph[$file->name]['edges'][$dependency_name] = $value;
- unset($roots[$dependency_name]);
+ foreach ($file->info['dependencies'] as $dependency) {
+ $dependency_data = drupal_parse_dependency($dependency);
+ $graph[$file->name]['edges'][$dependency_data['name']] = $dependency_data;
+ unset($roots[$dependency_data['name']]);
}
}
}