Passed
Branch 8.x-1.x (e6d5ba)
by Frédéric G.
03:03
created

Dependencies::buildTheming()   B

Complexity

Conditions 7
Paths 11

Size

Total Lines 51
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 33
c 1
b 0
f 0
dl 0
loc 51
rs 8.4586
cc 7
nc 11
nop 1

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Drupal\qa;
4
5
use Drupal\Core\Extension\ModuleExtensionList;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Extension\ModuleExtensionList was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Drupal\Core\Extension\ThemeHandlerInterface;
0 ignored issues
show
Bug introduced by
The type Drupal\Core\Extension\ThemeHandlerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Grafizzi\Graph\Attribute;
8
use Grafizzi\Graph\Cluster;
9
use Grafizzi\Graph\Edge;
10
use Grafizzi\Graph\Graph;
11
use Grafizzi\Graph\Node;
12
use Pimple\Container;
13
use Psr\Log\LoggerInterface;
14
15
class Dependencies {
16
  const SHAPE_THEME = 'octagon';
17
  const SHAPE_ENGINE = 'doubleoctagon';
18
19
  /**
20
   * @var \Grafizzi\Graph\Attribute
21
   */
22
  protected $font;
23
24
  /**
25
   * @var \Psr\Log\LoggerInterface
26
   */
27
  protected $logger;
28
29
  /**
30
   * @var \Drupal\Core\Extension\ModuleExtensionList
31
   */
32
  protected $moduleExtensionList;
33
34
  /**
35
   * @var \Pimple\Container
36
   */
37
  protected $pimple;
38
39
  /**
40
   * @var \Drupal\Core\Extension\ThemeHandlerInterface
41
   */
42
  protected $themeHandler;
43
44
  public function __construct(
45
    ThemeHandlerInterface $themeHandler,
46
    ModuleExtensionList $moduleExtensionList,
47
    LoggerInterface $logger
48
  ) {
49
    $this->logger = $logger;
50
    $this->moduleExtensionList = $moduleExtensionList;
51
    $this->pimple = new Container(['logger' => $logger]);
52
    $this->themeHandler = $themeHandler;
53
54
    $this->font = $this->attr("fontsize", 10);
55
  }
56
57
58
  /**
59
   * Clone of function _graphviz_create_filepath() from graphviz_filter.module.
60
   *
61
   * @param string $path
62
   * @param string $filename
63
   *
64
   * @return string
65
   */
66
  public function graphvizCreateFilepath($path, $filename) {
67
    if (!empty($path)) {
68
      return rtrim($path, '/') .'/'. $filename;
69
    }
70
    return $filename;
71
  }
72
73
  /**
74
   * Facade for Grafizzi Attribute constructor.
75
   *
76
   * @param $name
77
   * @param $value
78
   *
79
   * @return \Grafizzi\Graph\Attribute
80
   */
81
  public function attr(string $name, string $value) : Attribute {
82
    return new Attribute($this->pimple, $name, $value);
83
  }
84
85
  public function edge(Node $from, Node $to, array $attrs) : Edge {
86
    return new Edge($this->pimple, $from, $to, $attrs);
87
  }
88
89
  /**
90
   * Facade for Grafizzi Node constructor.
91
   *
92
   * Strips the optional "namespace" (aka project or package) part of the name.
93
   *
94
   * @param string $name
95
   * @param \Grafizzi\Graph\Attribute[] $attrs
96
   *
97
   * @return \Grafizzi\Graph\Node
98
   */
99
  public function node(string $name, array $attrs = []) : Node {
100
    // Strip the "namespace" part.
101
    $arName = explode(':', $name);
102
    $localName = array_pop($arName);
103
104
    $arLocal = explode(' ', $localName);
105
    $simpleName = current($arLocal);
106
    return new Node($this->pimple, $simpleName, $attrs);
107
  }
108
109
  /**
110
   * Facade for Grafizzi Cluster constructor.
111
   *
112
   * @param string $name
113
   *
114
   * @return \Grafizzi\Graph\Cluster
115
   */
116
  public function cluster(string $name, array $attrs = []): Cluster {
117
    return new Cluster($this->pimple, urlencode($name), [
118
      $this->attr('label', $name),
119
    ] + $attrs);
120
  }
121
122
  protected function initGraph() : Graph {
123
    $g = new Graph($this->pimple, "deps", [
124
      $this->attr("rankdir", "RL"),
125
    ]);
126
    $g->setDirected(TRUE);
127
    return $g;
128
  }
129
130
  public function buildModules(Graph $g) : Graph {
131
    $modules = $this->moduleExtensionList->reset()->getList();
132
    krsort($modules);
133
134
    $packages = [];
135
136
    foreach ($modules as $module => $detail) {
137
      if (!$detail->status) {
138
        continue;
139
      }
140
      $package = $detail->info['package'] ?? '';
141
      if (!empty($package)) {
142
        if (!isset($packages[$package])) {
143
          $packageCluster = $this->cluster($package);
144
          $packages[$package] = $packageCluster;
145
          $g->addChild($packageCluster);
146
        }
147
        else {
148
          /** @var \Grafizzi\Graph\Cluster $packageCluster */
149
          $packageCluster = $packages[$package];
150
        }
151
152
        $packageCluster->addChild($from = $this->node("${package}:${module}", [$this->font]));
153
      }
154
      else {
155
        $g->addChild($from = $this->node($module, [$this->font]));
156
      }
157
158
      $dependencies = $detail->info['dependencies'] ?? [];
159
      foreach ($dependencies as $depend) {
160
        $to = $this->node($depend, [$this->font]);
161
        $g->addChild(
162
          $this->edge($from, $to, [
163
            $this->font,
164
            $this->attr('color', 'lightgray'),
165
          ]));
166
      }
167
    }
168
    return $g;
169
  }
170
171
  protected function buildTheming(Graph $g) : Graph {
172
    $engineShape = $this->attr('shape', static::SHAPE_ENGINE);
173
    $themeShape = $this->attr('shape', static::SHAPE_THEME);
174
    $engineLine = $this->attr('style', 'dotted');
175
    $baseLine = $this->attr('style', 'dashed');
176
177
    $themeList = $this->themeHandler->listInfo();
178
    krsort($themeList);
179
180
    $engines = [];
181
    $themes = [];
182
183
    foreach ($themeList as $theme => $detail) {
184
      if (empty($detail->status)) {
185
        continue;
186
      }
187
188
      // Build theme engine links.
189
      $themes[$theme] = $from = $this->node($theme, [$this->font, $themeShape]);
190
      $g->addChild($from);
191
      if (!empty($detail->owner)) {
192
        // D8 still theoretically supports multiple engines (e.g. nyan_cat).
193
        $engine = basename($detail->owner); // with extension
194
        $engineBase = basename($engine, '.engine');
195
        if (!isset($engines[$engineBase])) {
196
          $engines[$engineBase] = $engineNode = $this->node($engineBase, [
197
            $engineShape,
198
          ]);
199
          $g->addChild($engineCluster = $this->cluster($engineBase, [$this->font]));
200
          $engineCluster->addChild($engineNode);
201
        }
202
        $to = $engines[$engineBase];
203
        $g->addChild($this->edge($from, $to, [$this->font, $engineLine]));
204
      }
205
      else {
206
        $g->addChild($from);
207
      }
208
209
      // Build base theme links.
210
      $toName = $detail->base_theme ?? '';
211
      if (!empty($toName)) {
212
        $to = $themes[$toName];
213
        if (empty($to)) {
214
          $to = $this->node($toName, [$this->font]);
215
          $g->addChild($to);
216
        }
217
        $g->addChild($this->edge($from, $to, [$this->font, $baseLine]));
218
      }
219
    }
220
221
    return $g;
222
  }
223
224
  public function build() : Graph {
225
    // @see https://wiki.php.net/rfc/pipe-operator
226
    $g = $this->initGraph();
227
    $g = $this->buildModules($g);
228
    //$g = $this->buildTheming($g);
229
    return $g;
230
  }
231
232
}
233