Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
141 / 141
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
MigrationController
100.00% covered (success)
100.00%
141 / 141
100.00% covered (success)
100.00%
5 / 5
46
100.00% covered (success)
100.00%
1 / 1
 create
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
6
 run
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
1 / 1
9
 rollback
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
1 / 1
9
 point
100.00% covered (success)
100.00%
36 / 36
100.00% covered (success)
100.00%
1 / 1
14
 reset
100.00% covered (success)
100.00%
29 / 29
100.00% covered (success)
100.00%
1 / 1
8
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (http://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/pop-bootstrap
7 * @author     Nick Sagona, III <nick@noladev.com>
8 * @copyright  Copyright (c) 2012-2025 NOLA Interactive, LLC.
9 * @license    http://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Kettle\Controller;
16
17use Pop\Console\Color;
18use Pop\Db\Sql\Migrator;
19use Pop\Kettle\Model;
20
21/**
22 * Console database controller class
23 *
24 * @category   Pop\Kettle
25 * @package    Pop\Kettle
26 * @author     Nick Sagona, III <nick@noladev.com>
27 * @copyright  Copyright (c) 2012-2025 NOLA Interactive, LLC.
28 * @license    http://www.popphp.org/license     New BSD License
29 * @version    3.0.0
30 */
31class MigrationController extends AbstractController
32{
33
34    /**
35     * Create command
36     *
37     * @param  string  $class
38     * @param  ?string $database
39     * @return void
40     */
41    public function create(string $class, ?string $database = 'default'): void
42    {
43        $location  = getcwd();
44
45        if ($database === null) {
46            $databases = ['default'];
47        } else if ($database == 'all') {
48            $databases = array_filter(scandir($location . '/database/migrations'), function($value) {
49                return (($value != '.') && ($value != '..'));
50            });
51        } else {
52            $databases = [$database];
53        }
54
55        foreach ($databases as $db) {
56            if (!file_exists($location . '/database/migrations/' . $db)) {
57                mkdir($location . '/database/migrations/' . $db);
58            }
59
60            $migrationClass = $class . uniqid();
61            Migrator::create($migrationClass, $location . '/database/migrations/' . $db);
62            $this->console->write("Migration class '" . $migrationClass . "' created for '" . $db . "'.");
63        }
64    }
65
66    /**
67     * Run command
68     *
69     * @param  int|string|null $steps
70     * @param  ?string         $database
71     * @return void
72     */
73    public function run(int|string|null $steps = 1, ?string $database = 'default'): void
74    {
75        $location = getcwd();
76        $dbModel  = new Model\Database();
77
78        if ($database === null) {
79            $databases = ['default'];
80        } else if ($database == 'all') {
81            $databases = array_filter(scandir($location . '/database/migrations'), function($value) {
82                return (($value != '.') && ($value != '..'));
83            });
84        } else {
85            $databases = [$database];
86        }
87
88        if ($steps === null) {
89            $steps = 1;
90        }
91
92        if (!file_exists($location . '/app/config/database.php')) {
93            $this->console->write($this->console->colorize(
94                'The database configuration was not found.', Color::BOLD_RED
95            ));
96        } else {
97            foreach ($databases as $db) {
98                if (!file_exists($location . '/database/migrations/' . $db)) {
99                    $this->console->write($this->console->colorize(
100                        "The database migration folder was not found for '" . $db . "'.", Color::BOLD_RED
101                    ));
102                } else {
103                    $this->console->write("Running database migration for '" . $db . "'...");
104
105                    $dbConfig = include $location . '/app/config/database.php';
106                    if (!isset($dbConfig[$db])) {
107                        $this->console->write($this->console->colorize(
108                            "The database configuration was not found for '" . $db . "'.", Color::BOLD_RED
109                        ));
110                    } else {
111                        $dbAdapter = $dbModel->createAdapter($dbConfig[$db]);
112                        $migrator  = new Migrator($dbAdapter, $location . '/database/migrations/' . $db);
113                        $migrator->run($steps);
114                        $this->console->write();
115                        $this->console->write('Done!');
116                    }
117                }
118            }
119        }
120    }
121
122    /**
123     * Rollback command
124     *
125     * @param  int|string|null $steps
126     * @param  ?string         $database
127     * @return void
128     */
129    public function rollback(int|string|null $steps = 1, ?string $database = 'default'): void
130    {
131        $location = getcwd();
132        $dbModel  = new Model\Database();
133
134        if ($database === null) {
135            $databases = ['default'];
136        } else if ($database == 'all') {
137            $databases = array_filter(scandir($location . '/database/migrations'), function($value) {
138                return (($value != '.') && ($value != '..'));
139            });
140        } else {
141            $databases = [$database];
142        }
143
144        if ($steps === null) {
145            $steps = 1;
146        }
147
148        if (!file_exists($location . '/app/config/database.php')) {
149            $this->console->write($this->console->colorize(
150                'The database configuration was not found.', Color::BOLD_RED
151            ));
152        } else {
153            foreach ($databases as $db) {
154                if (!file_exists($location . '/database/migrations/' . $db)) {
155                    $this->console->write($this->console->colorize(
156                        "The database migration folder was not found for '" . $db . "'.", Color::BOLD_RED
157                    ));
158                } else {
159                    $this->console->write("Rolling back database migration for '" . $db . "'...");
160
161                    $dbConfig = include $location . '/app/config/database.php';
162                    if (!isset($dbConfig[$db])) {
163                        $this->console->write($this->console->colorize(
164                            "The database configuration was not found for '" . $db . "'.", Color::BOLD_RED
165                        ));
166                    } else {
167                        $dbAdapter = $dbModel->createAdapter($dbConfig[$db]);
168                        $migrator  = new Migrator($dbAdapter, $location . '/database/migrations/' . $db);
169                        $migrator->rollback($steps);
170                        $this->console->write();
171                        $this->console->write('Done!');
172                    }
173                }
174            }
175        }
176    }
177
178    /**
179     * Point command
180     *
181     * @param  mixed   $id
182     * @param  ?string $database
183     * @return void
184     */
185    public function point(mixed $id = 'latest', ?string $database = 'default'): void
186    {
187        $location = getcwd();
188
189        if ($id === null) {
190            $id = 'latest';
191        }
192        if ($database === null) {
193            $database = 'default';
194        }
195
196        if (!file_exists($location . '/database/migrations/' . $database)) {
197            $this->console->write($this->console->colorize(
198                "The database '" . $database . "' does not exist in the migration folder.", Color::BOLD_RED
199            ));
200        } else if (file_exists($location . '/database/migrations/' . $database . '/.current')) {
201            $ids = array_map(function($value) {
202                return substr($value, 0, strpos($value, '_'));
203            },
204                array_values(array_filter(scandir($location . '/database/migrations/' . $database), function ($value) {
205                        return ($value != '.') && ($value != '..') && ($value != '.current') && ($value != '.empty') && (stripos($value, '_') !== false);
206                    })
207                ));
208
209            if (!empty($ids)) {
210                sort($ids, SORT_NUMERIC);
211            }
212
213            if (empty($ids)) {
214                $this->console->write($this->console->colorize(
215                    "No migrations for the database '" . $database . "' were found.", Color::BOLD_RED
216                ));
217            } else if (is_numeric($id)) {
218                if (!in_array($id, $ids)) {
219                    $this->console->write($this->console->colorize(
220                        "The migration '" . $id . "' for the database '" . $database . "' does not exist.", Color::BOLD_RED
221                    ));
222                } else {
223                    file_put_contents($location . '/database/migrations/' . $database . '/.current', $id);
224                    $this->console->write();
225                    $this->console->write('Done!');
226                }
227            } else if ($id == 'latest') {
228                $id = end($ids);
229                file_put_contents($location . '/database/migrations/' . $database . '/.current', $id);
230                $this->console->write();
231                $this->console->write('Done!');
232            }
233        }
234    }
235
236    /**
237     * Reset command
238     *
239     * @param  ?string $database
240     * @return void
241     */
242    public function reset(?string $database = 'default'): void
243    {
244        $location = getcwd();
245        $dbModel  = new Model\Database();
246
247        if ($database === null) {
248            $databases = ['default'];
249        } else if ($database == 'all') {
250            $databases = array_filter(scandir($location . '/database/migrations'), function($value) {
251                return (($value != '.') && ($value != '..'));
252            });
253        } else {
254            $databases = [$database];
255        }
256
257        if (!file_exists($location . '/app/config/database.php')) {
258            $this->console->write($this->console->colorize(
259                'The database configuration was not found.', Color::BOLD_RED
260            ));
261        } else {
262            foreach ($databases as $db) {
263                if (!file_exists($location . '/database/migrations/' . $db)) {
264                    $this->console->write($this->console->colorize(
265                        "The database migration folder was not found for '" . $db . "'.", Color::BOLD_RED
266                    ));
267                } else {
268                    $this->console->write("Resetting the database for '" . $db . "'...");
269
270                    $dbConfig = include $location . '/app/config/database.php';
271                    if (!isset($dbConfig[$db])) {
272                        $this->console->write($this->console->colorize(
273                            "The database configuration was not found for '" . $db . "'.", Color::BOLD_RED
274                        ));
275                    } else {
276                        $dbAdapter = $dbModel->createAdapter($dbConfig[$db]);
277                        $migrator  = new Migrator($dbAdapter, $location . '/database/migrations/' . $db);
278                        $migrator->rollbackAll();
279                        $this->console->write();
280                        $this->console->write('Done!');
281                    }
282                }
283            }
284        }
285    }
286
287}