Passed
Push — master ( d15464...d64dd2 )
by Alexey
05:25
created

Modules   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 262
Duplicated Lines 6.49 %

Coupling/Cohesion

Components 0
Dependencies 8

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 17
loc 262
ccs 0
cts 225
cp 0
rs 5.1724
c 0
b 0
f 0
wmc 57
lcom 0
cbo 8

11 Methods

Rating   Name   Duplication   Size   Complexity  
A createBlankModule() 0 11 1
A parseColsForModel() 0 20 4
C parseColsForTable() 0 38 13
B generateModel() 0 31 4
C install() 4 34 8
C unInstall() 4 34 8
A addInMenu() 0 13 3
D getSelectListModels() 9 27 10
A getModelsList() 0 16 4
A createController() 0 13 1
A addActionToController() 0 12 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Modules 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 Modules, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Modules module
5
 *
6
 * @author Alexey Krupskiy <[email protected]>
7
 * @link http://inji.ru/
8
 * @copyright 2015 Alexey Krupskiy
9
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
10
 */
11
class Modules extends Module {
12
13
    public function createBlankModule($name, $codeName) {
14
        $codeName = ucfirst($codeName);
15
        Tools::createDir(App::$primary->path . '/modules/' . $codeName);
16
        ob_start();
17
        include $this->path . '/tpls/BlankModule.php';
18
        $moduleCode = ob_get_contents();
19
        ob_end_clean();
20
        file_put_contents(App::$primary->path . '/modules/' . $codeName . '/' . $codeName . '.php', $moduleCode);
21
        file_put_contents(App::$primary->path . '/modules/' . $codeName . '/info.php', "<?php\nreturn " . CodeGenerator::genArray(['name' => $name]));
22
        file_put_contents(App::$primary->path . '/modules/' . $codeName . '/generatorHash.php', "<?php\nreturn " . CodeGenerator::genArray([$codeName . '.php' => md5($moduleCode)]));
23
    }
24
25
    public function parseColsForModel($cols = []) {
26
        $modelCols = [ 'labels' => [], 'cols' => [], 'relations' => []];
27
        foreach ($cols as $col) {
28
            $modelCols['labels'][$col['code']] = $col['label'];
29
            $colType = !empty($col['type']['primary']) ? $col['type']['primary'] : $col['type'];
30
            switch ($colType) {
31
                case 'relation':
32
                    $relationName = Tools::randomString();
33
                    $modelCols['cols'][$col['code']] = ['type' => 'select', 'source' => 'relation', 'relation' => $relationName, 'showCol' => 'name'];
34
                    $modelCols['relations'][$relationName] = [
35
                        'model' => $col['type']['aditional'],
36
                        'col' => $col['code']
37
                    ];
38
                    break;
39
                default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
40
                    $modelCols['cols'][$col['code']] = ['type' => $colType];
41
            }
42
        }
43
        return $modelCols;
44
    }
45
46
    public function parseColsForTable($cols, $colPrefix, $tableName) {
47
48
        $colsExist = App::$cur->db->getTableCols($tableName);
49
        $tableCols = [];
50
        if (empty($colsExist[$colPrefix . 'id'])) {
51
            $tableCols[$colPrefix . 'id'] = 'pk';
52
        }
53
        foreach ($cols as $col) {
54
            if (!empty($colsExist[$colPrefix . $col['code']])) {
55
                continue;
56
            }
57
            $colType = !empty($col['type']['primary']) ? $col['type']['primary'] : $col['type'];
58
            switch ($colType) {
59
                case 'image':
60
                case 'number':
61
                case 'relation':
62
                    $tableCols[$colPrefix . $col['code']] = 'int(11) NOT NULL';
63
                    break;
64
                case 'decimal':
65
                    $tableCols[$colPrefix . $col['code']] = 'decimal(11,2) NOT NULL';
66
                    break;
67
                case 'dateTime':
68
                    $tableCols[$colPrefix . $col['code']] = 'timestamp NOT NULL';
69
                    break;
70
                case 'currentDateTime':
71
                    $tableCols[$colPrefix . $col['code']] = 'timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP';
72
                    break;
73
                case 'text':
74
                    $tableCols[$colPrefix . $col['code']] = 'varchar(255) NOT NULL';
75
                    break;
76
                case 'textarea':
77
                default:
78
                    $tableCols[$colPrefix . $col['code']] = 'text NOT NULL';
79
                    break;
80
            }
81
        }
82
        return $tableCols;
83
    }
84
85
    public function generateModel($module, $name, $codeName, $options) {
86
        $codeName = ucfirst($codeName);
87
        $class = new CodeGenerator\ClassGenerator();
88
        $class->name = $codeName;
89
        $class->extends = '\Model';
90
        $modelCols = $this->parseColsForModel();
91
        if (!empty($options['cols'])) {
92
            $modelCols = $this->parseColsForModel($options['cols']);
93
            $tableName = strtolower($module) . '_' . strtolower($codeName);
94
            $tableCols = $this->parseColsForTable($options['cols'], strtolower($codeName) . '_', $tableName);
95
            if (App::$cur->db->tableExist($tableName)) {
96
                foreach ($tableCols as $colKey => $params) {
97
                    App::$cur->db->add_col($tableName, $colKey, $params);
98
                }
99
            } else {
100
                App::$cur->db->createTable($tableName, $tableCols);
101
            }
102
        }
103
        $class->addProperty('objectName', $name, true);
104
        $class->addProperty('cols', $modelCols['cols'], true);
105
        $class->addProperty('labels', $modelCols['labels'], true);
106
        $class->addMethod('relations', 'return ' . CodeGenerator::genArray($modelCols['relations']), [], true);
107
        $modelCode = "<?php \n\nnamespace {$module};\n\n" . $class->generate();
108
109
        $modulePath = Module::getModulePath($module);
110
        Tools::createDir($modulePath . '/models');
111
        file_put_contents($modulePath . '/models/' . $codeName . '.php', $modelCode);
112
        $config = Config::custom($modulePath . '/generatorHash.php');
113
        $config['models/' . $codeName . '.php'] = md5($modelCode);
114
        Config::save($modulePath . '/generatorHash.php', $config);
115
    }
116
117
    public function install($module, $params = []) {
118
        $installed = Module::getInstalled(App::$primary);
119
        if (in_array($module, $installed)) {
120
            return true;
121
        }
122
        $info = Module::getInfo($module);
123
        if (!empty($info['requires'])) {
124
            foreach ($info['requires'] as $requireModuleName) {
125
                $this->install($requireModuleName);
126
            }
127
        }
128
129
        $config = Config::app();
130
131
        $type = 'modules';
132
133
        $path = INJI_SYSTEM_DIR . '/modules/';
134
        $location = 'modules';
135
136
        $config[$location][] = $module;
137
        if (!empty($info['autoload'])) {
138
            $config['autoloadModules'][] = $module;
139
        }
140
        if (!empty($info['menu'])) {
141
            foreach ($info['menu'] as $appType => $items) {
142
                $this->addInMenu($items, $appType);
143
            }
144
        }
145
        Config::save('app', $config, null, App::$primary);
146 View Code Duplication
        if (file_exists($path . $module . '/install_script.php')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
            $installFunction = include $path . $module . '/install_script.php';
148
            $installFunction(1, $params);
149
        }
150
    }
151
152
    public function unInstall($module, $params = []) {
153
        $installed = Module::getInstalled(App::$primary);
154
        if (!in_array($module, $installed)) {
155
            return true;
156
        }
157
        $info = Module::getInfo($module);
158
159
        $config = Config::app();
160
161
        $type = 'modules';
162
163
        $path = INJI_SYSTEM_DIR . '/modules/';
164
        $location = 'modules';
165
166
        foreach ($config[$location] as $key => $moduleName) {
167
            if ($moduleName == $module) {
168
                unset($config[$location][$key]);
169
                break;
170
            }
171
        }
172
        if (!empty($config['autoload'])) {
173
            foreach ($config['autoload'] as $key => $moduleName) {
174
                if ($moduleName == $module) {
175
                    unset($config['autoload'][$key]);
176
                    break;
177
                }
178
            }
179
        }
180
        Config::save('app', $config, null, App::$primary);
181 View Code Duplication
        if (file_exists($path . $module . '/uninstall_script.php')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
182
            $installFunction = include $path . $module . '/uninstall_script.php';
183
            $installFunction(1, $params);
184
        }
185
    }
186
187
    public function addInMenu($items, $appType, $parent = 0) {
188
        foreach ($items as $item) {
189
            $menuItem = new \Menu\Item();
190
            $menuItem->name = $item['name'];
191
            $menuItem->href = $item['href'];
192
            $menuItem->Menu_id = 1;
193
            $menuItem->parent_id = $parent;
194
            $menuItem->save(['appType' => $appType]);
195
            if (!empty($item['childs'])) {
196
                $this->addInMenu($item['childs'], $appType, $menuItem->pk());
197
            }
198
        }
199
    }
200
201
    public function getSelectListModels($module = '') {
202
        $models = [];
203
        if ($module) {
204
            $modelsNames = $this->getModelsList($module);
205
206
            $info = Modules::getInfo($module);
207
            $moduleName = !empty($info['name']) ? $info['name'] : $module;
208 View Code Duplication
            foreach ($modelsNames as $modelName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
209
                $fullModelName = $module . '\\' . $modelName;
210
                $models[$fullModelName] = $moduleName . ' - ' . ($fullModelName::$objectName ? $fullModelName::$objectName : $modelName);
211
            }
212
        }
213
        foreach (App::$primary->config['modules'] as $configModule) {
214
            if ($module == $configModule) {
215
                continue;
216
            }
217
            $modelsNames = $this->getModelsList($configModule);
218
            $info = Modules::getInfo($configModule);
219
            $moduleName = !empty($info['name']) ? $info['name'] : $configModule;
220 View Code Duplication
            foreach ($modelsNames as $modelName) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
                $fullModelName = $configModule . '\\' . $modelName;
222
                Router::loadClass($fullModelName);
223
                $models[$fullModelName] = $moduleName . ' - ' . ($fullModelName::$objectName ? $fullModelName::$objectName : $modelName);
224
            }
225
        }
226
        return $models;
227
    }
