Skip to content

Commit

Permalink
Handle dynamic file loading with module_load_include
Browse files Browse the repository at this point in the history
Fixes #166
  • Loading branch information
mglaman committed May 12, 2021
1 parent 74e75c4 commit 642a995
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 0 deletions.
5 changes: 5 additions & 0 deletions extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,8 @@ services:
tags: [phpstan.rules.rule]
arguments:
- %drupal.drupal_root%
-
class: PHPStan\Rules\Drupal\ModuleLoadInclude
tags: [phpstan.rules.rule]
arguments:
- %drupal.drupal_root%
88 changes: 88 additions & 0 deletions src/Rules/Drupal/ModuleLoadInclude.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php declare(strict_types=1);

namespace PHPStan\Rules\Drupal;

use DrupalFinder\DrupalFinder;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Drupal\ExtensionDiscovery;
use PHPStan\Rules\Rule;

/**
* Handles module_load_include dynamic file loading.
*
* @note may become deprecated and removed in D10
* @see https://www.drupal.org/project/drupal/issues/697946
*/
class ModuleLoadInclude implements Rule
{

/**
* The project root.
*
* @var string
*/
protected $projectRoot;

/**
* ModuleLoadInclude constructor.
* @param string $project_root
*/
public function __construct(string $project_root)
{
$this->projectRoot = $project_root;
}

public function getNodeType(): string
{
return Node\Expr\FuncCall::class;
}

public function processNode(Node $node, Scope $scope): array
{
assert($node instanceof Node\Expr\FuncCall);
if (!$node->name instanceof \PhpParser\Node\Name) {
return [];
}
$name = (string) $node->name;
if ($name !== 'module_load_include') {
return [];
}
$stop = null;

try {
// Try to invoke it similarily as the module handler itself.
$finder = new DrupalFinder();
$finder->locateRoot($this->projectRoot);
$drupal_root = $finder->getDrupalRoot();
$extensionDiscovery = new ExtensionDiscovery($drupal_root);
$modules = $extensionDiscovery->scan('module');
$type_arg = $node->args[0];
assert($type_arg->value instanceof Node\Scalar\String_);
$module_arg = $node->args[1];
assert($module_arg->value instanceof Node\Scalar\String_);
$name_arg = $node->args[2] ?? null;

if ($name_arg === null) {
$name_arg = $module_arg;
}
assert($name_arg->value instanceof Node\Scalar\String_);

$module_name = $module_arg->value->value;
if (!isset($modules[$module_name])) {
return [];
}
$type_prefix = $name_arg->value->value;
$type_filename = $type_arg->value->value;
$module = $modules[$module_name];
$file = $drupal_root . '/' . $module->getPath() . "/$type_prefix.$type_filename";
if (is_file($file)) {
require_once $file;
return [];
}
return [sprintf('File %s could not be loaded from module_load_include', $file)];
} catch (\Throwable $e) {
return ['A file could not be loaded from module_load_include'];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type: module
name: Module with tests
core: 8.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php declare(strict_types=1);

function test_locale_translation_inc_included() {
module_load_include('bulk.inc', 'locale');
locale_translate_get_interface_translation_files();
module_load_include('compare.inc', 'locale');
locale_translation_build_projects();
module_load_include('translation.inc', 'locale');
locale_translation_build_sources();
}
6 changes: 6 additions & 0 deletions tests/src/DrupalIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,10 @@ public function testThemeSettingsFile() {
$this->assertCount(0, $errors->getErrors(), var_export($errors, TRUE));
$this->assertCount(0, $errors->getInternalErrors(), var_export($errors, TRUE));
}

public function testModuleLoadInclude() {
$errors = $this->runAnalyze(__DIR__ . '/../fixtures/drupal/modules/module_load_include_fixture/module_load_include_fixture.module');
$this->assertCount(0, $errors->getErrors(), var_export($errors, TRUE));
$this->assertCount(0, $errors->getInternalErrors(), var_export($errors, TRUE));
}
}

0 comments on commit 642a995

Please sign in to comment.