Skip to content

Commit 11101c9

Browse files
committed
#72 Fix code complexity in Psalm Drupal autoloader.
1 parent ab6b5dd commit 11101c9

File tree

2 files changed

+264
-224
lines changed

2 files changed

+264
-224
lines changed

src/Drupal/DrupalAutoloader.php

Lines changed: 40 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Wunderio\GrumPHP\Drupal;
66

77
use DrupalFinder\DrupalFinder;
8-
use Drupal\Core\DependencyInjection\ContainerNotInitializedException;
98
use Drush\Drush;
109
use Nette\Utils\Finder;
1110
use PHPUnit\Framework\Test;
@@ -18,70 +17,7 @@
1817
*
1918
* Code re-used from https://github.com/mglaman/phpstan-drupal/blob/main/src/Drupal/DrupalAutoloader.php.
2019
*/
21-
class DrupalAutoloader {
22-
23-
/**
24-
* Drupal autoloader.
25-
*
26-
* @var \Composer\Autoload\ClassLoader
27-
*/
28-
private $autoloader;
29-
30-
/**
31-
* Path to Drupal root.
32-
*
33-
* @var string
34-
*/
35-
private $drupalRoot;
36-
37-
/**
38-
* List of available modules.
39-
*
40-
* @var array
41-
*/
42-
protected $moduleData = [];
43-
44-
/**
45-
* List of available themes.
46-
*
47-
* @var array
48-
*/
49-
protected $themeData = [];
50-
51-
/**
52-
* Array of Drupal service mapping.
53-
*
54-
* @var array
55-
*/
56-
private $serviceMap = [];
57-
58-
/**
59-
* Array of Drupal service yml files.
60-
*
61-
* @var array
62-
*/
63-
private $serviceYamls = [];
64-
65-
/**
66-
* Array of service class providers.
67-
*
68-
* @var array
69-
*/
70-
private $serviceClassProviders = [];
71-
72-
/**
73-
* ExtensionDiscovery object.
74-
*
75-
* @var \mglaman\PHPStanDrupal\Drupal\ExtensionDiscovery
76-
*/
77-
private $extensionDiscovery;
78-
79-
/**
80-
* Array of Drupal namespaces.
81-
*
82-
* @var array
83-
*/
84-
private $namespaces = [];
20+
class DrupalAutoloader extends DrupalAutoloaderBase {
8521

8622
/**
8723
* Load in Drupal code from defined path.
@@ -143,6 +79,32 @@ public function register(string $drupalRoot): void {
14379
}
14480
}
14581

82+
$this->registerIncludeModuleFiles();
83+
$this->registerIncludeThemeFiles();
84+
85+
if (class_exists(Drush::class)) {
86+
$reflect = new \ReflectionClass(Drush::class);
87+
if ($reflect->getFileName() !== FALSE) {
88+
$levels = 2;
89+
if (Drush::getMajorVersion() < 9) {
90+
$levels = 3;
91+
}
92+
$drushDir = dirname($reflect->getFileName(), $levels);
93+
/** @var \SplFileInfo $file */
94+
foreach (Finder::findFiles('*.inc')->in($drushDir . '/includes') as $file) {
95+
// phpcs:ignore PHPCS_SecurityAudit.Misc.IncludeMismatch.ErrMiscIncludeMismatchNoExt
96+
require_once $file->getPathname();
97+
}
98+
}
99+
}
100+
101+
$this->registerIncludeServicesFromYamls();
102+
}
103+
104+
/**
105+
* Helper for register() method to include module files.
106+
*/
107+
private function registerIncludeModuleFiles() {
146108
foreach ($this->moduleData as $extension) {
147109
$this->loadExtension($extension);
148110

@@ -177,6 +139,12 @@ public function register(string $drupalRoot): void {
177139
}
178140
}
179141
}
142+
}
143+
144+
/**
145+
* Helper for register() method to include theme files.
146+
*/
147+
private function registerIncludeThemeFiles() {
180148
foreach ($this->themeData as $extension) {
181149
$this->loadExtension($extension);
182150
$theme_dir = $this->drupalRoot . '/' . $extension->getPath();
@@ -185,23 +153,14 @@ public function register(string $drupalRoot): void {
185153
$this->loadAndCatchErrors($theme_settings_file);
186154
}
187155
}
156+
}
188157

