MigrateHandler   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 2
Bugs 1 Features 0
Metric Value
wmc 18
c 2
b 1
f 0
lcom 1
cbo 13
dl 0
loc 167
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A handle() 0 23 3
A attachEvents() 0 15 3
A saveVersionListener() 0 5 1
A onMigrationBefore() 0 11 2
A onMigrationAfter() 0 7 2
A onCollectionBefore() 0 15 3
A onCollectionAfter() 0 8 2
A getStrategyOption() 0 13 2
1
<?php
2
3
/*
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the MIT license. For more information, see
18
 * <http://www.doctrine-project.org>.
19
 */
20
21
namespace Baleen\Cli\CommandBus\Timeline;
22
23
use Baleen\Cli\Exception\CliException;
24
use Baleen\Migrations\Event\EventInterface;
25
use Baleen\Migrations\Event\Timeline\CollectionEvent;
26
use Baleen\Migrations\Event\Timeline\MigrationEvent;
27
use Baleen\Migrations\Migration\Options;
28
use Symfony\Component\Console\Helper\ProgressBar;
29
use Symfony\Component\Console\Input\InputInterface;
30
use Symfony\Component\Console\Output\OutputInterface;
31
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
32
33
/**
34
 * Class MigrateHandler.
35
 *
36
 * @author Gabriel Somoza <[email protected]>
37
 */
38
class MigrateHandler
39
{
40
    /** @var ProgressBar */
41
    protected $progress;
42
43
    /** @var bool */
44
    protected $saveChanges = true;
45
46
    /** @var array */
47
    protected $strategies = [
48
        Options::DIRECTION_UP => 'upTowards',
49
        Options::DIRECTION_DOWN => 'downTowards',
50
        'both' => 'goTowards',
51
    ];
52
53
    /** @var bool */
54
    protected $trackProgress = true;
55
56
    /** @var OutputInterface */
57
    protected $output;
58
59
    /** @var MigrateMessage */
60
    protected $command;
61
62
    /**
63
     * handle.
64
     *
65
     * @param MigrateMessage $command
66
     *
67
     * @throws CliException
68
     */
69
    public function handle(MigrateMessage $command)
70
    {
71
        $input = $command->getInput();
72
        $output = $command->getOutput();
73
        $this->command = $command;
74
75
        $targetArg = (string) $input->getArgument(MigrateMessage::ARG_TARGET);
76
        $strategy = (string) $this->getStrategyOption($input);
77
78
        $options = new Options(Options::DIRECTION_UP); // this value will get replaced by timeline later
79
        $options->setDryRun($input->getOption(MigrateMessage::OPT_DRY_RUN));
80
        $options->setExceptionOnSkip(false);
81
82
        $this->saveChanges = !$input->getOption(MigrateMessage::OPT_NO_STORAGE) && !$options->isDryRun();
83
84
        $this->trackProgress = ($output->getVerbosity() !== OutputInterface::VERBOSITY_QUIET)
85
            && !$input->getOption(MigrateMessage::OPT_NOPROGRESS);
86
87
        $this->attachEvents($output, $command->getTimeline()->getEventDispatcher());
88
89
        /* @var \Baleen\Migrations\Version\Collection\LinkedVersions $results */
90
        $command->getTimeline()->$strategy($targetArg, $options);
91
    }
92
93
    /**
94
     * @inheritDoc
95
     */
96
    protected function attachEvents(OutputInterface $output, EventDispatcherInterface $dispatcher)
97
    {
98
        $this->output = $output;
99
100
        if ($output->getVerbosity() >= OutputInterface::VERBOSITY_NORMAL) {
101
            $dispatcher->addListener(EventInterface::COLLECTION_BEFORE, [$this, 'onCollectionBefore']);
102
            $dispatcher->addListener(EventInterface::COLLECTION_AFTER, [$this, 'onCollectionAfter']);
103
            $dispatcher->addListener(EventInterface::MIGRATION_BEFORE, [$this, 'onMigrationBefore']);
104
            $dispatcher->addListener(EventInterface::MIGRATION_AFTER, [$this, 'onMigrationAfter']);
105
        }
106
107
        if ($this->saveChanges) {
108
            $dispatcher->addListener(EventInterface::MIGRATION_AFTER, [$this, 'saveVersionListener']);
109
        }
110
    }
111
112
    /**
113
     * saveVersionListener.
114
     *
115
     * @param MigrationEvent $event
116
     */
117
    public function saveVersionListener(MigrationEvent $event)
118
    {
119
        $version = $event->getVersion();
120
        $this->command->getStorage()->update($version);
121
    }
122
123
    /**
124
     * @param MigrationEvent $event
125
     */
126
    public function onMigrationBefore(MigrationEvent $event)
127
    {
128
        if (!$this->progress) {
129
            $version = $event->getVersion();
130
            $this->output->writeln(sprintf(
131
                '<info>[%s]</info> <comment>%s</comment>',
132
                $version->getId(),
133
                strtoupper($event->getOptions()->getDirection())
134
            ));
135
        }
136
    }
137
138
    /**
139
     * onMigrationAfter.
140
     *
141
     * @param MigrationEvent $event
142
     */
143
    public function onMigrationAfter(MigrationEvent $event)
144
    {
145
        if ($this->progress) {
146
            $runProgress = $event->getProgress();
147
            $this->progress->setProgress($runProgress->getCurrent());
148
        }
149
    }
150
151
    /**
152
     * onCollectionBefore.
153
     *
154
     * @param CollectionEvent $event
155
     */
156
    public function onCollectionBefore(CollectionEvent $event)
157
    {
158
        $target = $event->getTarget();
159
160
        $this->output->writeln(sprintf(
161
            '<info>[START]</info> Migrating %s to <comment>%s</comment>:',
162
            $event->getOptions()->isDirectionUp() ? 'up' : 'down',
163
            $target->getId()
164
        ));
165
        if ($this->trackProgress) {
166
            $this->progress = new ProgressBar($this->output, $event->getProgress()->getTotal());
167
            $this->progress->setFormat('verbose');
168
            $this->progress->setProgress(0);
169
        }
170
    }
171
172
    /**
173
     * onCollectionAfter.
174
     */
175
    public function onCollectionAfter()
176
    {
177
        if ($this->progress) {
178
            $this->progress->finish();
179
            $this->output->writeln(''); // new line after progress bar
180
        }
181
        $this->output->writeln('<info>[END]</info>');
182
    }
183
184
    /**
185
     * @param InputInterface $input
186
     *
187
     * @return string
188
     *
189
     * @throws CliException
190
     */
191
    protected function getStrategyOption(InputInterface $input)
192
    {
193
        $strategy = strtolower($input->getOption(MigrateMessage::OPT_STRATEGY));
194
        if (!isset($this->strategies[$strategy])) {
195
            throw new CliException(sprintf(
196
                'Unknown strategy "%s". Must be one of: %s',
197
                $strategy,
198
                implode(', ', array_keys($this->strategies))
199
            ));
200
        }
201
202
        return $this->strategies[$strategy];
203
    }
204
}
205