From 831717249c604f75b8c487e85e126d3752bd37eb Mon Sep 17 00:00:00 2001
From: effulgentsia <alex.bronstein@acquia.com>
Date: Tue, 29 Jun 2021 10:51:38 -0700
Subject: [PATCH] Issue #3021803 by alexpott, AaronBauman, effulgentsia,
 longwave, dawehner, larowlan, bradjones1, tim.plunkett, Berdir, joachim,
 mondrake, weaverryan, JParkinson1991, kim.pepper, louis-cuny,
 rodrigoaguilera: Document and add tests for service autowiring

---
 core/core.api.php                             |  6 ++++
 core/misc/cspell/dictionary.txt               |  1 +
 .../autowire_test/autowire_test.info.yml      |  5 +++
 .../autowire_test/autowire_test.services.yml  | 22 +++++++++++++
 .../autowire_test/src/TestInjection.php       |  9 ++++++
 .../autowire_test/src/TestInjection2.php      |  9 ++++++
 .../src/TestInjectionInterface.php            |  9 ++++++
 .../modules/autowire_test/src/TestService.php | 30 +++++++++++++++++
 .../Core/DependencyInjection/AutowireTest.php | 32 +++++++++++++++++++
 9 files changed, 123 insertions(+)
 create mode 100644 core/modules/system/tests/modules/autowire_test/autowire_test.info.yml
 create mode 100644 core/modules/system/tests/modules/autowire_test/autowire_test.services.yml
 create mode 100644 core/modules/system/tests/modules/autowire_test/src/TestInjection.php
 create mode 100644 core/modules/system/tests/modules/autowire_test/src/TestInjection2.php
 create mode 100644 core/modules/system/tests/modules/autowire_test/src/TestInjectionInterface.php
 create mode 100644 core/modules/system/tests/modules/autowire_test/src/TestService.php
 create mode 100644 core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php

diff --git a/core/core.api.php b/core/core.api.php
index 93ad0576f29d..fb612f23dbf5 100644
--- a/core/core.api.php
+++ b/core/core.api.php
@@ -852,6 +852,12 @@
  * Services can also be defined dynamically, as in the
  * \Drupal\Core\CoreServiceProvider class, but this is less common for modules.
  *
+ * @section sec_define Service autowiring
+ * Instead of specifying arguments explicitly, the container can also autowire
+ * a service's arguments from the constructor's type-hints. See
+ * @link https://symfony.com/doc/current/service_container/autowiring.html the Symfony documentation on defining services dependencies automatically @endlink
+ * for details.
+ *
  * @section sec_tags Service tags
  * Some services have tags, which are defined in the service definition. See
  * @link service_tag Service Tags @endlink for usage.
diff --git a/core/misc/cspell/dictionary.txt b/core/misc/cspell/dictionary.txt
index 80d6cb2fc679..f6328a4e3f1c 100644
--- a/core/misc/cspell/dictionary.txt
+++ b/core/misc/cspell/dictionary.txt
@@ -110,6 +110,7 @@ autosave
 autosubmit
 autowire
 autowired
+autowiring
 backend's
 backlink
 backlinks
