Completed
Push — master ( f5a493...f6c233 )
by Joao
03:20
created

Migration::prepareEnvironment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 5
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace ByJG\DbMigration;
4
5
use ByJG\AnyDataset\ConnectionManagement;
6
use ByJG\AnyDataset\Repository\DBDataset;
7
use ByJG\DbMigration\Commands\CommandInterface;
8
9
class Migration
10
{
11
    /**
12
     * @var ConnectionManagement
13
     */
14
    protected $_connection;
15
16
    /**
17
     * @var string
18
     */
19
    protected $_folder;
20
21
    /**
22
     * @var DBDataset
23
     */
24
    protected $_dbDataset;
25
26
    /**
27
     * @var CommandInterface
28
     */
29
    protected $_dbCommand;
30
    
31
    /**
32
     * Migration constructor.
33
     *
34
     * @param ConnectionManagement $_connection
35
     * @param string $_folder
36
     */
37
    public function __construct(ConnectionManagement $_connection, $_folder)
38
    {
39
        $this->_connection = $_connection;
40
        $this->_folder = $_folder;
41
42
        if (!file_exists($this->_folder) || !is_dir($this->_folder)) {
43
            throw new \InvalidArgumentException("Base migrations directory '{$this->_folder}' not found");
44
        }
45
    }
46
47
    /**
48
     * @return DBDataset
49
     */
50
    public function getDbDataset()
51
    {
52
        if (is_null($this->_dbDataset)) {
53
            $this->_dbDataset = new DBDataset($this->_connection->getDbConnectionString());
54
        }
55
        return $this->_dbDataset;
56
    }
57
58
    /**
59
     * @return CommandInterface
60
     */
61
    public function getDbCommand()
62
    {
63
        if (is_null($this->_dbCommand)) {
64
            $class = $this->getCommandClassName();
65
            $this->_dbCommand = new $class($this->getDbDataset());
66
        }
67
        return $this->_dbCommand;
68
    }
69
70
    protected function getCommandClassName()
71
    {
72
        return "\\ByJG\\DbMigration\\Commands\\" . ucfirst($this->_connection->getDriver()) . "Command";
73
    }
74
75
    /**
76
     * Get the full path and name of the "base.sql" script
77
     *
78
     * @return string
79
     */
80
    public function getBaseSql()
81
    {
82
        return $this->_folder . "/base.sql";
83
    }
84
85
    /**
86
     * Get the full path script based on the version
87
     *
88
     * @param $version
89
     * @param $increment
90
     * @return string
91
     */
92
    public function getMigrationSql($version, $increment)
93
    {
94
        return $this->_folder 
95
            . "/migrations" 
96
            . "/" . ($increment < 0 ? "down" : "up")
97
            . "/" . str_pad($version, 5, '0', STR_PAD_LEFT) . ".sql";
98
    }
99
100
    /**
101
     * Create the database it it does not exists. Does not use this methos in a production environment; 
102
     */
103
    public function prepareEnvironment()
104
    {
105
        $class = $this->getCommandClassName();
106
        $class::prepareEnvironment($this->_connection);
107
    }
108
    
109
    /**
110
     * Restore the database using the "base.sql" script and run all migration scripts
111
     * Note: the database must exists. If dont exist run the method prepareEnvironment.  
112
     *
113
     * @param int $upVersion
114
     */
115
    public function reset($upVersion = null)
116
    {
117
        $this->getDbCommand()->dropDatabase();
118
        $this->getDbCommand()->createDatabase();
119
        $this->getDbCommand()->executeSql(file_get_contents($this->getBaseSql()));
120
        $this->getDbCommand()->createVersion();
121
        $this->up($upVersion);
122
    }
123
124
    /**
125
     * Get the current database version
126
     *
127
     * @return int
128
     */
129
    public function getCurrentVersion()
130
    {
131
        return intval($this->getDbCommand()->getVersion());
132
    }
133
134
    /**
135
     * @param $currentVersion
136
     * @param $upVersion
137
     * @param $increment
138
     * @return bool
139
     */
140
    protected function canContinue($currentVersion, $upVersion, $increment)
141
    {
142
        $existsUpVersion = ($upVersion !== null);
143
        $compareVersion = strcmp(
144
                str_pad($currentVersion, 5, '0', STR_PAD_LEFT),
145
                str_pad($upVersion, 5, '0', STR_PAD_LEFT)
146
            ) == $increment;
147
148
        return !($existsUpVersion && $compareVersion);
149
    }
150
151
    /**
152
     * Method for execute the migration.
153
     *
154
     * @param int $upVersion
155
     * @param int $increment Can accept 1 for UP or -1 for down
156
     */
157
    protected function migrate($upVersion, $increment)
158
    {
159
        $currentVersion = $this->getCurrentVersion() + $increment;
160
        
161
        while ($this->canContinue($currentVersion, $upVersion, $increment)
162
            && file_exists($file = $this->getMigrationSql($currentVersion, $increment))
163
        ) {
164
            $this->getDbCommand()->executeSql(file_get_contents($file));
165
            $this->getDbCommand()->setVersion($currentVersion++);
166
        }
167
    }
168
169
    /**
170
     * Run all scripts to up the database version from current up to latest version or the specified version.
171
     *
172
     * @param int $upVersion
173
     */
174
    public function up($upVersion = null)
175
    {
176
        $this->migrate($upVersion, 1);
177
    }
178
179
    /**
180
     * Run all scripts to down the database version from current version up to the specified version.
181
     *
182
     * @param int $upVersion
183
     */
184
    public function down($upVersion)
185
    {
186
        $this->migrate($upVersion, -1);
187
    }
188
}
189