Completed
Push — master ( 8be2e3...f70097 )
by Adrian
11:42
created

MongodbMigrateCommand::execute()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 48
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 48
ccs 0
cts 34
cp 0
rs 8.551
cc 6
eloc 30
nc 8
nop 2
crap 42
1
<?php
2
/**
3
 * graviton:mongodb:migrations:execute command
4
 */
5
6
namespace Graviton\MigrationBundle\Command;
7
8
use Symfony\Component\Console\Command\Command;
9
use Symfony\Component\Console\Input\InputInterface;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use Symfony\Component\Console\Input\ArrayInput;
12
use Symfony\Component\DependencyInjection\ContainerInterface;
13
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
14
use Symfony\Component\Finder\Finder;
15
use Graviton\MigrationBundle\Command\Helper\DocumentManager as DocumentManagerHelper;
16
use AntiMattr\MongoDB\Migrations\OutputWriter;
17
18
/**
19
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
20
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
21
 * @link     http://swisscom.ch
22
 */
23
class MongodbMigrateCommand extends Command
24
{
25
    /**
26
     * @var ContainerInterface
27
     */
28
    private $container;
29
    
30
    /**
31
     * @var Finder
32
     */
33
    private $finder;
34
35
    /**
36
     * @var DocumentManagerHelper
37
     */
38
    private $documentManager;
39
40
    /**
41
     * @var string
42
     */
43
    private $databaseName;
44
45
    /**
46
     * @var array
47
     */
48
    private $errors = [];
49
50
    /**
51
     * @param ContainerInterface    $container       container instance for injecting into aware migrations
52
     * @param Finder                $finder          finder that finds configs
53
     * @param DocumentManagerHelper $documentManager dm helper to get access to db in command
54
     * @param string                $databaseName    name of database where data is found in
55
     */
56 4
    public function __construct(
57
        ContainerInterface $container,
58
        Finder $finder,
59
        DocumentManagerHelper $documentManager,
60
        $databaseName
61
    ) {
62 4
        $this->container = $container;
63 4
        $this->finder = $finder;
64 4
        $this->documentManager = $documentManager;
65 4
        $this->databaseName = $databaseName;
66
67 4
        parent::__construct();
68 4
    }
69
70
    /**
71
     * setup command
72
     *
73
     * @return void
74
     */
75 4
    protected function configure()
76
    {
77 4
        parent::configure();
78
79 4
        $this->setName('graviton:mongodb:migrate');
80 4
    }
81
82
    /**
83
     * call execute on found commands
84
     *
85
     * @param InputInterface  $input  user input
86
     * @param OutputInterface $output command output
87
     *
88
     * @return void
0 ignored issues
show
Documentation introduced by
Should the return type not be integer?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
89
     */
90
    public function execute(InputInterface $input, OutputInterface $output)
91
    {
92
        $this->finder->in(
93
            strpos(getcwd(), 'vendor/') === false ? getcwd() :  getcwd() . '/../../../../'
94
        )->path('Resources/config')->name('/migrations.(xml|yml)/')->files();
95
96
        foreach ($this->finder as $file) {
97
            if (!$file->isFile()) {
98
                continue;
99
            }
100
101
            $output->writeln('Found '.$file->getRelativePathname());
102
103
            $command = $this->getApplication()->find('mongodb:migrations:migrate');
104
105
            $helperSet = $command->getHelperSet();
106
            $helperSet->set($this->documentManager, 'dm');
107
            $command->setHelperSet($helperSet);
108
109
            $configuration = $this->getConfiguration($file->getPathname(), $output);
0 ignored issues
show
Documentation introduced by
$output is of type object<Symfony\Component...Output\OutputInterface>, but the function expects a object<Graviton\MigrationBundle\Command\Output>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
110
            self::injectContainerToMigrations($this->container, $configuration->getMigrations());
111
            $command->setMigrationConfiguration($configuration);
112
113
            $arguments = $input->getArguments();
114
            $arguments['command'] = 'mongodb:migrations:migrate';
115
            $arguments['--configuration'] = $file->getPathname();
116
117
            $migrateInput = new ArrayInput($arguments);
118
            $migrateInput->setInteractive($input->isInteractive());
119
            $returnCode = $command->run($migrateInput, $output);
120
121
            if ($returnCode !== 0) {
122
                $this->errors[] = sprintf(
123
                    'Calling mongodb:migrations:migrate failed for %s',
124
                    $file->getRelativePathname()
125
                );
126
            }
127
        }
128
129
        if (!empty($this->errors)) {
130
            $output->writeln(
131
                sprintf('<error>%s</error>', implode(PHP_EOL, $this->errors))
132
            );
133
            return -1;
134
        }
135
136
        return 0;
137
    }
138
139
    /**
140
     * get configration object for migration script
141
     *
142
     * This is based on antromattr/mongodb-migartion code but extends it so we can inject
143
     * non local stuff centrally.
144
     *
145
     * @param string $filepath path to configuration file
146
     * @param Output $output   ouput interface need by config parser to do stuff
147
     *
148
     * @return AntiMattr\MongoDB\Migrations\Configuration\Configuration
149
     */
150
    private function getConfiguration($filepath, $output)
151
    {
152
        $outputWriter = new OutputWriter(
153
            function ($message) use ($output) {
154
                return $output->writeln($message);
155
            }
156
        );
157
158
        $info = pathinfo($filepath);
159
        $namespace = 'AntiMattr\MongoDB\Migrations\Configuration';
160
        $class = $info['extension'] === 'xml' ? 'XmlConfiguration' : 'YamlConfiguration';
161
        $class = sprintf('%s\%s', $namespace, $class);
162
        $configuration = new $class($this->documentManager->getDocumentManager()->getConnection(), $outputWriter);
163
164
        // register databsae name before loading to ensure that loading does not fail
165
        $configuration->setMigrationsDatabaseName($this->databaseName);
166
167
        // load additional config from migrations.(yml|xml)
168
        $configuration->load($filepath);
169
170
        return $configuration;
171
    }
172
    
173
    /**
174
     * Injects the container to migrations aware of it
175
     *
176
     * @param ContainerInterface $container container to inject into container aware migrations
177
     * @param array              $versions  versions that might need injecting a container
178
     *
179
     * @return void
180
     */
181
    private static function injectContainerToMigrations(ContainerInterface $container, array $versions)
182
    {
183
        foreach ($versions as $version) {
184
            $migration = $version->getMigration();
185
            if ($migration instanceof ContainerAwareInterface) {
186
                $migration->setContainer($container);
187
            }
188
        }
189
    }
190
}
191