Migrations::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 5
rs 10
1
<?php
2
3
namespace yentu;
4
5
use clearice\io\Io;
6
use yentu\factories\DatabaseManipulatorFactory;
7
8
9
/**
10
 * Provides an interface for accessing migrations.
11
 *
12
 * @package yentu
13
 */
14
class Migrations
15
{
16
    /**
17
     * An instance of the database manipulator.
18
     * @var DatabaseManipulatorFactory
19
     */
20
    private $manipulatorFactory;
21
    private $config;
22
    private $io;
23
24
    public function __construct(Io $io, DatabaseManipulatorFactory $manipulatorFactory, array $config = [])
25
    {
26
        $this->manipulatorFactory = $manipulatorFactory;
27
        $this->config = $config;
28
        $this->io = $io;
29
    }
30
31
    public function getAllPaths()
32
    {
33
        return array_merge(
34
            array(
35
                array(
36
                    'home' => $this->getPath('migrations'),
37
                    'variables' => $this->config['variables'] ?? []
38
                )
39
            ), $this->config['other_migrations'] ?? []
40
        );
41
    }
42
43
    /**
44
     * Return an array of all migrations available.
45
     *
46
     * @param string $path
47
     * @return array
48
     */
49
    public function getMigrationFiles($path)
50
    {
51
        if (!file_exists($path))
52
            return [];
53
        $migrationFiles = scandir($path, 0);
54
        $migrations = array();
55
        foreach ($migrationFiles as $migration) {
56
            $details = $this->getMigrationDetails($migration);
57
            if ($details === false)
58
                continue;
59
            $migrations[$details['timestamp']] = $details;
60
            unset($migrations[$details['timestamp']][0]);
61
            unset($migrations[$details['timestamp']][1]);
62
            unset($migrations[$details['timestamp']][2]);
63
        }
64
65
        return $migrations;
66
    }
67
68
    /**
69
     * Return the details of a migration extracted from the file name.
70
     * This method uses a regular expression to extract the timestamp and
71
     * migration name from the migration script.
72
     *
73
     * @param string $migration
74
     * @return array|bool
75
     */
76
    private function getMigrationDetails($migration)
77
    {
78
        if (preg_match("/^(?<timestamp>[0-9]{14})\_(?<migration>[a-z][a-z0-9\_]*)\.php$/", $migration, $details)) {
79
            $details['file'] = $migration;
80
        } else {
81
            $details = false;
82
        }
83
        return $details;
84
    }
85
    /**
86
     * Returns an array of all migrations, in all configured migrations
87
     * directories.
88
     * @return array
89
     */
90
    public function getAllMigrations()
91
    {
92
        $migrations = array();
93
        foreach ($this->getAllPaths() as $migration) {
94
            $migrations = $migrations + $this->getMigrationFiles($migration['home']);
95
        }
96
        return $migrations;
97
    }
98
99
100
    /**
101
     * Returns an array of all migrations that have been run on the database.
102
     * The information returned includes the timestamp, the name of the migration
103
     * and the default schema on which it was run.
104
     * @return array
105
     * @throws exceptions\DatabaseManipulatorException
106
     */
107
    public function getRunMirations()
108
    {
109
        $db = $this->manipulatorFactory->createManipulator();
110
        $runMigrations = $db->query("SELECT DISTINCT version, migration, default_schema FROM yentu_history ORDER BY version");
111
        $migrations = array();
112
        foreach ($runMigrations as $migration) {
113
            $migrations[$migration['version']] = array(
114
                'timestamp' => $migration['version'],
115
                'migration' => $migration['migration'],
116
                'default_schema' => $migration['default_schema']
117
            );
118
        }
119
120
        return $migrations;
121
    }
122
123
    /**
124
     * Returns a path relative to the current yentu home.
125
     * @param string $path
126
     * @return string
127
     */
128
    public function getPath($path)
129
    {
130
        return ($this->config['home'] ?? './yentu') . DIRECTORY_SEPARATOR . $path;
131
    }
132
133
134
    /**
135
     * Announce a migration based on the command and the arguments called for
136
     * the migration.
137
     *
138
     * @param string $command The action being performed
139
     * @param string $itemType The type of item
140
     * @param array $arguments The arguments of the
141
     */
142
    public function announce($command, $itemType, $arguments)
143
    {
144
        $this->io->output(
145
            "\n  - " . ucfirst("{$command}ing ") .
146
            preg_replace("/([a-z])([A-Z])/", "$1 $2", $itemType) . " " .
147
            $this->getMigrationEventDescription($command, Parameters::wrap($arguments)), Io::OUTPUT_LEVEL_2
148
        );
149
        $this->io->output(".");
150
    }
151
152
    /**
153
     * Convert the arguments of a migration event to a string description.
154
     *
155
     * @param string $command
156
     * @param array $arguments
157
     * @return string
158
     */
159
    private function getMigrationEventDescription($command, $arguments)
160
    {
161
        $dir = '';
162
        $destination = '';
163
        $arguments = Parameters::wrap($arguments, ['name' => null]);
164
165
        if ($command == 'add') {
166
            $dir = 'to';
167
        } else if ($command == 'drop') {
168
            $dir = 'from';
169
        }
170
171
        if (isset($arguments['table']) && isset($arguments['schema'])) {
172
            $destination = "table " .
173
                ($arguments['schema'] != '' ? "{$arguments['schema']}." : '' ) .
174
                "{$arguments['table']}'";
175
        } elseif (isset($arguments['schema']) && !isset($arguments['table'])) {
176
            $destination = "schema '{$arguments['schema']}'";
177
        }
178
179
        if (is_string($arguments)) {
180
            return $arguments;
181
        }
182
183
        if (isset($arguments['column'])) {
184
            $item = $arguments['column'];
185
        } else {
186
            $item = $arguments['name'];
187
        }
188
189
        return "'$item' $dir $destination";
190
    }
191
}