Completed
Branch dev (b4f2c3)
by James Ekow Abaka
03:46
created

Yentu::setConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * The MIT License
5
 *
6
 * Copyright 2015 James Ekow Abaka Ainooson.
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
 * THE SOFTWARE.
25
 */
26
27
namespace yentu;
28
use clearice\io\Io;
29
use yentu\factories\DatabaseManipulatorFactory;
30
31
32
/**
33
 * Utility class for yentu related functions.
34
 */
35
class Yentu
36
{
37
38
    /**
39
     * The current home path for yentu.
40
     * The home path represents the location of migrations and the configurations used for the yentu session.
41
     *
42
     * @var string
43
     */
44
    private $home;
45
46
    /**
47
     * An instance of the clearice Io class
48
     * @var Io
49
     */
50
    private $io;
51
    private $databaseManipulatorFactory;
52
    private $migrationVariables;
53
    private $otherMigrations;
54
55
    /**
56
     * Current version of yentu.
57
     * @var string
58
     */
59
    const VERSION = 'v0.3.0';
60
61 39
    public function __construct(Io $io, DatabaseManipulatorFactory $databaseManipulatorFactory, $migrationVariables = [], $otherMigrations = [])
62
    {
63 39
        $this->databaseManipulatorFactory = $databaseManipulatorFactory;
64 39
        $this->io = $io;
65 39
        $this->migrationVariables = $migrationVariables;
66 39
        $this->otherMigrations = $otherMigrations;
67 39
    }
68
69
    /**
70
     * Set the current home of yentu.
71
     * The home of yentu contains is a directory which contains the yentu 
72
     * configurations and migrations. Configurations are stored in the config
73
     * sub directory and the migrations are stored in the migrations sub
74
     * directory. 
75
     * @param string $home
76
     */
77 39
    public function setDefaultHome($home)
78
    {
79 39
        $this->home = $home;
80 39
    }
81
82
    /**
83
     * Returns a path relative to the current yentu home.
84
     * @param string $path
85
     * @return string
86
     */
87 39
    public function getPath($path)
88
    {
89 39
        return $this->home . "/$path";
90
    }
91
92
    /**
93
     * Returns an array of all migrations that have been run on the database.
94
     * The information returned includes the timestamp, the name of the migration
95
     * and the default schema on which it was run.
96
     *
97
     * @return array
98
     * @throws exceptions\DatabaseManipulatorException
99
     */
100
    public function getExecutedMigrations()
101
    {
102
        $db = $this->databaseManipulatorFactory->createManipulator();
103
        $runMigrations = $db->query("SELECT DISTINCT version, migration, default_schema FROM yentu_history ORDER BY version");
104
        $migrations = array();
105
        foreach ($runMigrations as $migration) {
106
            $migrations[$migration['version']] = array(
107
                'timestamp' => $migration['version'],
108
                'migration' => $migration['migration'],
109
                'default_schema' => $migration['default_schema']
110
            );
111
        }
112
113
        return $migrations;
114
    }
115
116
    /**
117
     * Returns an array of all migrations, in all configured migrations directories.
118
     *
119
     * @return array
120
     */
121
    public function getAllMigrations()
122
    {
123
        $migrations = array();
124
        foreach ($this->getMigrationPaths() as $migration) {
125
            $migrations = $migrations + $this->getMigrationsFromPath($migration['home']);
126
        }
127
        return $migrations;
128
    }
129
130 9
    public function getMigrationPaths()
131
    {
132 9
        return array_merge(
133
            array(
134
                array(
135 9
                    'home' => $this->getPath('migrations'),
136 9
                    'variables' => $this->migrationVariables
137
                )
138 9
            ), $this->otherMigrations
139
        );
140
    }
141
142
    /**
143
     * Return an array of all migrations from a given migration path
144
     * 
145
     * @param string $path
146
     * @return array
147
     */
148 9
    public function getMigrationsFromPath($path)
149
    {
150 9
        if (!file_exists($path))
151
            return [];
152 9
        $migrationFiles = scandir($path, 0);
153 9
        $migrations = array();
154 9
        foreach ($migrationFiles as $migration) {
155 9
            $details = $this->getMigrationDetails($migration);
156 9
            if ($details === false)
157 9
                continue;
158 9
            $migrations[$details['timestamp']] = $details;
159 9
            unset($migrations[$details['timestamp']][0]);
160 9
            unset($migrations[$details['timestamp']][1]);
161 9
            unset($migrations[$details['timestamp']][2]);
162
        }
163
164 9
        return $migrations;
165
    }
166
167
    /**
168
     * Return the details of a migration extracted from the file name. This method uses a regular expression to extract
169
     * the timestamp and migration name from the migration script.
170
     * 
171
     * @param string $migration
172
     * @return array|bool
173
     */
174 9
    private function getMigrationDetails($migration)
175
    {
176 9
        if (preg_match("/^(?<timestamp>[0-9]{14})\_(?<migration>[a-z][a-z0-9\_]*)\.php$/", $migration, $details)) {
177 9
            $details['file'] = $migration;
178
        } else {
179 9
            $details = false;
180
        }
181 9
        return $details;
182
    }
183
184
    /**
185
     * Announce a migration based on the command and the arguments called for the migration.
186
     * 
187
     * @param string $command The action being performed
188
     * @param string $itemType The type of item
189
     * @param array $arguments The arguments of the 
190
     */
191 9
    public function announce($command, $itemType, $arguments)
192
    {
193 9
        $this->io->output(
194 9
            "\n  - " . ucfirst("{$command}ing ") .
195 9
            preg_replace("/([a-z])([A-Z])/", "$1 $2", $itemType) . " " .
196 9
            $this->getEventDescription($command, Parameters::wrap($arguments)), Io::OUTPUT_LEVEL_2
197
        );
198 9
        $this->io->output(".");
199 9
    }
200
201
    /**
202
     * Convert the arguments of a migration event to a string description.
203
     * 
204
     * @param string $command
205
     * @param array $arguments
206
     * @return string
207
     */
208 9
    private function getEventDescription($command, $arguments)
209
    {
210 9
        $dir = '';
211 9
        $destination = '';
212 9
        $arguments = Parameters::wrap($arguments, ['name' => null]);
213
214 9
        if ($command == 'add') {
215 9
            $dir = 'to';
216 6
        } else if ($command == 'drop') {
217
            $dir = 'from';
218
        }
219
220 9
        if (isset($arguments['table']) && isset($arguments['schema'])) {
221
            $destination = "table " .
222 9
                ($arguments['schema'] != '' ? "{$arguments['schema']}." : '' ) .
223 9
                "{$arguments['table']}'";
224 9
        } elseif (isset($arguments['schema']) && !isset($arguments['table'])) {
225 9
            $destination = "schema '{$arguments['schema']}'";
226
        }
227
228 9
        if (is_string($arguments)) {
229
            return $arguments;
230
        }
231
232 9
        if (isset($arguments['column'])) {
233 9
            $item = $arguments['column'];
234
        } else {
235 9
            $item = $arguments['name'];
236
        }
237
238 9
        return "'$item' $dir $destination";
239
    }
240
241
    /**
242
     * Reverses a command which is reversible.
243
     * 
244
     * @param \yentu\Reversible $command
245
     */
246
    public function reverseCommand($command)
247
    {
248
        if ($command instanceof \yentu\Reversible) {
249
            $command->reverse();
250
        }
251
    }
252
    
253
    /**
254
     * Display the greeting for the CLI user interface.
255
     */
256 39
    public function greet()
257
    {
258 39
        $version = $this->getVersion();
259
        $welcome = <<<WELCOME
260
Yentu Database Migration Tool
261 39
Version $version
262
263
264
WELCOME;
265 39
        $this->io->output($welcome);
266 39
    }
267
268 39
    public function getVersion()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
269
    {
270 39
        if (defined('PHING_BUILD_VERSION')) {
271 39
            return PHING_BUILD_VERSION;
272
        } else {
273
            $version = new \SebastianBergmann\Version(Yentu::VERSION, dirname(__DIR__));
274
            return $version->getVersion();
275
        }
276
    }
277
278
}
279