189-
if (class_exists(Drush::class)) {
190-
$reflect = new \ReflectionClass(Drush::class);
191-
if ($reflect->getFileName() !== FALSE) {
192-
$levels = 2;
193-
if (Drush::getMajorVersion() < 9) {
194-
$levels = 3;
195-
}
196-
$drushDir = dirname($reflect->getFileName(), $levels);
197-
/** @var \SplFileInfo $file */
198-
foreach (Finder::findFiles('*.inc')->in($drushDir . '/includes') as $file) {
199-
// phpcs:ignore PHPCS_SecurityAudit.Misc.IncludeMismatch.ErrMiscIncludeMismatchNoExt
200-
require_once $file->getPathname();
201-
}
202-
}
203-
}
204-
158+
/**
159+
* Helper for register() method to include services.
160+
*
161+
* @todo Fix this method not being properly used - see https://github.com/wunderio/code-quality/issues/96 for more info.
162+
*/
163+
private function registerIncludeServicesFromYamls() {
205164
foreach ($this->serviceYamls as $extension => $serviceYaml) {
206165
$yaml = Yaml::parseFile($serviceYaml);
207166
// Weed out service files which only provide parameters.
@@ -246,147 +205,4 @@ public function register(string $drupalRoot): void {
246205
}
247206
}
248207

249-
/**
250-
* Load legacy includes.
251-
*/
252-
protected function loadLegacyIncludes(): void {
253-
/** @var \SplFileInfo $file */
254-
foreach (Finder::findFiles('*.inc')->in($this->drupalRoot . '/core/includes') as $file) {
255-
// phpcs:ignore PHPCS_SecurityAudit.Misc.IncludeMismatch.ErrMiscIncludeMismatchNoExt
256-
require_once $file->getPathname();
257-
}
258-
}
259-
260-
/**
261-
* Add core test namespaces.
262-
*/
263-
protected function addTestNamespaces(): void {
264-
$core_tests_dir = $this->drupalRoot . '/core/tests/Drupal';
265-
$this->namespaces['Drupal\\BuildTests'] = $core_tests_dir . '/BuildTests';
266-
$this->namespaces['Drupal\\FunctionalJavascriptTests'] = $core_tests_dir . '/FunctionalJavascriptTests';
267-
$this->namespaces['Drupal\\FunctionalTests'] = $core_tests_dir . '/FunctionalTests';
268-
$this->namespaces['Drupal\\KernelTests'] = $core_tests_dir . '/KernelTests';
269-
$this->namespaces['Drupal\\Tests'] = $core_tests_dir . '/Tests';
270-
$this->namespaces['Drupal\\TestSite'] = $core_tests_dir . '/TestSite';
271-
$this->namespaces['Drupal\\TestTools'] = $core_tests_dir . '/TestTools';
272-
$this->namespaces['Drupal\\Tests\\TestSuites'] = $this->drupalRoot . '/core/tests/TestSuites';
273-
}
274-
275-
/**
276-
* Add Drupal module namespaces.
277-
*/
278-
protected function addModuleNamespaces(): void {
279-
foreach ($this->moduleData as $module) {
280-
$module_name = $module->getName();
281-
$module_dir = $this->drupalRoot . '/' . $module->getPath();
282-
$this->namespaces["Drupal\\$module_name"] = $module_dir . '/src';
283-
284-
// Extensions can have a \Drupal\Tests\extension namespace for test
285-
// cases, traits, and other classes such
286-
// as those that extend \Drupal\TestSite\TestSetupInterface.
287-
// @see drupal_phpunit_get_extension_namespaces()
288-
$module_test_dir = $module_dir . '/tests/src';
289-
if (is_dir($module_test_dir)) {
290-
$this->namespaces["Drupal\\Tests\\$module_name"] = $module_test_dir;
291-
}
292-
293-
$servicesFileName = $module_dir . '/' . $module_name . '.services.yml';
294-
if (file_exists($servicesFileName)) {
295-
$this->serviceYamls[$module_name] = $servicesFileName;
296-
}
297-
$camelized = $this->camelize($module_name);
298-
$name = "{$camelized}ServiceProvider";
299-
$class = "Drupal\\{$module_name}\\{$name}";
300-
301-
$this->serviceClassProviders[$module_name] = $class;
302-
$serviceId = "service_provider.$module_name.service_provider";
303-
$this->serviceMap[$serviceId] = ['class' => $class];
304-
}
305-
}
306-
307-
/**
308-
* Add Drupal theme namespaces.
309-
*/
310-
protected function addThemeNamespaces(): void {
311-
foreach ($this->themeData as $theme_name => $theme) {
312-
$theme_dir = $this->drupalRoot . '/' . $theme->getPath();
313-
$this->namespaces["Drupal\\$theme_name"] = $theme_dir . '/src';
314-
}
315-
}
316-
317-
/**
318-
* Register PS4 namespaces.
319-
*
320-
* @param array $namespaces
321-
* An array of namespaces to load.
322-
*/
323-
protected function registerPs4Namespaces(array $namespaces): void {
324-
foreach ($namespaces as $prefix => $paths) {
325-
if (is_array($paths)) {
326-
foreach ($paths as $key => $value) {
327-
$paths[$key] = $value;
328-
}
329-
}
330-
$this->autoloader->addPsr4($prefix . '\\', $paths);
331-
}
332-
}
333-
334-
/**
335-
* Loads in extensions (modules, themes, etc).
336-
*
337-
* Wrapper for \mglaman\PHPStanDrupal\Drupal\Extension->load().
338-
*
339-
* @param \mglaman\PHPStanDrupal\Drupal\Extension $extension
340-
* Extension object.
341-
*/
342-
protected function loadExtension(Extension $extension): void {
343-
try {
344-
$extension->load();
345-
}
346-
catch (\Throwable $e) {
347-
// Something prevented the extension file from loading.
348-
// This can happen when drupal_get_path or drupal_get_filename are used
349-
// outside the scope of a function.
350-
}
351-
}
352-
353-
/**
354-
* Wrapper for require_once() that catches errors.
355-
*
356-
* @param string $path
357-
* Path to file.
358-
*/
359-
protected function loadAndCatchErrors(string $path): void {
360-
try {
361-
// phpcs:ignore PHPCS_SecurityAudit.Misc.IncludeMismatch.ErrMiscIncludeMismatchNoExt
362-
require_once $path;
363-
}
364-
catch (ContainerNotInitializedException $e) {
365-
$path = str_replace(dirname($this->drupalRoot) . '/', '', $path);
366-
// This can happen when drupal_get_path or drupal_get_filename are used
367-
// outside the scope of a function.
368-
@trigger_error("$path invoked the Drupal container outside of the scope of a function or class method. It was not loaded.", E_USER_WARNING);
369-
}
370-
catch (\Throwable $e) {
371-
$path = str_replace(dirname($this->drupalRoot) . '/', '', $path);
372-
// Something prevented the extension file from loading.
373-
@trigger_error("$path failed loading due to {$e->getMessage()}", E_USER_WARNING);
374-
}
375-
}
376-
377-
/**
378-
* Camelizes a string.
379-
*
380-
* @todo Should we use method from Symfony\Component\DependencyInjection\Container instead?
381-
*
382-
* @param string $id
383-
* A string to camelize.
384-
*
385-
* @return string
386-
* The camelized string.
387-
*/
388-
protected function camelize(string $id): string {
389-
return strtr(ucwords(strtr($id, ['_' => ' ', '.' => '_ ', '\\' => '_ '])), [' ' => '']);
390-
}
391-
392208
}

0 commit comments

Comments
 (0)