diff --git a/core/modules/system/tests/modules/autowire_test/autowire_test.info.yml b/core/modules/system/tests/modules/autowire_test/autowire_test.info.yml
new file mode 100644
index 000000000000..e121afef6cc0
--- /dev/null
+++ b/core/modules/system/tests/modules/autowire_test/autowire_test.info.yml
@@ -0,0 +1,5 @@
+name: 'Auto-wiring test'
+type: module
+description: 'Support module for auto-wiring testing.'
+package: Testing
+version: VERSION
diff --git a/core/modules/system/tests/modules/autowire_test/autowire_test.services.yml b/core/modules/system/tests/modules/autowire_test/autowire_test.services.yml
new file mode 100644
index 000000000000..8111f39a56dc
--- /dev/null
+++ b/core/modules/system/tests/modules/autowire_test/autowire_test.services.yml
@@ -0,0 +1,22 @@
+services:
+  # Multiple services that implements TestInjectionInterface.
+  # These are marked private, because they are only intended to be used as
+  # dependencies injected into other services.
+  Drupal\autowire_test\TestInjection:
+    public: false
+  Drupal\autowire_test\TestInjection2:
+    public: false
+
+  # An alias that specifies which service to use by default for arguments that
+  # type-hint to the interface.
+  # This is marked private, because it is only intended to be used as a
+  # dependency injected into other services.
+  Drupal\autowire_test\TestInjectionInterface:
+    alias: 'Drupal\autowire_test\TestInjection'
+    public: false
+
+  # A service that tests autowiring for two constructor arguments:
+  # - One type-hinted to TestInjectionInterface.
+  # - One type-hinted to TestInjection2.
+  Drupal\autowire_test\TestService:
+    autowire: true
diff --git a/core/modules/system/tests/modules/autowire_test/src/TestInjection.php b/core/modules/system/tests/modules/autowire_test/src/TestInjection.php
new file mode 100644
index 000000000000..c49d856fd9d4
--- /dev/null
+++ b/core/modules/system/tests/modules/autowire_test/src/TestInjection.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Drupal\autowire_test;
+
+/**
+ * A service that is autowired.
+ */
+class TestInjection implements TestInjectionInterface {
+}
diff --git a/core/modules/system/tests/modules/autowire_test/src/TestInjection2.php b/core/modules/system/tests/modules/autowire_test/src/TestInjection2.php
new file mode 100644
index 000000000000..83e1e3822128
--- /dev/null
+++ b/core/modules/system/tests/modules/autowire_test/src/TestInjection2.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Drupal\autowire_test;
+
+/**
+ * A service that is autowired.
+ */
+class TestInjection2 {
+}
diff --git a/core/modules/system/tests/modules/autowire_test/src/TestInjectionInterface.php b/core/modules/system/tests/modules/autowire_test/src/TestInjectionInterface.php
new file mode 100644
index 000000000000..b9bb38252c0e
--- /dev/null
+++ b/core/modules/system/tests/modules/autowire_test/src/TestInjectionInterface.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace Drupal\autowire_test;
+
+/**
+ * An interface for a service that is autowired.
+ */
+interface TestInjectionInterface {
+}
diff --git a/core/modules/system/tests/modules/autowire_test/src/TestService.php b/core/modules/system/tests/modules/autowire_test/src/TestService.php
new file mode 100644
index 000000000000..23febc6ae304
--- /dev/null
+++ b/core/modules/system/tests/modules/autowire_test/src/TestService.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Drupal\autowire_test;
+
+class TestService {
+
+  /**
+   * @var \Drupal\autowire_test\TestInjectionInterface
+   */
+  protected $testInjection;
+
+  /**
+   * @var \Drupal\autowire_test\TestInjection2
+   */
+  protected $testInjection2;
+
+  public function __construct(TestInjectionInterface $test_injection, TestInjection2 $test_injection2) {
+    $this->testInjection = $test_injection;
+    $this->testInjection2 = $test_injection2;
+  }
+
+  public function getTestInjection(): TestInjectionInterface {
+    return $this->testInjection;
+  }
+
+  public function getTestInjection2(): TestInjection2 {
+    return $this->testInjection2;
+  }
+
+}
diff --git a/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php b/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php
new file mode 100644
index 000000000000..08052c74e5d5
--- /dev/null
+++ b/core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Drupal\KernelTests\Core\DependencyInjection;
+
+use Drupal\autowire_test\TestInjection;
+use Drupal\autowire_test\TestInjection2;
+use Drupal\autowire_test\TestService;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests auto-wiring services.
+ *
+ * @group DependencyInjection
+ */
+class AutowireTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['autowire_test'];
+
+  /**
+   * Tests that 'autowire_test.service' has its dependencies injected.
+   */
+  public function testAutowire(): void {
+    // Ensure an autowired interface works.
+    $this->assertInstanceOf(TestInjection::class, $this->container->get(TestService::class)->getTestInjection());
+    // Ensure an autowired class works.
+    $this->assertInstanceOf(TestInjection2::class, $this->container->get(TestService::class)->getTestInjection2());
+  }
+
+}
-- 
GitLab