Failed Conditions
Pull Request — master (#39)
by Tobias
20:44
created

ModuleCommandHandler::printModuleTable()   C

Complexity

Conditions 11
Paths 72

Size

Total Lines 28
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 28
rs 5.2653
cc 11
eloc 19
nc 72
nop 4

How to fix   Complexity   

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
/*
4
 * This file is part of the puli/cli package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\Cli\Handler;
13
14
use Puli\Cli\Style\PuliTableStyle;
15
use Puli\Cli\Util\StringUtil;
16
use Puli\Manager\Api\Environment;
17
use Puli\Manager\Api\Module\Module;
18
use Puli\Manager\Api\Module\ModuleList;
19
use Puli\Manager\Api\Module\ModuleManager;
20
use Puli\Manager\Api\Module\ModuleState;
21
use RuntimeException;
22
use Webmozart\Console\Api\Args\Args;
23
use Webmozart\Console\Api\IO\IO;
24
use Webmozart\Console\UI\Component\Table;
25
use Webmozart\Expression\Expr;
26
use Webmozart\PathUtil\Path;
27
28
/**
29
 * Handles the "module" command.
30
 *
31
 * @since  1.0
32
 *
33
 * @author Bernhard Schussek <[email protected]>
34
 */
35
class ModuleCommandHandler
36
{
37
    /**
38
     * @var array
39
     */
40
    private static $stateStrings = array(
41
        ModuleState::ENABLED => 'enabled',
42
        ModuleState::NOT_FOUND => 'not-found',
43
        ModuleState::NOT_LOADABLE => 'not-loadable',
44
    );
45
46
    /**
47
     * @var ModuleManager
48
     */
49
    private $moduleManager;
50
51
    /**
52
     * Creates the handler.
53
     *
54
     * @param ModuleManager $moduleManager The module manager
55
     */
56
    public function __construct(ModuleManager $moduleManager)
57
    {
58
        $this->moduleManager = $moduleManager;
59
    }
60
61
    /**
62
     * Handles the "module --list" command.
63
     *
64
     * @param Args $args The console arguments
65
     * @param IO   $io   The I/O
66
     *
67
     * @return int The status code
68
     */
69
    public function handleList(Args $args, IO $io)
70
    {
71
        $modules = $this->getSelectedModules($args);
72
73
        if ($args->isOptionSet('format')) {
74
            $this->printModulesWithFormat($io, $modules, $args->getOption('format'));
75
        } else {
76
            $this->printModulesByState($io, $modules, $this->getSelectedStates($args));
77
        }
78
79
        return 0;
80
    }
81
82
    /**
83
     * Handles the "module --install" command.
84
     *
85
     * @param Args $args The console arguments
86
     *
87
     * @return int The status code
88
     */
89
    public function handleInstall(Args $args)
90
    {
91
        $moduleName = $args->getArgument('name');
92
        $installPath = Path::makeAbsolute($args->getArgument('path'), getcwd());
93
        $installer = $args->getOption('installer');
94
        $env = $args->isOptionSet('dev') ? Environment::DEV : Environment::PROD;
95
96
        $this->moduleManager->installModule($installPath, $moduleName, $installer, $env);
97
98
        return 0;
99
    }
100
101
    /**
102
     * Handles the "module --rename" command.
103
     *
104
     * @param Args $args The console arguments
105
     *
106
     * @return int The status code
107
     */
108
    public function handleRename(Args $args)
109
    {
110
        $moduleName = $args->getArgument('name');
111
        $newName = $args->getArgument('new-name');
112
113
        $this->moduleManager->renameModule($moduleName, $newName);
114
115
        return 0;
116
    }
117
118
    /**
119
     * Handles the "module --delete" command.
120
     *
121
     * @param Args $args The console arguments
122
     *
123
     * @return int The status code
124
     */
125
    public function handleDelete(Args $args)
126
    {
127
        $moduleName = $args->getArgument('name');
128
129
        if (!$this->moduleManager->hasModule($moduleName)) {
130
            throw new RuntimeException(sprintf(
131
                'The module "%s" is not installed.',
132
                $moduleName
133
            ));
134
        }
135
136
        $this->moduleManager->removeModule($moduleName);
137
138
        return 0;
139
    }
140
141
    /**
142
     * Handles the "module --clean" command.
143
     *
144
     * @param Args $args The console arguments
145
     * @param IO   $io   The I/O
146
     *
147
     * @return int The status code
148
     */
149
    public function handleClean(Args $args, IO $io)
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
150
    {
151
        $expr = Expr::method('getState', Expr::same(ModuleState::NOT_FOUND));
152
153
        foreach ($this->moduleManager->findModules($expr) as $module) {
154
            $io->writeLine('Removing '.$module->getName());
155
            $this->moduleManager->removeModule($module->getName());
156
        }
157
158
        return 0;
159
    }
160
161
    /**
162
     * Returns the module states that should be displayed for the given
163
     * console arguments.
164
     *
165
     * @param Args $args The console arguments
166
     *
167
     * @return int[] A list of {@link ModuleState} constants
168
     */
169
    private function getSelectedStates(Args $args)
170
    {
171
        $states = array();
172
173
        if ($args->isOptionSet('enabled')) {
174
            $states[] = ModuleState::ENABLED;
175
        }
176
177
        if ($args->isOptionSet('not-found')) {
178
            $states[] = ModuleState::NOT_FOUND;
179
        }
180
181
        if ($args->isOptionSet('not-loadable')) {
182
            $states[] = ModuleState::NOT_LOADABLE;
183
        }
184
185
        return $states ?: ModuleState::all();
186
    }
187
188
    /**
189
     * Returns the modules that should be displayed for the given console
190
     * arguments.
191
     *
192
     * @param Args $args The console arguments
193
     *
194
     * @return ModuleList The modules
195
     */
196
    private function getSelectedModules(Args $args)
197
    {
198
        $states = $this->getSelectedStates($args);
199
        $expr = Expr::true();
200
        $envs = array();
201
202
        if ($states !== ModuleState::all()) {
203
            $expr = $expr->andMethod('getState', Expr::in($states));
204
        }
205
206
        if ($args->isOptionSet('installer')) {
207
            $expr = $expr->andMethod('getInstallInfo', Expr::method('getInstallerName', Expr::same($args->getOption('installer'))));
208
        }
209
210
        if ($args->isOptionSet('prod')) {
211
            $envs[] = Environment::PROD;
212
        }
213
214
        if ($args->isOptionSet('dev')) {
215
            $envs[] = Environment::DEV;
216
        }
217
218
        if (count($envs) > 0) {
219
            $expr = $expr->andMethod('getInstallInfo', Expr::method('getEnvironment', Expr::in($envs)));
220
        }
221
222
        return $this->moduleManager->findModules($expr);
223
    }
224
225
    /**
226
     * Prints modules with intermediate headers for the module states.
227
     *
228
     * @param IO         $io      The I/O
229
     * @param ModuleList $modules The modules to print
230
     * @param int[]      $states  The states to print
231
     */
232
    private function printModulesByState(IO $io, ModuleList $modules, array $states)
233
    {
234
        $printStates = count($states) > 1;
235
236
        foreach ($states as $state) {
237
            $filteredModules = array_filter($modules->toArray(), function (Module $module) use ($state) {
238
                return $state === $module->getState();
239
            });
240
241
            if (0 === count($filteredModules)) {
242
                continue;
243
            }
244
245
            if ($printStates) {
246
                $this->printModuleState($io, $state);
247
            }
248
249
            if (ModuleState::NOT_LOADABLE === $state) {
250
                $this->printNotLoadableModules($io, $filteredModules, $printStates);
251
            } else {
252
                $styleTag = ModuleState::ENABLED === $state ? null : 'bad';
253
                $this->printModuleTable($io, $filteredModules, $styleTag, $printStates);
254
            }
255
256
            if ($printStates) {
257
                $io->writeLine('');
258
            }
259
        }
260
    }
261
262
    /**
263
     * Prints modules using the given format.
264
     *
265
     * @param IO         $io      The I/O
266
     * @param ModuleList $modules The modules to print
267
     * @param string     $format  The format string
268
     */
269
    private function printModulesWithFormat(IO $io, ModuleList $modules, $format)
270
    {
271
        /** @var Module $module */
272
        foreach ($modules as $module) {
273
            $installInfo = $module->getInstallInfo();
274
275
            $io->writeLine(strtr($format, array(
276
                '%name%' => $module->getName(),
277
                '%installer%' => $installInfo ? $installInfo->getInstallerName() : '',
278
                '%install_path%' => $module->getInstallPath(),
279
                '%state%' => self::$stateStrings[$module->getState()],
280
                '%env%' => $installInfo ? $installInfo->getEnvironment() : Environment::PROD,
281
            )));
282
        }
283
    }
284
285
    /**
286
     * Prints the heading for a given module state.
287
     *
288
     * @param IO  $io          The I/O
289
     * @param int $ModuleState The {@link ModuleState} constant
290
     */
291
    private function printModuleState(IO $io, $ModuleState)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $ModuleState is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
292
    {
293 View Code Duplication
        switch ($ModuleState) {
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...
294
            case ModuleState::ENABLED:
295
                $io->writeLine('The following modules are currently enabled:');
296
                $io->writeLine('');
297
298
                return;
299
            case ModuleState::NOT_FOUND:
300
                $io->writeLine('The following modules could not be found:');
301
                $io->writeLine(' (use "puli module --clean" to remove)');
302
                $io->writeLine('');
303
304
                return;
305
            case ModuleState::NOT_LOADABLE:
306
                $io->writeLine('The following modules could not be loaded:');
307
                $io->writeLine('');
308
309
                return;
310
        }
311
    }
312
313
    /**
314
     * Prints a list of modules in a table.
315
     *
316
     * @param IO          $io       The I/O
317
     * @param Module[]    $modules  The modules
318
     * @param string|null $styleTag The tag used to style the output. If `null`,
319
     *                              the default colors are used
320
     * @param bool        $indent   Whether to indent the output
321
     */
322
    private function printModuleTable(IO $io, array $modules, $styleTag = null, $indent = false)
323
    {
324
        $table = new Table(PuliTableStyle::borderless());
325
        $table->setHeaderRow(array('Module Name', 'Installer', 'Env', 'Install Path'));
326
327
        $installerTag = $styleTag ?: 'c1';
328
        $envTag = $styleTag ?: 'c1';
329
        $pathTag = $styleTag ?: 'c2';
330
331
        ksort($modules);
332
333
        foreach ($modules as $module) {
334
            $moduleName = $module->getName();
335
            $installInfo = $module->getInstallInfo();
336
            $installPath = $installInfo ? $installInfo->getInstallPath() : '.';
337
            $installer = $installInfo ? $installInfo->getInstallerName() : '';
338
            $env = $installInfo ? $installInfo->getEnvironment() : Environment::PROD;
339
340
            $table->addRow(array(
341
                $styleTag ? sprintf('<%s>%s</%s>', $styleTag, $moduleName, $styleTag) : $moduleName,
342
                $installer ? sprintf('<%s>%s</%s>', $installerTag, $installer, $installerTag) : '',
343
                sprintf('<%s>%s</%s>', $envTag, $env, $envTag),
344
                sprintf('<%s>%s</%s>', $pathTag, $installPath, $pathTag),
345
            ));
346
        }
347
348
        $table->render($io, $indent ? 4 : 0);
349
    }
350
351
    /**
352
     * Prints not-loadable modules in a table.
353
     *
354
     * @param IO       $io      The I/O
355
     * @param Module[] $modules The not-loadable modules
356
     * @param bool     $indent  Whether to indent the output
357
     */
358
    private function printNotLoadableModules(IO $io, array $modules, $indent = false)
359
    {
360
        $rootDir = $this->moduleManager->getContext()->getRootDirectory();
361
        $table = new Table(PuliTableStyle::borderless());
362
        $table->setHeaderRow(array('Module Name', 'Error'));
363
364
        ksort($modules);
365
366
        foreach ($modules as $module) {
367
            $moduleName = $module->getName();
368
            $loadErrors = $module->getLoadErrors();
369
            $errorMessage = '';
370
371
            foreach ($loadErrors as $loadError) {
372
                $errorMessage .= StringUtil::getShortClassName(get_class($loadError)).': '.$loadError->getMessage()."\n";
373
            }
374
375
            $errorMessage = rtrim($errorMessage);
376
377
            if (!$errorMessage) {
378
                $errorMessage = 'Unknown error.';
379
            }
380
381
            // Remove root directory
382
            $errorMessage = str_replace($rootDir.'/', '', $errorMessage);
383
384
            $table->addRow(array(
385
                sprintf('<bad>%s</bad>', $moduleName),
386
                sprintf('<bad>%s</bad>', $errorMessage),
387
            ));
388
        }
389
390
        $table->render($io, $indent ? 4 : 0);
391
    }
392
}
393