Skip to content

Commit 549b5aa

Browse files
committed
Test the warnings for container not initialized
1 parent cae8441 commit 549b5aa

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

src/Drupal/Bootstrap.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,11 @@ protected function loadAndCatchErrors(string $path): void
230230
try {
231231
require $path;
232232
} catch (ContainerNotInitializedException $e) {
233+
$path = str_replace(dirname($this->drupalRoot) . '/', '', $path);
233234
// This can happen when drupal_get_path or drupal_get_filename are used outside of the scope of a function.
234-
@trigger_error("$path invoked the Drupal container outside of the scope of a function or class method. It was skipped for analysis.", E_USER_WARNING);
235+
@trigger_error("$path invoked the Drupal container outside of the scope of a function or class method. It was not loaded.", E_USER_WARNING);
235236
} catch (\Throwable $e) {
237+
$path = str_replace(dirname($this->drupalRoot) . '/', '', $path);
236238
// Something prevented the extension file from loading.
237239
@trigger_error("$path failed loading due to {$e->getMessage()}", E_USER_WARNING);
238240
}

tests/src/BootstrapTest.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace PHPStan\Drupal;
4+
5+
use Drupal\Core\DependencyInjection\ContainerNotInitializedException;
6+
use PHPStan\DependencyInjection\ContainerFactory;
7+
use PHPStan\File\FileHelper;
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class BootstrapTest extends TestCase
11+
{
12+
private $previousErrorHandler;
13+
private $gatheredWarnings = [];
14+
15+
public function testContainerNotInitializedExceptionCatch() {
16+
$this->previousErrorHandler = set_error_handler([$this, 'handleError']);
17+
$this->doDrupalBootstrap();
18+
restore_error_handler();
19+
20+
$this->assertNotEmpty($this->gatheredWarnings);
21+
$expectedWarnings = [
22+
'drupal/modules/contained_not_initialized/contained_not_initialized.install invoked the Drupal container outside of the scope of a function or class method. It was not loaded.',
23+
'drupal/modules/contained_not_initialized/contained_not_initialized.post_update.php invoked the Drupal container outside of the scope of a function or class method. It was not loaded.',
24+
'drupal/modules/contained_not_initialized/contained_not_initialized.views.inc invoked the Drupal container outside of the scope of a function or class method. It was not loaded.',
25+
'drupal/modules/contained_not_initialized/contained_not_initialized.views_execution.inc invoked the Drupal container outside of the scope of a function or class method. It was not loaded.',
26+
'drupal/modules/contained_not_initialized/contained_not_initialized.tokens.inc invoked the Drupal container outside of the scope of a function or class method. It was not loaded.',
27+
'drupal/modules/contained_not_initialized/contained_not_initialized.search_api.inc invoked the Drupal container outside of the scope of a function or class method. It was not loaded.',
28+
'drupal/modules/contained_not_initialized/contained_not_initialized.pathauto.inc invoked the Drupal container outside of the scope of a function or class method. It was not loaded.',
29+
];
30+
$this->assertEquals($expectedWarnings, $this->gatheredWarnings);
31+
}
32+
33+
public function handleError($type, $msg, $file, $line, $context = array()): void
34+
{
35+
if (E_USER_WARNING !== $type) {
36+
$h = $this->previousErrorHandler;
37+
if (\is_callable($h)) {
38+
$h($type, $msg, $file, $line, $context);
39+
}
40+
} else {
41+
$this->gatheredWarnings[] = $msg;
42+
}
43+
}
44+
45+
private function doDrupalBootstrap()
46+
{
47+
$rootDir = __DIR__ . '/../fixtures/drupal';
48+
$tmpDir = sys_get_temp_dir() . '/' . time() . 'phpstan';
49+
$containerFactory = new ContainerFactory($rootDir);
50+
$container = $containerFactory->create(
51+
$tmpDir,
52+
[__DIR__ . '/../fixtures/config/phpunit-drupal-phpstan.neon'],
53+
[]
54+
);
55+
$fileHelper = $container->getByType(FileHelper::class);
56+
assert($fileHelper !== null);
57+
58+
$bootstrapFile = $container->parameters['bootstrap'];
59+
$this->assertEquals(dirname(__DIR__, 2) . '/phpstan-bootstrap.php', $bootstrapFile);
60+
// Mock the autoloader.
61+
$GLOBALS['drupalVendorDir'] = dirname(__DIR__, 2) . '/vendor';
62+
if ($bootstrapFile !== null) {
63+
$bootstrapFile = $fileHelper->normalizePath($bootstrapFile);
64+
if (!is_file($bootstrapFile)) {
65+
$this->fail('Bootstrap file not found');
66+
}
67+
(static function (string $file): void {
68+
require_once $file;
69+
})($bootstrapFile);
70+
}
71+
}
72+
73+
}

0 commit comments

Comments
 (0)