1
1
<?php declare (strict_types=1 );
2
2
3
- namespace PHPStan \Drupal ;
3
+ namespace PHPStan \DependencyInjection ;
4
4
5
5
use Composer \Autoload \ClassLoader ;
6
+ use Nette \DI \CompilerExtension ;
7
+ use Nette \DI \Config \Helpers ;
8
+ use Nette \Utils \Finder ;
9
+ use PHPStan \Drupal \Extension ;
10
+ use PHPStan \Drupal \ExtensionDiscovery ;
6
11
7
- class Bootstrap
12
+ class DrupalExtension extends CompilerExtension
8
13
{
9
14
15
+ protected $ defaultConfig = [
16
+ 'modules ' => [],
17
+ 'themes ' => [],
18
+ ];
19
+
20
+ private $ autoloaderPath ;
21
+
10
22
/**
11
23
* @var \Composer\Autoload\ClassLoader
12
24
*/
@@ -18,30 +30,33 @@ class Bootstrap
18
30
private $ drupalRoot ;
19
31
20
32
/**
21
- * @var \PHPStan\Drupal\ExtensionDiscovery
33
+ * List of available modules.
34
+ *
35
+ * @var \PHPStan\Drupal\Extension[]
22
36
*/
23
- private $ extensionDiscovery ;
37
+ protected $ moduleData = [] ;
24
38
25
39
/**
26
- * @var array
40
+ * List of available themes.
41
+ *
42
+ * @var \PHPStan\Drupal\Extension[]
27
43
*/
28
- private $ modules = [];
44
+ protected $ themeData = [];
29
45
30
- /**
31
- * @var array
32
- */
46
+ private $ modules = [];
33
47
private $ themes = [];
48
+ private $ extensionDiscovery ;
34
49
35
- public function __construct ()
50
+ public function loadConfiguration (): void
36
51
{
37
- $ autoload_file = $ GLOBALS ['autoloaderInWorkingDirectory ' ];
52
+
53
+ $ this ->autoloaderPath = $ GLOBALS ['autoloaderInWorkingDirectory ' ];
38
54
/** @noinspection PhpIncludeInspection */
39
- $ this ->autoloader = require $ autoload_file ;
55
+ $ this ->autoloader = require $ this -> autoloaderPath ;
40
56
if (!$ this ->autoloader instanceof ClassLoader) {
41
57
throw new \InvalidArgumentException ('Unable to determine the Composer class loader for Drupal ' );
42
58
}
43
-
44
- $ realpath = realpath ($ autoload_file );
59
+ $ realpath = realpath ($ this ->autoloaderPath );
45
60
if ($ realpath === false ) {
46
61
throw new \InvalidArgumentException ('Cannot determine the realpath of the autoloader. ' );
47
62
}
@@ -57,10 +72,15 @@ public function __construct()
57
72
if ($ this ->drupalRoot === null ) {
58
73
throw new \InvalidArgumentException ('Unable to determine the Drupal root ' );
59
74
}
60
- }
61
75
62
- public function register (): void
63
- {
76
+ $ builder = $ this ->getContainerBuilder ();
77
+ $ builder ->parameters ['drupalRoot ' ] = $ this ->drupalRoot ;
78
+
79
+ $ config = Helpers::merge ($ this ->config , $ this ->defaultConfig );
80
+
81
+ $ this ->modules = $ config ['modules ' ] ?? [];
82
+ $ this ->themes = $ config ['themes ' ] ?? [];
83
+
64
84
$ this ->extensionDiscovery = new ExtensionDiscovery ($ this ->drupalRoot );
65
85
$ this ->extensionDiscovery ->setProfileDirectories ([]);
66
86
$ profiles = $ this ->extensionDiscovery ->scan ('profile ' );
@@ -69,48 +89,52 @@ public function register(): void
69
89
}, $ profiles );
70
90
$ this ->extensionDiscovery ->setProfileDirectories ($ profile_directories );
71
91
72
- $ this ->modules = $ this ->extensionDiscovery ->scan ('module ' );
73
- $ this ->themes = $ this ->extensionDiscovery ->scan ('theme ' );
92
+ $ this ->moduleData = $ this ->extensionDiscovery ->scan ('module ' );
93
+ $ this ->themeData = $ this ->extensionDiscovery ->scan ('theme ' );
74
94
75
- require $ this ->drupalRoot . '/core/includes/bootstrap.inc ' ;
76
- require $ this ->drupalRoot . '/core/includes/common.inc ' ;
77
- require $ this ->drupalRoot . '/core/includes/entity.inc ' ;
78
- require $ this ->drupalRoot . '/core/includes/menu.inc ' ;
79
- require $ this ->drupalRoot . '/core/includes/database.inc ' ;
80
- require $ this ->drupalRoot . '/core/includes/file.inc ' ;
81
- $ core_namespaces = $ this ->getCoreNamespaces ();
82
- $ module_namespaces = $ this ->getModuleNamespaces ();
83
- $ theme_namespaces = $ this ->getThemeNamespaces ();
95
+ $ this ->loadLegacyIncludes ();
84
96
85
- $ namespaces = array_merge ($ core_namespaces , $ module_namespaces , $ theme_namespaces );
97
+ $ this ->addCoreNamespaces ();
98
+ $ this ->addModuleNamespaces ();
99
+ $ this ->addThemeNamespaces ();
86
100
87
- foreach ($ namespaces as $ prefix => $ paths ) {
88
- if (is_array ($ paths )) {
89
- foreach ($ paths as $ key => $ value ) {
90
- $ paths [$ key ] = $ value ;
101
+ foreach ($ this ->moduleData as $ extension ) {
102
+ $ this ->loadExtension ($ extension );
103
+
104
+ $ module_name = $ extension ->getName ();
105
+ $ module_dir = $ this ->drupalRoot . '/ ' . $ extension ->getPath ();
106
+ // Add .post_update.php
107
+ if (file_exists ($ module_dir . '/ ' . $ module_name . '.post_update.php ' )) {
108
+ require $ module_dir . '/ ' . $ module_name . '.post_update.php ' ;
109
+ }
110
+ // Add misc .inc that are magically allowed via hook_hook_info.
111
+ $ magic_hook_info_includes = [
112
+ 'views ' ,
113
+ 'views_execution ' ,
114
+ 'tokens ' ,
115
+ 'search_api ' ,
116
+ 'pathauto ' ,
117
+ ];
118
+ foreach ($ magic_hook_info_includes as $ hook_info_include ) {
119
+ if (file_exists ($ module_dir . "/ $ module_name. $ hook_info_include.inc " )) {
120
+ require $ module_dir . "/ $ module_name. $ hook_info_include.inc " ;
91
121
}
92
122
}
93
- $ this ->autoloader ->addPsr4 ($ prefix . '\\' , $ paths );
94
123
}
124
+ foreach ($ this ->themeData as $ extension ) {
125
+ $ this ->loadExtension ($ extension );
126
+ }
127
+ }
95
128
96
- // Add core test namespaces.
97
- $ core_tests_dir = $ this ->drupalRoot . '/core/tests ' ;
98
- $ this ->autoloader ->add ('Drupal \\Tests ' , $ core_tests_dir );
99
- $ this ->autoloader ->add ('Drupal \\TestSite ' , $ core_tests_dir );
100
- $ this ->autoloader ->add ('Drupal \\KernelTests ' , $ core_tests_dir );
101
- $ this ->autoloader ->add ('Drupal \\FunctionalTests ' , $ core_tests_dir );
102
- $ this ->autoloader ->add ('Drupal \\FunctionalJavascriptTests ' , $ core_tests_dir );
103
-
104
- $ this ->loadModules ();
105
- $ this ->loadThemes ();
129
+ protected function loadLegacyIncludes (): void
130
+ {
131
+ /** @var \SplFileInfo $file */
132
+ foreach (Finder::findFiles ('*.inc ' )->in ($ this ->drupalRoot . '/core/includes ' ) as $ file ) {
133
+ require $ file ->getPathname ();
134
+ }
106
135
}
107
136
108
- /**
109
- * @return array
110
- *
111
- * @see \Drupal\Core\DrupalKernel::compileContainer
112
- */
113
- protected function getCoreNamespaces (): array
137
+ protected function addCoreNamespaces (): void
114
138
{
115
139
$ namespaces = [];
116
140
foreach (['Core ' , 'Component ' ] as $ parent_directory ) {
@@ -127,14 +151,20 @@ protected function getCoreNamespaces(): array
127
151
}
128
152
}
129
153
}
154
+ $ this ->registerPs4Namespaces ($ namespaces );
130
155
131
- return $ namespaces ;
156
+ // Add core test namespaces.
157
+ $ core_tests_dir = $ this ->drupalRoot . '/core/tests ' ;
158
+ $ this ->autoloader ->add ('Drupal \\Tests ' , $ core_tests_dir );
159
+ $ this ->autoloader ->add ('Drupal \\TestSite ' , $ core_tests_dir );
160
+ $ this ->autoloader ->add ('Drupal \\KernelTests ' , $ core_tests_dir );
161
+ $ this ->autoloader ->add ('Drupal \\FunctionalTests ' , $ core_tests_dir );
162
+ $ this ->autoloader ->add ('Drupal \\FunctionalJavascriptTests ' , $ core_tests_dir );
132
163
}
133
-
134
- protected function getModuleNamespaces (): array
164
+ protected function addModuleNamespaces (): void
135
165
{
136
166
$ namespaces = [];
137
- foreach ($ this ->modules as $ module_name => $ module ) {
167
+ foreach ($ this ->moduleData as $ module_name => $ module ) {
138
168
$ module_dir = $ this ->drupalRoot . '/ ' . $ module ->getPath ();
139
169
$ namespaces ["Drupal \\$ module_name " ] = $ module_dir . '/src ' ;
140
170
@@ -158,67 +188,36 @@ protected function getModuleNamespaces(): array
158
188
}
159
189
}
160
190
}
161
-
162
- return $ namespaces ;
191
+ $ this ->registerPs4Namespaces ($ namespaces );
163
192
}
164
-
165
- protected function getThemeNamespaces (): array
193
+ protected function addThemeNamespaces (): void
166
194
{
167
195
$ namespaces = [];
168
- foreach ($ this ->themes as $ theme_name => $ theme ) {
196
+ foreach ($ this ->themeData as $ theme_name => $ theme ) {
169
197
$ theme_dir = $ this ->drupalRoot . '/ ' . $ theme ->getPath ();
170
198
$ namespaces ["Drupal \\$ theme_name " ] = $ theme_dir . '/src ' ;
171
199
}
172
- return $ namespaces ;
200
+ $ this -> registerPs4Namespaces ( $ namespaces) ;
173
201
}
174
202
175
- protected function loadModules ( ): void
203
+ protected function registerPs4Namespaces ( array $ namespaces ): void
176
204
{
177
- foreach ($ this ->modules as $ module_name => $ module ) {
178
- $ module_dir = $ this ->drupalRoot . '/ ' . $ module ->getPath ();
179
- // Need to ensure .module is enabled.
180
- if ($ module ->getExtensionFilename () !== null ) {
181
- try {
182
- require $ module_dir . '/ ' . $ module ->getExtensionFilename ();
183
- } catch (\Throwable $ e ) {
184
- // Something prevent the extension file from loading.
185
- }
186
- }
187
- // Add .post_update.php
188
- if (file_exists ($ module_dir . '/ ' . $ module_name . '.post_update.php ' )) {
189
- require $ module_dir . '/ ' . $ module_name . '.post_update.php ' ;
190
- }
191
- // Add misc .inc that are magically allowed via hook_hook_info.
192
- $ magic_hook_info_includes = [
193
- 'views ' ,
194
- 'views_execution ' ,
195
- 'tokens ' ,
196
- 'search_api ' ,
197
- 'pathauto ' ,
198
- ];
199
- foreach ($ magic_hook_info_includes as $ hook_info_include ) {
200
- if (file_exists ($ module_dir . "/ $ module_name. $ hook_info_include.inc " )) {
201
- require $ module_dir . "/ $ module_name. $ hook_info_include.inc " ;
205
+ foreach ($ namespaces as $ prefix => $ paths ) {
206
+ if (is_array ($ paths )) {
207
+ foreach ($ paths as $ key => $ value ) {
208
+ $ paths [$ key ] = $ value ;
202
209
}
203
210
}
211
+ $ this ->autoloader ->addPsr4 ($ prefix . '\\' , $ paths );
204
212
}
205
213
}
206
-
207
- protected function loadThemes (): void
214
+ protected function loadExtension (Extension $ extension ): void
208
215
{
209
- foreach ($ this ->themes as $ theme_name => $ theme ) {
210
- if ($ theme_name === 'bootstrap ' ) {
211
- continue ;
212
- }
213
- $ theme_dir = $ this ->drupalRoot . '/ ' . $ theme ->getPath ();
214
- // Need to ensure .theme is enabled.
215
- if ($ theme ->getExtensionFilename () !== null ) {
216
- try {
217
- require $ theme_dir . '/ ' . $ theme ->getExtensionFilename ();
218
- } catch (\Throwable $ e ) {
219
- // Something prevent the extension file from loading.
220
- }
221
- }
216
+ try {
217
+ $ extension ->load ();
218
+ } catch (\Throwable $ e ) {
219
+ // Something prevented the extension file from loading.
220
+ // This can happen when drupal_get_path or drupal_get_filename are used outside of the scope of a function.
222
221
}
223
222
}
224
223
}
0 commit comments