Completed
Push — master ( b659c5...c65770 )
by Michael
10:22
created

SchemaUpdater   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 7
dl 0
loc 141
ccs 0
cts 90
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 2
A configure() 0 23 1
B processSql() 0 23 5
A getLatestDatabaseVersion() 0 22 3
A getUpdateFileNames() 0 13 1
1
<?php
2
declare(strict_types = 1);
3
/**
4
 * Contains SchemaUpdater class.
5
 *
6
 * PHP version 7.0+
7
 *
8
 * LICENSE:
9
 * This file is part of Yet Another Php Eve Api Library also know as Yapeal
10
 * which can be used to access the Eve Online API data and place it into a
11
 * database.
12
 * Copyright (C) 2014-2017 Michael Cummings
13
 *
14
 * This program is free software: you can redistribute it and/or modify it
15
 * under the terms of the GNU Lesser General Public License as published by the
16
 * Free Software Foundation, either version 3 of the License, or (at your
17
 * option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful, but WITHOUT
20
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
22
 * for more details.
23
 *
24
 * You should have received a copy of the GNU Lesser General Public License
25
 * along with this program. If not, see
26
 * <http://spdx.org/licenses/LGPL-3.0.html>.
27
 *
28
 * You should be able to find a copy of this license in the COPYING-LESSER.md
29
 * file. A copy of the GNU GPL should also be available in the COPYING.md file.
30
 *
31
 * @copyright 2014-2017 Michael Cummings
32
 * @license   LGPL-3.0+
33
 * @author    Michael Cummings <[email protected]>
34
 */
35
namespace Yapeal\Console\Schema;
36
37
use Symfony\Component\Console\Output\OutputInterface;
38
use Yapeal\Container\ContainerInterface;
39
use Yapeal\Event\YEMAwareTrait;
40
use Yapeal\Exception\YapealDatabaseException;
41
use Yapeal\Log\Logger;
42
43
/**
44
 * Class SchemaUpdater
45
 */
