Skip to content

Commit ecefe2d

Browse files
committed
Disable PrivateServiceRule when the class implements ServiceSubscriberInterface
1 parent d471f62 commit ecefe2d

File tree

4 files changed

+72
-0
lines changed

4 files changed

+72
-0
lines changed

phpstan.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ parameters:
88
- */tests/tmp/*
99
- */tests/*/ExampleContainer.php
1010
- */tests/*/ExampleController.php
11+
- */tests/*/ExampleServiceSubscriber.php
1112
- */tests/*/request_get_content.php

src/Rules/Symfony/ContainerInterfacePrivateServiceRule.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public function processNode(Node $node, Scope $scope): array
5050
return [];
5151
}
5252

53+
$isServiceSubscriber = (new ObjectType('Symfony\Component\DependencyInjection\ServiceSubscriberInterface'))->isSuperTypeOf($argType);
54+
if ($isServiceSubscriber->yes()) {
55+
return [];
56+
}
57+
5358
$serviceId = ServiceMap::getServiceIdFromNode($node->args[0]->value, $scope);
5459
if ($serviceId !== null) {
5560
$service = $this->serviceMap->getService($serviceId);

tests/Rules/Symfony/ContainerInterfacePrivateServiceRuleTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,18 @@ public function testGetPrivateService(): void
2929
);
3030
}
3131

32+
public function testGetPrivateServiceInServiceSubscriber(): void
33+
{
34+
if (!interface_exists('Symfony\\Component\\DependencyInjection\\ServiceSubscriberInterface')) {
35+
self::markTestSkipped('The test needs Symfony\Component\DependencyInjection\ServiceSubscriberInterface class.');
36+
}
37+
38+
$this->analyse(
39+
[
40+
__DIR__ . '/ExampleServiceSubscriber.php',
41+
],
42+
[]
43+
);
44+
}
45+
3246
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Symfony;
4+
5+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
6+
7+
final class ExampleServiceSubscriber extends AbstractController
8+
{
9+
10+
public function privateService(): void
11+
{
12+
$this->get('private');
13+
}
14+
15+
public function privateServiceInTestContainer(): void
16+
{
17+
/** @var \Symfony\Bundle\FrameworkBundle\Test\TestContainer $container */
18+
$container = doFoo();
19+
$container->get('private');
20+
}
21+
22+
public function unknownService(): void
23+
{
24+
$this->get('unknown');
25+
}
26+
27+
public function unknownGuardedServiceInsideContext(): void
28+
{
29+
if ($this->has('unknown')) { // phpcs:ignore
30+
$this->get('unknown');
31+
}
32+
}
33+
34+
public function unknownGuardedServiceOutsideOfContext(): void
35+
{
36+
if (!$this->has('unknown')) {
37+
return;
38+
}
39+
$this->get('unknown');
40+
}
41+
42+
/**
43+
* @return string[]
44+
*/
45+
public static function getSubscribedServices(): array
46+
{
47+
return [
48+
'private' => MyService::class,
49+
];
50+
}
51+
52+
}

0 commit comments

Comments
 (0)