228
229
    public function getModelsList($module, $dir = '') {
230
        $modulePath = Module::getModulePath($module);
231
        $path = rtrim($modulePath . '/models/' . $dir, '/');
232
        $models = [];
233
        if (file_exists($path)) {
234
            foreach (array_slice(scandir($path), 2) as $file) {
235
                $modelLastName = pathinfo($file, PATHINFO_FILENAME);
236
                if (is_dir($path . '/' . $file)) {
237
                    $models = array_merge($models, $this->getModelsList($module, $dir . '/' . $modelLastName));
238
                }
239
                $nameSpace = trim(preg_replace('!/' . $modelLastName . '$!', '', $dir), '/');
240
                $models[] = trim(str_replace('/', '\\', $nameSpace) . '\\' . $modelLastName, '\\');
241
            }
242
        }
243
        return $models;
244
    }
245
246
    public function createController($module, $controllerType) {
247
        $modulePath = Module::getModulePath($module);
248
        $path = $modulePath . '/' . $controllerType . '/' . $module . 'Controller.php';
249
        $class = new CodeGenerator\ClassGenerator();
250
        $class->name = $module . 'Controller';
251
        $class->extends = 'Controller';
252
        $controllerCode = "<?php\n\n" . $class->generate();
253
        Tools::createDir(pathinfo($path, PATHINFO_DIRNAME));
254
        file_put_contents($path, $controllerCode);
255
        $config = Config::custom($modulePath . '/generatorHash.php');
256
        $config[$controllerType . '/' . $module . 'Controller.php'] = md5($controllerCode);
257
        Config::save($modulePath . '/generatorHash.php', $config);
258
    }
259
260
    public function addActionToController($module, $type, $controller, $url) {
261
        $modulePath = Module::getModulePath($module);
262
        $path = Modules::getModulePath($module) . '/' . $type . '/' . $controller . '.php';
263
        $class = CodeGenerator::parseClass($path);
264
        $class->addMethod($url . 'Action');
265
        $controllerCode = "<?php\n\n" . $class->generate();
266
        Tools::createDir(pathinfo($path, PATHINFO_DIRNAME));
267
        file_put_contents($path, $controllerCode);
268
        $config = Config::custom($modulePath . '/generatorHash.php');
269
        $config[$type . '/' . $module . 'Controller.php'] = md5($controllerCode);
270
        Config::save($modulePath . '/generatorHash.php', $config);
271
    }
272
}