Skip to content

Commit b9acf69

Browse files
authored
Merge pull request #95 from wunderio/feature/72-Re-add-code-complexity
#72 Add tomasvotruba/cognitive-complexity.
2 parents facc619 + 55f1a4e commit b9acf69

File tree

6 files changed

+273
-225
lines changed

6 files changed

+273
-225
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ jobs:
33
# Install all dependencies and run check tasks.
44
build_and_test:
55
docker:
6-
- image: cimg/php:8.1
6+
- image: cimg/php:8.1.18
77
steps:
88
# Check out source code.
99
- checkout

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
"mglaman/phpstan-drupal": "^1.1",
4646
"phpstan/extension-installer": "^1.1",
4747
"phpstan/phpstan-deprecation-rules": "^1.0",
48+
"nette/finder": "^2.5",
49+
"tomasvotruba/cognitive-complexity": "^0.1.1",
4850
"webflo/drupal-finder": "^1.3"
4951
},
5052
"autoload": {

config/phpstan.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ parameters:
77
- '#Plugin definitions cannot be altered.#'
88
- '#Missing cache backend declaration for performance.#'
99
- '#Plugin manager has cache backend specified but does not declare cache tags.#'
10+
cognitive_complexity:
11+
class: 50
12+
function: 15

phpstan.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ parameters:
77
- '#Plugin definitions cannot be altered.#'
88
- '#Missing cache backend declaration for performance.#'
99
- '#Plugin manager has cache backend specified but does not declare cache tags.#'
10+
cognitive_complexity:
11+
class: 50
12+
function: 15

src/Drupal/DrupalAutoloader.php

Lines changed: 40 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Wunderio\GrumPHP\Drupal;
66

7-
use Drupal\Core\DependencyInjection\ContainerNotInitializedException;
87
use DrupalFinder\DrupalFinderComposerRuntime;
98
use Drush\Drush;
109
use mglaman\PHPStanDrupal\Drupal\Extension;
@@ -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.
@@ -142,6 +78,32 @@ public function register(string $drupalRoot): void {
14278
}
14379
}
14480

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

@@ -176,6 +138,12 @@ public function register(string $drupalRoot): void {
176138
}
177139
}
178140
}
141+
}
142+
143+
/**
144+
* Helper for register() method to include theme files.
145+
*/
146+
private function registerIncludeThemeFiles() {
179147
foreach ($this->themeData as $extension) {
180148
$this->loadExtension($extension);
181149
$theme_dir = $this->drupalRoot . '/' . $extension->getPath();
@@ -184,23 +152,14 @@ public function register(string $drupalRoot): void {
184152
$this->loadAndCatchErrors($theme_settings_file);
185153
}
186154
}
155+
}
187156

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

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

0 commit comments

Comments
 (0)