function AutowireTest::testCoreServiceAliases
Same name in other branches
- 10 core/tests/Drupal/KernelTests/Core/DependencyInjection/AutowireTest.php \Drupal\KernelTests\Core\DependencyInjection\AutowireTest::testCoreServiceAliases()
Tests that core services have aliases correctly defined where possible.
File
-
core/
tests/ Drupal/ KernelTests/ Core/ DependencyInjection/ AutowireTest.php, line 53
Class
- AutowireTest
- Tests auto-wiring services.
Namespace
Drupal\KernelTests\Core\DependencyInjectionCode
public function testCoreServiceAliases() : void {
$services = [];
$aliases = [];
$filenames = array_map(fn($module) => "core/modules/{$module[0]}/{$module[0]}.services.yml", $this->coreModuleListDataProvider());
$filenames[] = 'core/core.services.yml';
foreach (array_filter($filenames, 'file_exists') as $filename) {
foreach (Yaml::decode(file_get_contents($filename))['services'] as $id => $service) {
if (is_string($service)) {
$aliases[$id] = substr($service, 1);
}
elseif (isset($service['class']) && class_exists($service['class'])) {
// Ignore services named by their own class.
if ($id === $service['class']) {
continue;
}
// Ignore certain tagged services.
if (isset($service['tags'])) {
foreach ($service['tags'] as $tag) {
if (in_array($tag['name'], [
'access_check',
'cache.context',
'context_provider',
'event_subscriber',
])) {
continue 2;
}
}
}
$services[$id] = $service['class'];
}
}
}
$interfaces = [];
foreach (get_declared_classes() as $class) {
// Ignore proxy classes for autowiring purposes.
if (str_contains($class, '\\ProxyClass\\')) {
continue;
}
foreach (class_implements($class) as $interface) {
$interfaces[$interface][] = $class;
}
}
$expected = [];
foreach ($services as $id => $class) {
// Skip services that share a class.
if (count(array_keys($services, $class)) > 1) {
continue;
}
// Skip IDs that are interfaces already.
if (interface_exists($id)) {
continue;
}
// Expect standalone classes to be aliased.
$implements = class_implements($class);
if (!$implements) {
$expected[$class] = $id;
}
elseif (count($implements) === 1 && TrustedCallbackInterface::class === reset($implements)) {
// Classes implementing only TrustedCallbackInterface should be aliased.
$expected[$class] = $id;
}
// Expect classes that are the only implementation of their interface to
// be aliased.
foreach ($implements as $interface) {
if (count($interfaces[$interface]) === 1) {
$expected[$interface] = $id;
}
}
}
$missing = array_diff($expected, $aliases);
$formatted = Yaml::encode(array_map(fn($alias) => sprintf('@%s', $alias), $missing));
$this->assertSame($expected, array_intersect($expected, $aliases), sprintf('The following core services do not have map the class name to an alias. Add the following to core.services.yml in the appropriate place: %s%s%s', \PHP_EOL, \PHP_EOL, $formatted));
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.