Skip to content

Commit 1cdd1a0

Browse files
committed
More code for up command
1 parent 39e02bc commit 1cdd1a0

File tree

2 files changed

+196
-7
lines changed

2 files changed

+196
-7
lines changed

src/Smrtr/MysqlVersionControl/DbConfig.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public static function getEnvironments()
1818
return $config['environments'];
1919
}
2020

21+
public static function getTestingEnvironments()
22+
{
23+
$config = new \Zend_Config_Ini(self::getConfigFile(), 'environments');
24+
$config = $config->toArray();
25+
return $config['testing_environments'];
26+
}
27+
2128
public static function getPDO($env, $buildtime = false)
2229
{
2330
$key = $buildtime ? 'buildtime' : 'runtime';

src/Smrtr/MysqlVersionControl/UpCommand.php

Lines changed: 189 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
namespace Smrtr\MysqlVersionControl;
44

5-
use Symfony\Component\Console\Application;
65
use Symfony\Component\Console\Command\Command;
76
use Symfony\Component\Console\Input\InputArgument;
87
use Symfony\Component\Console\Input\InputInterface;
98
use Symfony\Component\Console\Input\InputOption;
109
use Symfony\Component\Console\Output\OutputInterface;
10+
use Symfony\Component\Process\Process;
1111

1212
/**
1313
* Class UpCommand
@@ -52,12 +52,194 @@ protected function configure()
5252
*/
5353
protected function execute(InputInterface $input, OutputInterface $output)
5454
{
55-
Controller::update(
56-
$this->env,
57-
$output,
58-
$this->getHelperSet()->get('dialog'),
59-
(bool) $input->getOption('confirm'),
60-
$input->getArgument('mysqlbin') ?: 'mysql'
55+
$mysqlbin = $input->getArgument('mysqlbin') ?: 'mysql';
56+
$buildConf = DbConfig::getPDO($this->env, true);
57+
$runConf = DbConfig::getPDO($this->env);
58+
59+
// 1. Make sure that db_config table is present
60+
61+
$output->writeln('');
62+
$output->writeln('Checking database status... ');
63+
$output->writeln('');
64+
65+
66+
if (!$buildConf instanceof \PDO) {
67+
$output->writeln('<error>Failed: unable to obtain a database connection.</error>');
68+
return false;
69+
}
70+
71+
if ($buildConf->query("SHOW TABLES LIKE 'db_config'")->rowCount()) {
72+
73+
$output->writeln('<info>Database version control is already installed.</info>');
74+
self::$checkList['db-schema'] = true;
75+
return true;
76+
77+
} else {
78+
79+
$output->writeln('Installing version control...');
80+
81+
$result = $buildConf->query(
82+
"CREATE TABLE `db_config`
83+
(
84+
`key` VARCHAR(50) COLLATE 'utf8_general_ci' NOT NULL,
85+
`value` TEXT,
86+
`created_at` DATETIME,
87+
`updated_at` DATETIME,
88+
PRIMARY KEY (`key`),
89+
UNIQUE INDEX `db_config_U_1` (`key`)
90+
) ENGINE=MyISAM;"
91+
)
92+
->execute();
93+
94+
if (!$result) {
95+
$output->writeln('<error>Installing version control failed.</error>');
96+
return false;
97+
}
98+
99+
$output->writeln('<info>Installed version control successfully.</info>');
100+
}
101+
102+
// 2. Check for current version and available version
103+
104+
// what is the current version?
105+
$query = $runConf->query("SELECT `value` FROM `db_config` WHERE `key`='version'");
106+
if ($query->rowCount()) {
107+
$versionRow = $query->fetch(\PDO::FETCH_ASSOC);
108+
$currentVersion = (int) $versionRow['value'];
109+
} else {
110+
$currentVersion = 0;
111+
}
112+
113+
// what is the available version?
114+
$availableVersion = 0;
115+
$versionsPath = realpath(dirname(__FILE__).'/../../../../../../db/versions');
116+
foreach (scandir($versionsPath) as $path) {
117+
if (preg_match("/^(\\d)+$/", $path) && (int) $path > $availableVersion) {
118+
$availableVersion = (int) $path;
119+
}
120+
}
121+
122+
if ($currentVersion >= $availableVersion) {
123+
$output->writeln('<info>Database version is already up to date.</info>');
124+
return true;
125+
}
126+
127+
$noun = ($availableVersion - $currentVersion > 1) ? 'updates' : 'update';
128+
$output->writeln(
129+
"Installing database $noun (Current version: $currentVersion, Available version: $availableVersion)..."
61130
);
131+
132+
// go from current to latest version, building stack of SQL files
133+
$filesToLookFor = [];
134+
$filesToLookFor[] = 'schema.sql'; // structural changes, alters, creates, drops
135+
$filesToLookFor[] = 'data.sql'; // core data, inserts, replaces, updates, deletes
136+
if (in_array($this->env, DbConfig::getTestingEnvironments())) {
137+
$filesToLookFor[] = 'testing.sql'; // extra data on top of data.sql for the testing environment(s)
138+
}
139+
$filesToLookFor[] = 'runme.php'; // custom php hook
140+
141+
$stack = array();
142+
for ($i = $currentVersion + 1; $i <= $availableVersion; $i++) {
143+
144+
$path = $versionsPath.DIRECTORY_SEPARATOR.$i;
145+
if (!is_dir($path) || !is_readable($path)) {
146+
continue;
147+
}
148+
149+
foreach ($filesToLookFor as $file) {
150+
if (is_readable($path.DIRECTORY_SEPARATOR.$file)) {
151+
$stack[$i][$file] = $path.DIRECTORY_SEPARATOR.$file;
152+
}
153+
}
154+
}
155+
156+
$s = '\\' == DIRECTORY_SEPARATOR ? "%s" : "'%s'"; // Windows doesn't like quoted params
157+
$cmdMySQL = "$mysqlbin -h $s --user=$s --password=$s --database=$s < %s";
158+
159+
// loop sql file stack and execute on mysql CLI
160+
161+
$dbConf = DbConfig::getConfig($this->env);
162+
163+
$previousVersion = $currentVersion;
164+
$result = true;
165+
foreach ($stack as $version => $files) {
166+
167+
$output->write($previousVersion." -> $version ");
168+
169+
if (!$result) {
170+
$output->write('skipped');
171+
continue;
172+
}
173+
174+
foreach ($files as $file) {
175+
176+
if ('schema.sql' === $file) {
177+
$conf = $dbConf['buildtime'];
178+
} else {
179+
$conf = $dbConf['runtime'];
180+
}
181+
$host = $conf['host'];
182+
$user = $conf['user'];
183+
$pass = $conf['password'];
184+
$name = $conf['database'];
185+
186+
if ('.sql' === substr($file, -4)) {
187+
188+
$command = sprintf(
189+
$cmdMySQL,
190+
$host,
191+
$user,
192+
$pass,
193+
$name,
194+
$file
195+
);
196+
197+
$process = new Process($command);
198+
$process->run();
199+
200+
if (!$process->isSuccessful()) {
201+
$result = false;
202+
break;
203+
}
204+
205+
continue;
206+
}
207+
208+
if ('.php' === substr($file, -4)) {
209+
210+
$feedback = require_once $file;
211+
}
212+
}
213+
214+
if ($result) {
215+
$result = $buildConf->query(
216+
"REPLACE INTO `db_config` (`key`, `value`, `updated_at`) VALUES ('version', $version, now())"
217+
)->execute();
218+
}
219+
220+
$statusMsg = $result ? '<info>OK</info>' : '<error>Failed</error>';
221+
$output->write($statusMsg, true);
222+
223+
if (isset($feedback) && is_string($feedback) && strlen($feedback)) {
224+
$output->write($feedback);
225+
unset($feedback);
226+
}
227+
228+
if (!$result) {
229+
$output->write('<error>'.$process->getErrorOutput().'</error>');
230+
}
231+
232+
$previousVersion = $version;
233+
}
234+
235+
if ($result) {
236+
$output->writeln('<info>Database updates installed successfully.</info>');
237+
self::$checkList['db-update'] = true;
238+
return true;
239+
240+
} else {
241+
$output->writeln('<error>Installing database updates failed.</error>');
242+
return false;
243+
}
62244
}
63245
}

0 commit comments

Comments
 (0)