From 305ed67652db4bfee074c65d436114faa0c3550b Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 19 Jan 2015 08:35:17 +0000
Subject: [PATCH] Issue #2205271 by trobey, jhedstrom: Project namespace for
 dependencies

---
 .../Core/Extension/InfoParserInterface.php       | 11 ++++++++++-
 core/lib/Drupal/Core/Extension/ModuleHandler.php | 14 ++++++++++++--
 .../system/src/Tests/Module/DependencyTest.php   | 16 ++++++++++++++++
 .../system_project_namespace_test.info.yml       |  8 ++++++++
 .../Tests/Core/Extension/ModuleHandlerTest.php   |  1 +
 5 files changed, 47 insertions(+), 3 deletions(-)
 create mode 100644 core/modules/system/tests/modules/system_project_namespace_test/system_project_namespace_test.info.yml

diff --git a/core/lib/Drupal/Core/Extension/InfoParserInterface.php b/core/lib/Drupal/Core/Extension/InfoParserInterface.php
index 09283b9a780a..853ebd570092 100644
--- a/core/lib/Drupal/Core/Extension/InfoParserInterface.php
+++ b/core/lib/Drupal/Core/Extension/InfoParserInterface.php
@@ -27,7 +27,16 @@ interface InfoParserInterface  {
    * - type: whether it is for a module or theme. (Required)
    *
    * Information stored in a module .info.yml file:
-   * - dependencies: An array of shortnames of other modules this module requires.
+   * - dependencies: An array of dependency strings. Each is in the form
+   *   'project:module (versions)'; with the following meanings:
+   *   - project: (optional) Project shortname, recommended to ensure
+   *     uniqueness, if the module is part of a project hosted on drupal.org.
+   *     If omitted, also omit the : that follows. The project name is currently
+   *     ignored by Drupal core but is used for automated testing.
+   *   - module: (required) Module shortname within the project.
+   *   - (versions): Version information, consisting of one or more
+   *     comma-separated operator/value pairs or simply version numbers, which
+   *     can contain "x" as a wildcard. Examples: (>=8.22, <8.28), (8.x-3.x).
    * - package: The name of the package of modules this module belongs to.
    *
    * See forum.info.yml for an example of a module .info.yml file.
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index 2c9876086299..c1eee716fdd2 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -631,7 +631,12 @@ protected function verifyImplementations(&$implementations, $hook) {
    * Parses a dependency for comparison by drupal_check_incompatibility().
    *
    * @param $dependency
-   *   A dependency string, for example 'foo (>=8.x-4.5-beta5, 3.x)'.
+   *   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)'
    *
    * @return
    *   An associative array with three keys:
@@ -646,6 +651,12 @@ protected function verifyImplementations(&$implementations, $hook) {
    * @see drupal_check_incompatibility()
    */
   public static function parseDependency($dependency) {
+    $value = array();
+    // 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>!=|==|=|<|<=|>|>=|<>)?';
@@ -654,7 +665,6 @@ public static function parseDependency($dependency) {
     $p_major = '(?<major>\d+)';
     // By setting the minor version to x, branches can be matched.
     $p_minor = '(?<minor>(?:\d+|x)(?:-[A-Za-z]+\d+)?)';
-    $value = array();
     $parts = explode('(', $dependency, 2);
     $value['name'] = trim($parts[0]);
     if (isset($parts[1])) {
diff --git a/core/modules/system/src/Tests/Module/DependencyTest.php b/core/modules/system/src/Tests/Module/DependencyTest.php
index e5787a53ec8d..88d959aaf43c 100644
--- a/core/modules/system/src/Tests/Module/DependencyTest.php
+++ b/core/modules/system/src/Tests/Module/DependencyTest.php
@@ -14,6 +14,22 @@
  * @group Module
  */
 class DependencyTest extends ModuleTestBase {
+  /**
+   * Checks functionality of project namespaces for dependencies.
+   */
+  function testProjectNamespaceForDependencies() {
+    $edit = array(
+      'modules[Core][filter][enable]' => TRUE,
+    );
+    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    // Enable module with project namespace to ensure nothing breaks.
+    $edit = array(
+      'modules[Testing][system_project_namespace_test][enable]' => TRUE,
+    );
+    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->assertModules(array('system_project_namespace_test'), TRUE);
+  }
+
   /**
    * Attempts to enable the Content Translation module without Language enabled.
    */
diff --git a/core/modules/system/tests/modules/system_project_namespace_test/system_project_namespace_test.info.yml b/core/modules/system/tests/modules/system_project_namespace_test/system_project_namespace_test.info.yml
new file mode 100644
index 000000000000..bcea14fb78ce
--- /dev/null
+++ b/core/modules/system/tests/modules/system_project_namespace_test/system_project_namespace_test.info.yml
@@ -0,0 +1,8 @@
+name: 'System project namespace'
+type: module
+description: 'Support module for testing project namespace system dependencies.'
+package: Testing
+version: VERSION
+core: 8.x
+dependencies:
+  - drupal:filter
diff --git a/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php b/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php
index 799c61081607..1a525270f9a0 100644
--- a/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php
+++ b/core/tests/Drupal/Tests/Core/Extension/ModuleHandlerTest.php
@@ -499,6 +499,7 @@ public function dependencyProvider() {
       array('views_ui(<= 8.x-1.x)', array('name' => 'views_ui', 'original_version' => ' (<= 8.x-1.x)', 'versions' => array(array('op' => '<=', 'version' => '2.x')))),
       array('views_ui( <=8.x-1.x)', array('name' => 'views_ui', 'original_version' => ' ( <=8.x-1.x)', 'versions' => array(array('op' => '<=', 'version' => '2.x')))),
       array('views_ui(>8.x-1.x)', array('name' => 'views_ui', 'original_version' => ' (>8.x-1.x)', 'versions' => array(array('op' => '>', 'version' => '2.x')))),
+      array('drupal:views_ui(>8.x-1.x)', array('project' => 'drupal', 'name' => 'views_ui', 'original_version' => ' (>8.x-1.x)', 'versions' => array(array('op' => '>', 'version' => '2.x')))),
     );
   }
 
-- 
GitLab