ModulesManager   A
last analyzed

Complexity

Total Complexity 42

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 217
rs 9.0399
c 0
b 0
f 0
ccs 0
cts 104
cp 0
wmc 42

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A countModulesInGroup() 0 2 1
A registerModule() 0 3 1
B getLoadOrder() 0 39 11
A loadModules() 0 10 4
A initModules() 0 18 4
B loadModulesFromDirectory() 0 16 7
A getModule() 0 2 4
B getModulesInGroup() 0 22 9

How to fix   Complexity   

Complex Class

Complex classes like ModulesManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ModulesManager, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Created by Gorlum 19.03.2018 19:56
4
 */
5
6
namespace Modules;
7
8
use Modules\sn_module;
9
use Core\GlobalContainer;
10
11
12
/**
13
 * Class ModulesManager
14
 *
15
 * Modules ModulesManager
16
 * Replacement for removed $sn_module and $sn_module_list global variables
17
 *
18
 * @package Modules
19
 */
20
class ModulesManager {
21
  /**
22
   * @var \Core\GlobalContainer $gc
23
   */
24
  protected $gc;
25
26
  /**
27
   * Is modules already loaded?
28
   *
29
   * @var bool $modulesAreLoaded
30
   */
31
  protected $modulesAreLoaded = false;
32
33
  /**
34
   * Plain list of available modules
35
   *
36
   * @var sn_module[] $modules - [(string)$moduleName => (sn_module)$module]
37
   */
38
  protected $modules = [];
39
40
  /**
41
   * Modules arranged per package
42
   *
43
   * @var sn_module[][] $packages - [[(string)$package] => [(string)$moduleName => (sn_module)$module]]
44
   */
45
  protected $packages = [];
46
47
48
  /**
49
   * ModulesManager constructor.
50
   *
51
   * @param GlobalContainer $gc
52
   */
53
  public function __construct($gc) {
54
    $this->gc = $gc;
55
56
    $this->loadModules(SN_ROOT_MODULES);
57
  }
58
59
60
  /**
61
   * @param string $dir_name
62
   */
63
  public function loadModules($dir_name = SN_ROOT_MODULES) {
64
    if ($this->modulesAreLoaded) {
65
      return;
66
    }
67
68
    if (file_exists($dir_name) && is_dir($dir_name)) {
69
      $this->loadModulesFromDirectory($dir_name, PHP_EX);
70
    }
71
72
    $this->modulesAreLoaded = true;
73
  }
74
75
  /**
76
   *
77
   */
78
  public function initModules() {
79
    $loadOrder = $this->getLoadOrder();
80
81
    // Инициализируем модули
82
    // По нормальным делам это должна быть загрузка модулей и лишь затем инициализация - что бы минимизировать размер процесса в памяти
83
    foreach ($loadOrder as $moduleName => $place) {
84
      $module = $this->modules[$moduleName];
85
86
      if ($place >= 0) {
87
        $module->check_status();
88
        if (!$module->isActive()) {
89
          unset($this->modules[$moduleName]);
90
          continue;
91
        }
92
93
        $module->initialize();
94
      } else {
95
        unset($module);
96
      }
97
    }
98
  }
99
100
  /**
101
   * @param $dir_name
102
   * @param $load_extension
103
   */
104
  protected function loadModulesFromDirectory($dir_name, $load_extension) {
105
    $dir = opendir($dir_name);
106
    while (($file = readdir($dir)) !== false) {
107
      if ($file == '..' || $file == '.') {
108
        continue;
109
      }
110
111
      $full_filename = $dir_name . $file;
112
      if (is_dir($full_filename) && file_exists($full_filename = "{$full_filename}/{$file}.{$load_extension}")) {
113
        require_once($full_filename);
114
115
        // Registering module
116
        if (class_exists($file)) {
117
          // TODO Module SHOULD register himself!
118
//          new $file($full_filename)
119
          $this->registerModule($file, new $file($full_filename));
120
        }
121
      }
122
    }
123
  }
124
125
  /**
126
   * Get module load order counting requirements and each module load order
127
   *
128
   * @return int[] - [(string)$moduleName => (int)$loadOrder]
129
   */
130
  protected function getLoadOrder() {
131
    // Генерируем список требуемых модулей
132
    $loadOrder = [];
133
    $sn_req = [];
134
135
    foreach ($this->modules as $loaded_module_name => $module) {
136
      $loadOrder[$loaded_module_name] = $module->getLoadOrder();
137
      if (!empty($module->manifest[sn_module::M_REQUIRE])) {
138
        foreach ($module->manifest[sn_module::M_REQUIRE] as $require_name) {
139
          $sn_req[$loaded_module_name][$require_name] = 0;
140
        }
141
      }
142
    }
143
144
    // Создаем последовательность инициализации модулей
145
    // По нормальным делам надо сначала читать их конфиги - вдруг какой-то модуль отключен?
146
    do {
147
      $prev_order = $loadOrder;
148
149
      foreach ($sn_req as $loaded_module_name => &$req_data) {
150
        $level = 1;
151
        foreach ($req_data as $req_name => &$req_level) {
152
          if ($loadOrder[$req_name] == -1 || !isset($loadOrder[$req_name])) {
153
            $level = $req_level = -1;
154
            break;
155
          } else {
156
            $level += $loadOrder[$req_name];
157
          }
158
          $req_level = $loadOrder[$req_name];
159
        }
160
        if ($level > $loadOrder[$loaded_module_name] || $level == -1) {
161
          $loadOrder[$loaded_module_name] = $level;
162
        }
163
      }
164
    } while ($prev_order != $loadOrder);
165
166
    asort($loadOrder);
167
168
    return $loadOrder;
169
  }
170
171
  /**
172
   * @param string|array $groups - Module group name or '' for any group
173
   * @param bool         $active - returns only active modules
174
   *
175
   * @return int
176
   */
177
  public function countModulesInGroup($groups = '', $active = true) {
178
    return count($this->getModulesInGroup($groups, $active));
179
  }
180
181
  /**
182
   * Getting list of active modules
183
   *
184
   * @param string|array $groups - Module group name or ''|[] for any group
185
   * @param bool         $active - returns only active modules
186
   *
187
   * @return sn_module[]
188
   */
189
  public function getModulesInGroup($groups = [], $active = true) {
190
    // If no groups specified - iterating all groups
191
    if (empty($groups)) {
192
      $groups = array_keys($this->packages);
193
    }
194
195
    if (!is_array($groups)) {
196
      $groups = [$groups];
197
    }
198
199
    $activeModules = [];
200
    foreach ($groups as $groupName) {
201
      if (is_array($this->packages[$groupName]) && !empty($this->packages[$groupName])) {
202
        foreach ($this->packages[$groupName] as $moduleName => $module) {
203
          if (!$active || $module->isActive()) {
204
            $activeModules[$moduleName] = $module;
205
          }
206
        }
207
      }
208
    }
209
210
    return $activeModules;
211
  }
212
213
214
  /**
215
   * Get module by name
216
   *
217
   * @param string $moduleName
218
   * @param bool   $active - return module only if it is active
219
   *
220
   * @return sn_module|null
221
   */
222
  public function getModule($moduleName, $active = true) {
223
    return !empty($this->modules[$moduleName]) && (!$active || $this->modules[$moduleName]->isActive()) ? $this->modules[$moduleName] : null;
224
  }
225
226
  /**
227
   * Register module for further use
228
   *
229
   * Basically modules does not exists anywhere except in Modules ModulesManager
230
   *
231
   * @param string    $moduleName
232
   * @param sn_module $module
233
   */
234
  public function registerModule($moduleName, $module) {
235
    $this->modules[$moduleName] = $module;
236
    $this->packages[$module->manifest['package']][$moduleName] = &$this->modules[$moduleName];
237
  }
238
239
}
240