Skip to content

Commit 869ab99

Browse files
committed
Module code adapted for PHPStan
1 parent c2adb5c commit 869ab99

20 files changed

+861
-686
lines changed

.github/workflows/main.yml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
uses: shivammathur/setup-php@v2
1818
with:
1919
php-version: ${{ matrix.php }}
20-
tools: composer:v2
20+
tools: composer:v2, phpstan
2121
extensions: ctype, iconv, intl, json, mbstring, pdo, pdo_sqlite
2222
coverage: none
2323

@@ -56,39 +56,38 @@ jobs:
5656
uses: actions/cache@v3
5757
with:
5858
path: ${{ steps.composer-cache.outputs.dir }}
59-
key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json', 'composer.lock') }}
59+
key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('**/composer.{json,lock}') }}
6060
restore-keys: ${{ runner.os }}-php-${{ matrix.php }}-composer-
6161

6262
- name: Install PHPUnit 10
63-
run: composer require --dev --no-update "phpunit/phpunit=^10.0"
63+
run: composer require --dev --no-update phpunit/phpunit:^10.0
6464

6565
- name: Install dependencies
6666
env:
6767
MATRIX_SYMFONY: ${{ matrix.symfony }}
6868
run: |
69-
composer require symfony/finder=${{ env.COMP_SYMFONY }} --no-update
70-
composer require symfony/yaml=${{ env.COMP_SYMFONY }} --no-update
71-
composer require symfony/console=${{ env.COMP_SYMFONY }} --no-update
72-
composer require symfony/event-dispatcher=${{ env.COMP_SYMFONY }} --no-update
73-
composer require symfony/css-selector=${{ env.COMP_SYMFONY }} --no-update
74-
composer require symfony/dom-crawler=${{ env.COMP_SYMFONY }} --no-update
75-
composer require symfony/browser-kit=${{ env.COMP_SYMFONY }} --no-update
76-
composer require vlucas/phpdotenv --no-update
77-
composer require codeception/module-asserts="3.*" --no-update
78-
composer require codeception/module-doctrine="3.*" --no-update
69+
composer require --no-update \
70+
symfony/{finder,yaml,console,event-dispatcher,css-selector,dom-crawler,browser-kit,validator}:${{ env.COMP_SYMFONY }} \
71+
vlucas/phpdotenv \
72+
codeception/module-asserts:"3.*" \
73+
codeception/module-doctrine:"3.*"
7974
8075
if [[ "$MATRIX_SYMFONY" == "6.4wApi" ]]; then
8176
composer require codeception/module-rest="3.*" --no-update
8277
fi
8378
8479
composer update --prefer-dist --no-progress --no-dev
8580
81+
- name: Run PHPStan (max)
82+
if: ${{ matrix.symfony == '7.2.*' }}
83+
run: phpstan analyse src --level=max --no-progress --error-format=github --memory-limit=1G
84+
8685
- name: Validate Composer files
8786
run: composer validate --strict
8887
working-directory: framework-tests
8988

9089
- name: Install PHPUnit in framework-tests
91-
run: composer require --dev --no-update "phpunit/phpunit=^10.0"
90+
run: composer require --dev --no-update phpunit/phpunit:^10.0
9291
working-directory: framework-tests
9392

9493
- name: Prepare Symfony sample

src/Codeception/Lib/Connector/Symfony.php

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,44 @@
55
namespace Codeception\Lib\Connector;
66

77
use InvalidArgumentException;
8-
use ReflectionClass;
8+
use LogicException;
99
use ReflectionMethod;
1010
use ReflectionProperty;
1111
use Symfony\Bundle\FrameworkBundle\Test\TestContainer;
1212
use Symfony\Component\DependencyInjection\ContainerInterface;
13-
use Symfony\Component\HttpFoundation\Request;
1413
use Symfony\Component\HttpFoundation\Response;
1514
use Symfony\Component\HttpKernel\HttpKernelBrowser;
15+
use Symfony\Component\HttpKernel\HttpKernelInterface;
1616
use Symfony\Component\HttpKernel\Kernel;
17+
use Symfony\Component\HttpKernel\KernelInterface;
1718
use Symfony\Component\HttpKernel\Profiler\Profiler;
18-
use function array_keys;
19+
1920
use function codecept_debug;
2021