46
class SchemaUpdater extends AbstractSchemaCommon
47
{
48
    use YEMAwareTrait;
49
    /**
50
     * @param string             $name
51
     * @param ContainerInterface $dic
52
     *
53
     * @throws \Symfony\Component\Console\Exception\LogicException
54
     */
55
    public function __construct(string $name, ContainerInterface $dic)
56
    {
57
        $this->setDescription('Retrieves SQL from files and updates schema');
58
        $this->setDic($dic);
59
        $this->platform = $dic['Yapeal.Sql.platform'];
60
        $this->updateDirs = [$dic['Yapeal.Sql.dir']];
61
        if (!empty($dic['Yapeal.Sql.appDir'])) {
62
            $this->updateDirs[] = $dic['Yapeal.Sql.appDir'];
63
        }
64
        $this->setCsq($dic['Yapeal.Sql.Callable.CommonQueries']);
65
        $this->setPdo($dic['Yapeal.Sql.Callable.Connection']);
66
        $this->setYem($dic['Yapeal.Event.Callable.Mediator']);
67
        parent::__construct($name);
68
    }
69
    /**
70
     * Configures the current command.
71
     */
72
    protected function configure()
73
    {
74
        $help = <<<'HELP'
75
The <info>%command.full_name%</info> command is used to initialize (create) a new
76
 schema and tables to be used by Yapeal-ng. If you already have a
77
 config/yapeal.yaml file setup you can use the following:
78
79
    <info>php %command.full_name%</info>
80
81
EXAMPLES:
82
To use a configuration file in a different location:
83
    <info>%command.name% -c /my/very/special/config.yaml</info>
84
85
<info>NOTE:</info>
86
Only the Sql section of the configuration file will be used.
87
88
You can also use the command before setting up a configuration file like so:
89
    <info>%command.name% -o "localhost" -d "yapeal" -u "YapealUser" -p "secret"
90
91
HELP;
92
        $this->addOptions($help);
93
        $this->setAliases(['Database:Update']);
94
    }
95
    /**
96
     * @param OutputInterface $output
97
     *
98
     * @throws YapealDatabaseException
99
     * @throws \DomainException
100
     * @throws \InvalidArgumentException
101
     * @throws \LogicException
102
     * @throws \Symfony\Component\Console\Exception\LogicException
103
     * @throws \UnexpectedValueException
104
     */
105
    protected function processSql(OutputInterface $output)
106
    {
107
        $yem = $this->getYem();
108
        $latestVersion = $this->getLatestDatabaseVersion($output);
109
        $fileNames = $this->getUpdateFileNames($latestVersion);
110
        if (0 === count($fileNames)) {
111
            $mess = sprintf('<info>No SQL update files newer then current schema version %s were found</info>', $latestVersion);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 128 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
112
            $yem->triggerLogEvent('Yapeal.Log.log', Logger::INFO, strip_tags($mess));
113
            if ($output::VERBOSITY_QUIET !== $output->getVerbosity()) {
114
                $output->writeln($mess);
115
            }
116
            return;
117
        }
118
        foreach ($fileNames as $fileName) {
119
            if (false === $sqlStatements = $this->safeFileRead($fileName)) {
120
                $mess = sprintf('<error>Could NOT get contents of SQL file %s</error>', $fileName);
121
                $yem->triggerLogEvent('Yapeal.Log.log', Logger::INFO, strip_tags($mess));
122
                $output->writeln($mess);
123
                throw new YapealDatabaseException(strip_tags($mess), 2);
124
            }
125
            $this->executeSqlStatements($sqlStatements, $fileName, $output);
126
        }
127
    }
128
    /**
129
     * @param OutputInterface $output
130
     *
131
     * @return string
132
     * @throws YapealDatabaseException
133
     * @throws \DomainException
134
     * @throws \InvalidArgumentException
135
     * @throws \LogicException
136
     * @throws \UnexpectedValueException
137
     */
138
    private function getLatestDatabaseVersion(OutputInterface $output): string
139
    {
140
        $sql = $this->getCsq()
141
            ->getLatestYapealSchemaVersion();
142
        $this->getYem()
143
            ->triggerLogEvent('Yapeal.Log.log', Logger::DEBUG, 'sql - ' . $sql);
144
        $version = '19700101000001.000';
145
        try {
146
            $result = $this->getPdo()
147
                ->query($sql, \PDO::FETCH_NUM);
148
            $version = (string)$result->fetchColumn();
149
            $result->closeCursor();
150
        } catch (\PDOException $exc) {
151
            $sql = '<comment>' . $sql . '</comment>';
152
            $mess = sprintf('<error>Could NOT query latest database version. Aborting ...</error>', $version);
153
            if ($output::VERBOSITY_QUIET !== $output->getVerbosity()) {
154
                $output->writeln([$sql, $mess]);
155
            }
156
            throw new YapealDatabaseException(strip_tags($mess), 2);
157
        }
158
        return $version;
159
    }
160
    /**
161
     * @param string $latestVersion
162
     *
163
     * @return array|string[]
164
     */
165
    private function getUpdateFileNames(string $latestVersion): array
166
    {
167
        $fileExt = sprintf('.%s.sql', $this->platform);
168
        $globPath = sprintf('{%1$s}Updates/{*%2$s,*/*%2$s}',
169
            implode(',', $this->updateDirs),
170
            $fileExt);
171
        $regex = '%^.+?/\d{14}\.\d{3}\..+$%';
172
        $filteredNames = array_filter(preg_grep($regex, glob($globPath, GLOB_BRACE | GLOB_NOESCAPE)),
173
            function (string $fileName) use ($fileExt, $latestVersion) {
174
                return $latestVersion < basename($fileName, $fileExt);
175
            });
176
        return $filteredNames;
177
    }
178
    /**
179
     * @var string $platform
180
     */
181
    private $platform;
182
    /**
183
     * @var string[] $updateDirs
184
     */
185
    private $updateDirs;
186
}
187