Passed
Pull Request — 8.x-1.x (#16)
by Frédéric G.
05:02
created

ExternalCode::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 5
c 1
b 0
f 1
dl 0
loc 14
rs 10
cc 1
nc 1
nop 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Drupal\qa\Plugin\QaCheck\System;
6
7
use Drupal\Core\Extension\ModuleExtensionList;
8
use Drupal\Core\Extension\ThemeExtensionList;
9
use Drupal\qa\Data;
10
use Drupal\qa\Pass;
11
use Drupal\qa\Plugin\QaCheckBase;
12
use Drupal\qa\Plugin\QaCheckInterface;
13
use Drupal\qa\Plugin\QaCheckManager;
14
use Drupal\qa\Result;
15
use ReflectionFunction;
16
use Symfony\Component\DependencyInjection\ContainerInterface;
17
18
/**
19
 * ExternalCode identifies code loaded from outside the project root and vendor.
20
 *
21
 * @QaCheck(
22
 *   id = "system.external",
23
 *   label = @Translation("System: external code"),
24
 *   details = @Translation("External code may be the result of an exploit."),
25
 *   usesBatch = false,
26
 *   steps = 1,
27
 * )
28
 */
29
class ExternalCode extends QaCheckBase implements QaCheckInterface {
30
31
  const NAME = 'system.external';
32
33
  /**
34
   * The element_list.module service.
35
   *
36
   * @var \Drupal\Core\Extension\ModuleExtensionList
37
   */
38
  protected $elm;
39
40
  /**
41
   * The extension.list.theme service.
42
   *
43
   * @var \Drupal\Core\Extension\ThemeExtensionList
44
   */
45
  protected $elt;
46
47
  /**
48
   * The list of internal functions.
49
   *
50
   * @var array
51
   */
52
  protected $internalFunctions;
53
54
  /**
55
   * The plugin_manager.qa_check service.
56
   *
57
   * @var \Drupal\qa\Plugin\QaCheckManager
58
   */
59
  protected $qam;
60
61
  /**
62
   * ExternalCode constructor.
63
   *
64
   * @param array $configuration
65
   *   The plugin configuration.
66
   * @param string $id
67
   *   The plugin ID.
68
   * @param array $definition
69
   *   The plugin definition.
70
   * @param \Drupal\Core\Extension\ModuleExtensionList $elm
71
   *   The extension.list.module service.
72
   * @param \Drupal\Core\Extension\ThemeExtensionList $elt
73
   *   The extension.list.theme service.
74
   * @param \Drupal\qa\Plugin\QaCheckManager $qam
75
   *   The plugin_manager.qa_check service.
76
   */
77
  public function __construct(
78
    array $configuration,
79
    string $id,
80
    array $definition,
81
    ModuleExtensionList $elm,
82
    ThemeExtensionList $elt,
83
    QaCheckManager $qam
84
  ) {
85
    parent::__construct($configuration, $id, $definition);
86
    $this->elm = $elm;
87
    $this->elt = $elt;
88
    $this->qam = $qam;
89
90
    $this->qam->initInternalFunctions();
91
  }
92
93
  /**
94
   * {@inheritdoc}
95
   */
96
  public static function create(
97
    ContainerInterface $container,
98
    array $configuration,
99
    $id,
100
    $definition
101
  ) {
102
    $elm = $container->get('extension.list.module');
103
    $elt = $container->get('extension.list.theme');
104
    $qam = $container->get(Data::MANAGER);
105
    return new static($configuration, $id, $definition, $elm, $elt, $qam);
0 ignored issues
show
Bug introduced by
It seems like $qam can also be of type null; however, parameter $qam of Drupal\qa\Plugin\QaCheck...rnalCode::__construct() does only seem to accept Drupal\qa\Plugin\QaCheckManager, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

105
    return new static($configuration, $id, $definition, $elm, $elt, /** @scrutinizer ignore-type */ $qam);
Loading history...
Bug introduced by
It seems like $elt can also be of type null; however, parameter $elt of Drupal\qa\Plugin\QaCheck...rnalCode::__construct() does only seem to accept Drupal\Core\Extension\ThemeExtensionList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

105
    return new static($configuration, $id, $definition, $elm, /** @scrutinizer ignore-type */ $elt, $qam);
Loading history...
Bug introduced by
It seems like $elm can also be of type null; however, parameter $elm of Drupal\qa\Plugin\QaCheck...rnalCode::__construct() does only seem to accept Drupal\Core\Extension\ModuleExtensionList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

105
    return new static($configuration, $id, $definition, /** @scrutinizer ignore-type */ $elm, $elt, $qam);
Loading history...
106
  }
107
108
  /**
109
   * Identify code loaded from outside the web root and vendor directory.
110
   *
111
   * This is not necessarily an issue, but warrants a manual verification.
112
   *
113
   * @return \Drupal\qa\Result
114
   *   The check result.
115
   */
116
  protected function checkExternal(): Result {
117
    $external = [];
118
    $funcs = array_flip(get_defined_functions()['user']);
119
    foreach ($funcs as $func => $_) {
120
      try {
121
        $rf = new ReflectionFunction($func);
122
      }
123
      catch (\ReflectionException $e) {
124
        // XXX probably cannot happen since the function is loaded.
125
        $external[$func] = ('function not found');
126
        continue;
127
      }
128
      $file = realpath($rf->getFileName());
129
      // TODO improve resilience, probably at the cost of computing time.
130
      if (strpos($file, $this->qam->root) === FALSE) {
131
        $external[$func] = $file;
132
      }
133
    }
134
    $res = new Result('external', empty($external), $external);
135
    return $res;
136
137
  }
138
139
  /**
140
   * {@inheritdoc}
141
   */
142
  public function run(): Pass {
143
    $pass = parent::run();
144
    $pass->record($this->checkExternal());
145
    $pass->life->end();
146
    return $pass;
147
  }
148
149
}
150