22+
/**
23+
* @property KernelInterface $kernel
24+
*/
2125
class Symfony extends HttpKernelBrowser
2226
{
27+
private ContainerInterface $container;
2328
private bool $hasPerformedRequest = false;
24-
private ?ContainerInterface $container;
2529

2630
public function __construct(
27-
Kernel $kernel,
31+
HttpKernelInterface $kernel,
32+
/** @var array<non-empty-string, object> */
2833
public array $persistentServices = [],
29-
private readonly bool $rebootable = true
34+
private bool $reboot = true
3035
) {
3136
parent::__construct($kernel);
3237
$this->followRedirects();
33-
$this->container = $this->getContainer();
38+
$this->container = $this->resolveContainer();
3439
$this->rebootKernel();
3540
}
3641

37-
/** @param Request $request */
3842
protected function doRequest(object $request): Response
3943
{
40-
if ($this->rebootable) {
41-
if ($this->hasPerformedRequest) {
42-
$this->rebootKernel();
43-
} else {
44-
$this->hasPerformedRequest = true;
45-
}
44+
if ($this->reboot) {
45+
$this->hasPerformedRequest ? $this->rebootKernel() : $this->hasPerformedRequest = true;
4646
}
4747

4848
return parent::doRequest($request);
@@ -57,30 +57,27 @@ protected function doRequest(object $request): Response
5757
*/
5858
public function rebootKernel(): void
5959
{
60-
if ($this->container) {
61-
foreach (array_keys($this->persistentServices) as $serviceName) {
62-
if ($service = $this->getService($serviceName)) {
63-
$this->persistentServices[$serviceName] = $service;
64-
}
60+
foreach (array_keys($this->persistentServices) as $service) {
61+
if ($this->container->has($service)) {
62+
$this->persistentServices[$service] = $this->container->get($service);
6563
}
6664
}
6765

6866
$this->persistDoctrineConnections();
69-
$this->ensureKernelShutdown();
70-
$this->kernel->boot();
71-
$this->container = $this->getContainer();
72-
73-
foreach ($this->persistentServices as $serviceName => $service) {
67+
if ($this->kernel instanceof Kernel) {
68+
$this->ensureKernelShutdown();
69+
$this->kernel->boot();
70+
}
71+
$this->container = $this->resolveContainer();
72+
foreach ($this->persistentServices as $name => $service) {
7473
try {
75-
$this->container->set($serviceName, $service);
74+
$this->container->set($name, $service);
7675
} catch (InvalidArgumentException $e) {
77-
codecept_debug("[Symfony] Can't set persistent service {$serviceName}: " . $e->getMessage());
76+
codecept_debug("[Symfony] Can't set persistent service {$name}: {$e->getMessage()}");
7877
}
7978
}
8079

81-
if ($profiler = $this->getProfiler()) {
82-
$profiler->enable();
83-
}
80+
$this->getProfiler()?->enable();
8481
}
8582

8683
protected function ensureKernelShutdown(): void
@@ -89,27 +86,25 @@ protected function ensureKernelShutdown(): void
8986
$this->kernel->shutdown();
9087
}
9188

92-
private function getContainer(): ?ContainerInterface
89+
private function resolveContainer(): ContainerInterface
9390
{
94-
/** @var ContainerInterface $container */
9591
$container = $this->kernel->getContainer();
96-
return $container->has('test.service_container')
97-
? $container->get('test.service_container')
98-
: $container;
99-
}
10092

101-
private function getProfiler(): ?Profiler
102-
{
103-
return $this->container->has('profiler')
104-
? $this->container->get('profiler')
105-
: null;
93+
if ($container->has('test.service_container')) {
94+
$testContainer = $container->get('test.service_container');
95+
if (!$testContainer instanceof ContainerInterface) {
96+
throw new LogicException('Service "test.service_container" must implement ' . ContainerInterface::class);
97+
}
98+
$container = $testContainer;
99+
}
100+
101+
return $container;
106102
}
107103

108-
private function getService(string $serviceName): ?object
104+
private function getProfiler(): ?Profiler
109105
{
110-
return $this->container->has($serviceName)
111-
? $this->container->get($serviceName)
112-
: null;
106+
$profiler = $this->container->get('profiler');
107+
return $profiler instanceof Profiler ? $profiler : null;
113108
}
114109

115110
private function persistDoctrineConnections(): void
@@ -119,20 +114,27 @@ private function persistDoctrineConnections(): void
119114
}
120115

121116
if ($this->container instanceof TestContainer) {
122-
$reflectedTestContainer = new ReflectionMethod($this->container, 'getPublicContainer');
123-
$reflectedTestContainer->setAccessible(true);
124-
$publicContainer = $reflectedTestContainer->invoke($this->container);
117+
$method = new ReflectionMethod($this->container, 'getPublicContainer');
118+
$publicContainer = $method->invoke($this->container);
125119
} else {
126120
$publicContainer = $this->container;
127121
}
128122

129-
$reflectedContainer = new ReflectionClass($publicContainer);
130-
$reflectionTarget = $reflectedContainer->hasProperty('parameters') ? $publicContainer : $publicContainer->getParameterBag();
123+
if (!is_object($publicContainer) || !method_exists($publicContainer, 'getParameterBag')) {
124+
return;
125+
}
126+
127+
$target = property_exists($publicContainer, 'parameters')
128+
? $publicContainer
129+
: $publicContainer->getParameterBag();
130+
131+
if (!is_object($target) || !property_exists($target, 'parameters')) {
132+
return;
133+
}
134+
$prop = new ReflectionProperty($target, 'parameters');
131135

132-
$reflectedParameters = new ReflectionProperty($reflectionTarget, 'parameters');
133-
$reflectedParameters->setAccessible(true);
134-
$parameters = $reflectedParameters->getValue($reflectionTarget);
135-
unset($parameters['doctrine.connections']);
136-
$reflectedParameters->setValue($reflectionTarget, $parameters);
136+
$params = (array) $prop->getValue($target);
137+
unset($params['doctrine.connections']);
138+
$prop->setValue($target, $params);
137139
}
138140
}

0 commit comments

Comments
 (0)