GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 2a7ea5...513f1e )
by Robert
11s
created

MigrationsCommand::execute()   F

Complexity

Conditions 24
Paths 5945

Size

Total Lines 146
Code Lines 89

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 24.0159

Importance

Changes 0
Metric Value
dl 0
loc 146
ccs 32
cts 33
cp 0.9697
rs 2
c 0
b 0
f 0
cc 24
eloc 89
nc 5945
nop 2
crap 24.0159

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 declare(strict_types=1);
2
3
namespace Gruberro\MongoDbMigrations\Console\Command;
4
5
use Gruberro\MongoDbMigrations;
6
use MongoDB;
7
use Symfony\Component\Console;
8
9
class MigrationsCommand extends Console\Command\Command
10
{
11
    /**
12
     * {@inheritdoc}
13
     */
14 7
    protected function configure()
15
    {
16
        $this
17 7
            ->setName('php-mongodb-migrations:migrate')
18 7
            ->setDescription('Execute all open migrations')
19 7
            ->addOption(
20 7
                'server',
21 7
                's',
22 7
                Console\Input\InputOption::VALUE_REQUIRED,
23 7
                'The connection string (e.g. mongodb://[username:password@]host1[:port1][,host2[:port2:],...]/db)',
24 7
                'mongodb://localhost:27017'
25
            )
26 7
            ->addOption(
27 7
                'contexts',
28 7
                'c',
29 7
                Console\Input\InputOption::VALUE_IS_ARRAY | Console\Input\InputOption::VALUE_REQUIRED,
30 7
                'A list of contexts evaluated with each migration of type ContextualMigrationInterface',
31 7
                []
32
            )
33 7
            ->addArgument(
34 7
                'database',
35 7
                Console\Input\InputArgument::REQUIRED,
36 7
                'The database to connect to'
37
            )
38 7
            ->addArgument(
39 7
                'migration-directories',
40 7
                Console\Input\InputArgument::IS_ARRAY,
41 7
                'List of directories containing migration classes',
42 7
                []
43
            )
44
        ;
45 7
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 8
    protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
51
    {
52 8
        $client = new MongoDB\Client($input->getOption('server'));
53 8
        $db = $client->selectDatabase($input->getArgument('database'));
54 8
        $output->writeln("<info>✓ Successfully established database connection</info>", $output::VERBOSITY_VERBOSE);
55
56 8
        $directories = $input->getArgument('migration-directories');
57 8
        foreach ($directories as $directory) {
58 8
            if (! is_dir($directory)) {
59 1
                throw new Console\Exception\InvalidArgumentException("'{$directory}' is no valid directory");
60
            }
61
62 8
            $output->writeln("<comment>Iterating '{$directory}' for potential migrations classes</comment>", $output::VERBOSITY_DEBUG);
63 8
            $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory), \RecursiveIteratorIterator::LEAVES_ONLY);
64
65
            /** @var \SplFileInfo $file */
66 8
            foreach ($iterator as $file) {
67 8
                if ($file->getBasename('.php') === $file->getBasename()) {
68 8
                    continue;
69
                }
70
71 8
                require_once $file->getRealPath();
72
73 8
                $output->writeln("<comment>Loaded potential migration '{$file->getRealPath()}'</comment>", $output::VERBOSITY_DEBUG);
74
            }
75
        }
76
77
        /** @var MongoDbMigrations\MigrationInterface[] $migrations */
78 7
        $migrations = [];
79 7
        foreach (get_declared_classes() as $className) {
80 7
            $reflectionClass = new \ReflectionClass($className);
81
82 7
            if ($reflectionClass->implementsInterface(MongoDbMigrations\MigrationInterface::class)) {
83
                /** @var MongoDbMigrations\MigrationInterface $newInstance */
84 7
                $newInstance = $reflectionClass->newInstance();
85 7
                $id = md5($newInstance->getId());
86
87 7
                if (isset($migrations[$id])) {
88 1
                    $existingMigrationClass = get_class($migrations[$id]);
89 1
                    throw new Console\Exception\RuntimeException("Found a non unique migration id '{$newInstance->getId()}' in '{$reflectionClass->getName()}', already defined by migration class '{$existingMigrationClass}'");
90
                }
91
92 7
                $migrations[$id] = $newInstance;
93
94 7
                $output->writeln("<comment>Found valid migration class '{$reflectionClass->getName()}'</comment>", $output::VERBOSITY_DEBUG);
95
            }
96
        }
97
98 6
        $migrationClassesCount = count($migrations);
99 6
        $output->writeln("<info>✓ Found {$migrationClassesCount} valid migration classes</info>", $output::VERBOSITY_VERBOSE);
100
101 6
        uasort($migrations, function (MongoDbMigrations\MigrationInterface $a, MongoDbMigrations\MigrationInterface $b) {
102 6
            if ($a->getCreateDate() === $b->getCreateDate()) {
103
                return 0;
104
            }
105
106 6
            return $a->getCreateDate() < $b->getCreateDate() ? -1 : 1;
107 6
        });
108
109
        $output->writeln("<info>✓ Reordered all migration classes according to their create date</info>", $output::VERBOSITY_VERBOSE);
110
111
        $databaseMigrationsLockCollection = $db->selectCollection('DATABASE_MIGRATIONS_LOCK');
112
        $databaseMigrationsLockCollection->createIndex(['locked' => 1]);
113
114
        $currentLock = $databaseMigrationsLockCollection->findOneAndReplace(['locked' => ['$exists' => true]], ['locked' => true, 'last_locked_date' => new MongoDB\BSON\UTCDatetime((new \DateTime())->getTimestamp() * 1000)], ['upsert' => true]);
115
        if ($currentLock !== null && $currentLock->locked === true) {
116
            throw new Console\Exception\RuntimeException('Concurrent migrations are not allowed');
117
        }
118
119
        try {
120
            $output->writeln("<info>✓ Successfully acquired migration lock</info>", $output::VERBOSITY_VERBOSE);
121
122
            $databaseMigrationsCollection = $db->selectCollection('DATABASE_MIGRATIONS');
123
            $databaseMigrationsCollection->createIndex(['migration_id' => 1], ['unique' => true, 'background' => false]);
124
125
            $progress = new Console\Helper\ProgressBar($output, count($migrations));
126
127
            switch ($output->getVerbosity()) {
128
                case $output::VERBOSITY_VERBOSE:
129
                    $format = 'verbose';
130
                    break;
131
                case $output::VERBOSITY_VERY_VERBOSE:
132
                    $format = 'very_verbose';
133
                    break;
134
                case $output::VERBOSITY_DEBUG:
135
                    $format = 'debug';
136
                    break;
137
                default:
138
                    $format = 'normal';
139
            }
140
141
            $progress->setFormat($format);
142
            $progress->start();
143
            $executedMigrations = 0;
144
145
            foreach ($migrations as $id => $migration) {
146
                $progress->advance();
147
148
                if ($migration instanceof MongoDbMigrations\ContextualMigrationInterface && $input->getOption('contexts') !== []) {
149
                    if ($migration->getContexts() === []) {
150
                        throw new \InvalidArgumentException('An empty context specification is not allowed');
151
                    }
152
153
                    if (array_intersect($migration->getContexts(), $input->getOption('contexts')) === []) {
154
                        continue;
155
                    }
156
                }
157
158
                if (!$migration instanceof MongoDbMigrations\RunAlwaysMigrationInterface) {
159
                    if ($databaseMigrationsCollection->count(['migration_id' => $id]) > 0) {
160
                        continue;
161
                    }
162
                }
163
164
                $migration->execute($db);
165
                $executedMigrations++;
166
167
                $migrationInfo = [
168
                    'migration_id' => $id,
169
                    'migration_class' => get_class($migration),
170
                    'last_execution_date' => new MongoDB\BSON\UTCDatetime((new \DateTime())->getTimestamp() * 1000),
171
                    'run_always' => $migration instanceof MongoDbMigrations\RunAlwaysMigrationInterface,
172
                ];
173
174
                if ($migration instanceof MongoDbMigrations\ContextualMigrationInterface) {
175
                    $migrationInfo['contexts'] = $migration->getContexts();
176
                }
177
178
                $databaseMigrationsCollection->updateOne(
179
                    ['migration_id' => $id],
180
                    ['$set' => $migrationInfo],
181
                    ['upsert' => true]
182
                );
183
            }
184
185
            $progress->finish();
186
            $output->writeln('');
187
188
            $output->writeln("<info>✓ Successfully executed {$executedMigrations} migrations</info>");
189
        } catch (\Exception $e) {
190
            throw new Console\Exception\RuntimeException('Error while executing migrations', $e->getCode(), $e);
191
        } finally {
192
            $databaseMigrationsLockCollection->updateOne(['locked' => true], ['$set' => ['locked' => false]]);
193
            $output->writeln("<info>✓ Successfully released migration lock</info>", $output::VERBOSITY_VERBOSE);
194
        }
195
    }
196
}
197