Skip to content

Commit dab7506

Browse files
committed
1 parent 337bc36 commit dab7506

File tree

5 files changed

+140
-1
lines changed

5 files changed

+140
-1
lines changed

src/Drupal/ServiceMap.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ public function setDrupalServices(array $drupalServices): void
2525
self::$services = [];
2626

2727
foreach ($drupalServices as $serviceId => $serviceDefinition) {
28+
if (isset($serviceDefinition['parent'], $drupalServices[$serviceDefinition['parent']])) {
29+
$serviceDefinition = $this->resolveParentDefinition($serviceDefinition['parent'], $serviceDefinition, $drupalServices);
30+
}
31+
2832
// @todo support factories
2933
if (!isset($serviceDefinition['class'])) {
3034
if (isset($serviceDefinition['alias'], $drupalServices[$serviceDefinition['alias']])) {
@@ -53,4 +57,30 @@ public function setDrupalServices(array $drupalServices): void
5357
}
5458
}
5559
}
60+
61+
private function resolveParentDefinition(string $parentId, array $serviceDefinition, array $drupalServices): array
62+
{
63+
$parentDefinition = $drupalServices[$parentId] ?? [];
64+
if ([] === $parentDefinition) {
65+
return $serviceDefinition;
66+
}
67+
68+
if (isset($parentDefinition['parent'])) {
69+
if (!isset($drupalServices[$parentDefinition['parent']])) {
70+
return $serviceDefinition;
71+
}
72+
73+
return $this->resolveParentDefinition($parentDefinition['parent'], $drupalServices[$parentDefinition['parent']], $drupalServices);
74+
}
75+
76+
if (isset($parentDefinition['class']) && !isset($serviceDefinition['class'])) {
77+
$serviceDefinition['class'] = $parentDefinition['class'];
78+
}
79+
80+
if (isset($parentDefinition['public']) && !isset($serviceDefinition['public'])) {
81+
$serviceDefinition['public'] = $parentDefinition['public'];
82+
}
83+
84+
return $serviceDefinition;
85+
}
5686
}

tests/fixtures/drupal/modules/service_map/service_map.services.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,18 @@ services:
66
Drupal\Core\Messenger\MessengerInterface: '@messenger'
77
Drupal\Core\Logger\LoggerChannelFactory: '@logger.factory'
88
Drupal\Core\Logger\LoggerChannelFactoryInterface: '@logger.factory'
9+
service_map.abstract_service:
10+
abstract: true
11+
class: Drupal\service_map\MyService
12+
service_map.concrete_service:
13+
parent: service_map.abstract_service
14+
service_map.concrete_service_with_a_parent_which_has_a_parent:
15+
parent: service_map.concrete_service
16+
service_map.abstract_service_private:
17+
abstract: true
18+
class: Drupal\service_map\MyService
19+
public: false
20+
service_map.concrete_service_overriding_definition_of_its_parent:
21+
parent: service_map.abstract_service_private
22+
class: Drupal\service_map\Override
23+
public: true
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Drupal\service_map;
6+
7+
final class Override
8+
{
9+
10+
}

tests/src/ServiceMapFactoryTest.php

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,35 @@ public function testFactory(string $id, callable $validator): void
3636
],
3737
'config.storage.sync' => [
3838
'alias' => 'config.storage.staging',
39-
]
39+
],
40+
'abstract_service' => [
41+
'abstract' => true,
42+
'class' => 'Drupal\service_map\MyService',
43+
],
44+
'concrete_service' => [
45+
'parent' => 'abstract_service',
46+
],
47+
'concrete_service_with_a_parent_which_has_a_parent' => [
48+
'parent' => 'concrete_service',
49+
],
50+
'abstract_service_private' => [
51+
'abstract' => true,
52+
'class' => 'Drupal\service_map\MyService',
53+
'public' => false,
54+
],
55+
'concrete_service_overriding_definition_of_its_parent' => [
56+
'parent' => 'abstract_service_private',
57+
'class' => 'Drupal\service_map\Override',
58+
'public' => true,
59+
],
60+
'service_with_unknown_parent' => [
61+
'parent' => 'unknown_parent',
62+
],
63+
'service_with_unknown_parent_overriding_definition_of_its_parent' => [
64+
'parent' => 'unknown_parent',
65+
'class' => 'Drupal\service_map\Override',
66+
'public' => false,
67+
],
4068
]);
4169
$validator($service->getService($id));
4270
}
@@ -71,6 +99,58 @@ function (DrupalServiceDefinition $service): void {
7199
self::assertEquals('config.storage.staging', $service->getAlias());
72100
}
73101
];
102+
yield [
103+
'concrete_service',
104+
function (DrupalServiceDefinition $service): void {
105+
self::assertEquals('concrete_service', $service->getId());
106+
self::assertEquals('Drupal\service_map\MyService', $service->getClass());
107+
self::assertTrue($service->isPublic());
108+
self::assertNull($service->getAlias());
109+
}
110+
];
111+
yield [
112+
'concrete_service_with_a_parent_which_has_a_parent',
113+
function (DrupalServiceDefinition $service): void {
114+
self::assertEquals('concrete_service_with_a_parent_which_has_a_parent', $service->getId());
115+
self::assertEquals('Drupal\service_map\MyService', $service->getClass());
116+
self::assertTrue($service->isPublic());
117+
self::assertNull($service->getAlias());
118+
}
119+
];
120+
yield [
121+
'abstract_service_private',
122+
function (DrupalServiceDefinition $service): void {
123+
self::assertEquals('abstract_service_private', $service->getId());
124+
self::assertEquals('Drupal\service_map\MyService', $service->getClass());
125+
self::assertFalse($service->isPublic());
126+
self::assertNull($service->getAlias());
127+
}
128+
];
129+
yield [
130+
'concrete_service_overriding_definition_of_its_parent',
131+
function (DrupalServiceDefinition $service): void {
132+
self::assertEquals('concrete_service_overriding_definition_of_its_parent', $service->getId());
133+
self::assertEquals('Drupal\service_map\Override', $service->getClass());
134+
self::assertTrue($service->isPublic());
135+
self::assertNull($service->getAlias());
136+
}
137+
];
138+
yield [
139+
'service_with_unknown_parent',
140+
function (?DrupalServiceDefinition $service): void {
141+
self::assertNull($service);
142+
}
143+
];
144+
145+
yield [
146+
'service_with_unknown_parent_overriding_definition_of_its_parent',
147+
function (DrupalServiceDefinition $service): void {
148+
self::assertEquals('service_with_unknown_parent_overriding_definition_of_its_parent', $service->getId());
149+
self::assertEquals('Drupal\service_map\Override', $service->getClass());
150+
self::assertFalse($service->isPublic());
151+
self::assertNull($service->getAlias());
152+
}
153+
];
74154
}
75155

76156
}

tests/src/Type/data/container.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
namespace DrupalContainerStatic;
44

55
use Drupal\service_map\MyService;
6+
use Drupal\service_map\Override;
67
use function PHPStan\Testing\assertType;
78

89
$container = \Drupal::getContainer();
910

1011
assertType(MyService::class, $container->get('service_map.my_service'));
1112
assertType('true', $container->has('service_map.my_service'));
1213
assertType('false', $container->has('unknown_service'));
14+
assertType(MyService::class, $container->get('service_map.concrete_service'));
15+
assertType(MyService::class, $container->get('service_map.concrete_service_with_a_parent_which_has_a_parent'));
16+
assertType(Override::class, $container->get('service_map.concrete_service_overriding_definition_of_its_parent'));

0 commit comments

Comments
 (0)