Completed
Push — master ( 97fb46...770b11 )
by Gaetano
15:34 queued 07:06
created

StatusCommand::execute()   F

Complexity

Conditions 36
Paths > 20000

Size

Total Lines 175
Code Lines 123

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 41
CRAP Score 345.4712

Importance

Changes 0
Metric Value
cc 36
eloc 123
nc 63553
nop 2
dl 0
loc 175
ccs 41
cts 108
cp 0.3796
crap 345.4712
rs 0
c 0
b 0
f 0

How to fix   Long Method    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
namespace Kaliop\eZMigrationBundle\Command;
4
5
use Symfony\Component\Console\Input\InputInterface;
6
use Symfony\Component\Console\Output\OutputInterface;
7
use Symfony\Component\Console\Input\InputOption;
8
use Kaliop\eZMigrationBundle\API\Value\Migration;
9
use Kaliop\eZMigrationBundle\API\Value\MigrationDefinition;
10
use Symfony\Component\Console\Helper\Table;
11
12
/**
13
 * Command to display the status of migrations.
14
 *
15
 * @todo add option to skip displaying already executed migrations
16
 * @todo allow sorting migrations by their execution date
17
 */
18
class StatusCommand extends AbstractCommand
19
{
20
    const STATUS_INVALID = -1;
21
22 94
    protected function configure()
23
    {
24 94
        $this->setName('kaliop:migration:status')
25 94
            ->setDescription('View the status of all (or a set of) migrations.')
26 94
            ->addOption('path', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, "The directory or file to load the migration definitions from")
27 94
            ->addOption('summary', null, InputOption::VALUE_NONE, "Only print summary information")
28 94
            ->addOption('todo', null, InputOption::VALUE_NONE, "Only print list of migrations to execute (full path to each)")
29 94
            ->setHelp(<<<EOT
30 94
The <info>kaliop:migration:status</info> command displays the status of all available migrations:
31
32
    <info>./ezpublish/console kaliop:migration:status</info>
33
34
You can optionally specify the path to migration versions with <info>--path</info>:
35
36
    <info>./ezpublish/console kaliop:migrations:status --path=/path/to/bundle/version_directory --path=/path/to/bundle/version_directory/single_migration_file</info>
37
EOT
38
            );
39 94
    }
40
41 34
    public function execute(InputInterface $input, OutputInterface $output)
42
    {
43 34
        $this->setOutput($output);
44 34
        $this->setVerbosity($output->getVerbosity());
45
46 34
        $migrationsService = $this->getMigrationService();
47
48 34
        $migrationDefinitions = $migrationsService->getMigrationsDefinitions($input->getOption('path'));
0 ignored issues
show
Bug introduced by
It seems like $input->getOption('path') can also be of type boolean and null and string; however, parameter $paths of Kaliop\eZMigrationBundle...MigrationsDefinitions() does only seem to accept array, 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

48
        $migrationDefinitions = $migrationsService->getMigrationsDefinitions(/** @scrutinizer ignore-type */ $input->getOption('path'));
Loading history...
49 34
        $migrations = $migrationsService->getMigrations();
50
51 34
        if (!count($migrationDefinitions) && !count($migrations)) {
52
            $output->writeln('<info>No migrations found</info>');
53
            return;
54
        }
55
56
        // create a unique ist of all migrations (coming from db) and definitions (coming from disk)
57 34
        $index = array();
58 34
        foreach ($migrationDefinitions as $migrationDefinition) {
59 34
            $index[$migrationDefinition->name] = array('definition' => $migrationDefinition);
60
        }
61 34
        foreach ($migrations as $migration) {
62
            if (isset($index[$migration->name])) {
63
                $index[$migration->name]['migration'] = $migration;
64
            } else {
65
                $index[$migration->name] = array('migration' => $migration);
66
67
                // no definition, but a migration is there. Check if the definition sits elsewhere on disk than we expect it to be...
68
                // q: what if we have a loader which does not work with is_file? Could we remove this check?
69
                if ($migration->path != '' && is_file($migration->path)) {
70
                    try {
71
                        $migrationDefinitionCollection = $migrationsService->getMigrationsDefinitions(array($migration->path));
72
                        if (count($migrationDefinitionCollection)) {
73
                            $index[$migration->name]['definition'] = reset($migrationDefinitionCollection);
74
                        }
75
                    } catch (\Exception $e) {
76
                        /// @todo one day we should be able to limit the kind of exceptions we have to catch here...
77
                    }
78
                }
79
            }
80
        }
81 34
        ksort($index);
82
83 34
        if (!$input->getOption('summary') && !$input->getOption('todo')) {
84 34
            if (count($index) > 50000) {
85
                $output->writeln("WARNING: printing the status table might take a while as it contains many rows. Please wait...");
86
            }
87 34
            $output->writeln("\n <info>==</info> All Migrations\n");
88
        }
89
90
        $summary = array(
91 34
            self::STATUS_INVALID => array('Invalid', 0),
92
            Migration::STATUS_TODO => array('To do', 0),
93
            Migration::STATUS_STARTED => array('Started', 0),
94
            Migration::STATUS_DONE => array('Done', 0),
95
            Migration::STATUS_SUSPENDED => array('Suspended', 0),
96
            Migration::STATUS_FAILED => array('Failed', 0),
97
            Migration::STATUS_SKIPPED => array('Skipped', 0),
98
            Migration::STATUS_PARTIALLY_DONE => array('Partially done', 0),
99
        );
100 34
        $data = array();
101
102 34
        $i = 1;
103 34
        foreach ($index as $name => $value) {
104 34
            if (!isset($value['migration'])) {
105 34
                $migrationDefinition = $migrationsService->parseMigrationDefinition($value['definition']);
106 34
                $notes = '';
107 34
                if ($migrationDefinition->status != MigrationDefinition::STATUS_PARSED) {
108 2
                    $notes = '<error>' . $migrationDefinition->parsingError . '</error>';
109 2
                    $summary[self::STATUS_INVALID][1]++;
110
                } else {
111 34
                    $summary[Migration::STATUS_TODO][1]++;
112
                }
113 34
                if ($input->getOption('todo')) {
114
                    $data[] = $migrationDefinition->path;
115
                } else {
116 34
                    $data[] = array(
117 34
                        $i++,
118 34
                        $name,
119 34
                        '<error>not executed</error>',
120 34
                        '',
121 34
                        $notes
122
                    );
123
124
                }
125
            } else {
126
                $migration = $value['migration'];
127
128
                if (!isset($summary[$migration->status])) {
129
                    $summary[$migration->status] = array($migration->status, 0);
130
                }
131
                $summary[$migration->status][1]++;
132
                if ($input->getOption('summary')) {
133
                    continue;
134
                }
135
136
                if ($input->getOption('todo')) {
137
                    if ($migration->status == Migration::STATUS_TODO) {
138
                        $data[] = $migration->path;
139
                    }
140
141
                    continue;
142
                }
143
144
                switch ($migration->status) {
145
                    case Migration::STATUS_DONE:
146
                        $status = '<info>executed</info>';
147
                        break;
148
                    case Migration::STATUS_STARTED:
149
                        $status = '<comment>execution started</comment>';
150
                        break;
151
                    case Migration::STATUS_TODO:
152
                        // bold to-migrate!
153
                        $status = '<error>not executed</error>';
154
                        break;
155
                    case Migration::STATUS_SKIPPED:
156
                        $status = '<comment>skipped</comment>';
157
                        break;
158
                    case Migration::STATUS_PARTIALLY_DONE:
159
                        $status = '<comment>partially executed</comment>';
160
                        break;
161
                    case Migration::STATUS_SUSPENDED:
162
                        $status = '<comment>suspended</comment>';
163
                        break;
164
                    case Migration::STATUS_FAILED:
165
                        $status = '<error>failed</error>';
166
                        break;
167
                }
168
                $notes = array();
169
                if ($migration->executionError != '') {
170
                    $notes[] = "<error>{$migration->executionError}</error>";
171
                }
172
                if (!isset($value['definition'])) {
173
                    $notes[] = '<comment>The migration definition file can not be found any more</comment>';
174
                } else {
175
                    $migrationDefinition = $value['definition'];
176
                    if (md5($migrationDefinition->rawDefinition) != $migration->md5) {
177
                        $notes[] = '<comment>The migration definition file has now a different checksum</comment>';
178
                    }
179
                    if ($migrationDefinition->path != $migrationDefinition->path) {
180
                        $notes[] = '<comment>The migration definition file has now moved</comment>';
181
                    }
182
                }
183
                $notes = implode(' ', $notes);
184
                $data[] = array(
185
                    $i++,
186
                    $migration->name,
187
                    $status,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $status does not seem to be defined for all execution paths leading up to this point.
Loading history...
188
                    ($migration->executionDate != null ? date("Y-m-d H:i:s", $migration->executionDate) : ''),
189 34
                    $notes
190
                );
191
            }
192
        }
193
194 34
        if ($input->getOption('todo')) {
195
            foreach ($data as $migrationData) {
196
                echo "$migrationData\n";
197
            }
198
            return;
199
        }
200
201 34
        if ($input->getOption('summary')) {
202
            $output->writeln("\n <info>==</info> Migrations Summary\n");
203
            // do not print info about the not yet supported case
204
            unset($summary[Migration::STATUS_PARTIALLY_DONE]);
205
            $data = $summary;
206
            $headers = array('Status', 'Count');
207
        } else {
208 34
            $headers = array('#', 'Migration', 'Status', 'Executed on', 'Notes');
209
        }
210
211 34
        $table = new Table($output);
212
        $table
213 34
            ->setHeaders($headers)
214 34
            ->setRows($data);
215 34
        $table->render();
216 34
    }
217
}
218