Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature migrations up/down #270

Merged
merged 28 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b5dcf76
Migrations up down
slawkens Sep 5, 2024
174accb
Merge branch 'develop' into feature/migrations-up-down
slawkens Sep 5, 2024
a5075d7
Merge branch 'develop' into feature/migrations-up-down
slawkens Nov 7, 2024
0c1d5ac
Merge branch 'develop' into feature/migrations-up-down
slawkens Nov 7, 2024
200be48
Add forum model
slawkens Nov 7, 2024
c7cb00f
Syntactic sugar for db structure changes
slawkens Nov 8, 2024
8aff9f3
Refactor migrations with $up & $down
slawkens Nov 8, 2024
c24c93a
Fix migrations upgrade and downgrade
slawkens Nov 8, 2024
0c332bd
Add migrate:to command
slawkens Nov 8, 2024
c3dd10a
Show error when mail is not enabled
slawkens Nov 8, 2024
92024cf
Fixes regarding to init.php
slawkens Nov 8, 2024
dead8e4
Add migrate command to manually upgrade db, incase auto migrate is di…
slawkens Nov 8, 2024
92de395
Fixed rest of the migrations
slawkens Nov 8, 2024
81d0ace
Limit max version of database
slawkens Nov 8, 2024
22aa80a
Don't allow minus number
slawkens Nov 8, 2024
71ec14c
Option to clear specified plugin settings by name
slawkens Nov 8, 2024
b6e0184
Version is required
slawkens Nov 8, 2024
88a0bc8
Fix PHPStan errors
slawkens Nov 8, 2024
99d77cb
Merge branch 'develop' into feature/migrations-up-down
slawkens Nov 12, 2024
cc8b0db
Merge branch 'develop' into feature/migrations-up-down
slawkens Nov 19, 2024
a4eb798
Unset $up after migration, to prevent executing same migration twice
slawkens Nov 19, 2024
4a148e3
Add database version to output
slawkens Nov 19, 2024
82bff4e
This is not needed
slawkens Nov 19, 2024
f8098fc
Update 5.php
slawkens Nov 19, 2024
2c852de
Set database_auto_migrate on install
slawkens Nov 19, 2024
f4ddf2b
Set blank & color only if current db version supports it
slawkens Nov 19, 2024
d6270a7
Fix duplicate function declaration
slawkens Nov 19, 2024
627fa97
Merge branch 'develop' into feature/migrations-up-down
slawkens Nov 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions aac
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ if(!IS_CLI) {
}

require_once SYSTEM . 'functions.php';
require_once SYSTEM . 'init.php';

define('SELF_NAME', basename(__FILE__));

use MyAAC\Plugins;
use Symfony\Component\Console\Application;

$application = new Application();
$application = new Application('MyAAC', MYAAC_VERSION);

$commandsGlob = glob(SYSTEM . 'src/Commands/*.php');
foreach ($commandsGlob as $item) {
Expand All @@ -34,7 +33,4 @@ foreach ($pluginCommands as $item) {
$application->add(require $item);
}

$application->setName('MyAAC');
$application->setVersion(MYAAC_VERSION);

$application->run();
1 change: 1 addition & 0 deletions install/steps/5-database.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
$configToSave['gzip_output'] = false;
$configToSave['cache_engine'] = 'auto';
$configToSave['cache_prefix'] = 'myaac_' . generateRandomString(8, true, false, true);
$configToSave['database_auto_migrate'] = true;

if(!$error) {
$content = '';
Expand Down
6 changes: 5 additions & 1 deletion system/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

defined('MYAAC') or die('Direct access not allowed!');

global $config;
if(!isset($config['installed']) || !$config['installed']) {
throw new RuntimeException('MyAAC has not been installed yet or there was error during installation. Please install again.');
}
Expand Down Expand Up @@ -142,7 +143,10 @@
}

// execute migrations
require SYSTEM . 'migrate.php';
$configDatabaseAutoMigrate = config('database_auto_migrate');
if (!isset($configDatabaseAutoMigrate) || $configDatabaseAutoMigrate) {
require SYSTEM . 'migrate.php';
}

// settings
$settings = Settings::getInstance();
Expand Down
24 changes: 24 additions & 0 deletions system/libs/pot/OTS_Base_DB.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,30 @@ public function delete($table, $data, $limit = 1)
$this->exec($query);
return true;
}

public function addColumn($table, $column, $definition): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' ADD ' . $this->fieldName($column) . ' ' . $definition . ';');
}

public function modifyColumn($table, $column, $definition): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' MODIFY ' . $this->fieldName($column) . ' ' . $definition . ';');
}

public function changeColumn($table, $from, $to, $definition): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' CHANGE ' . $this->fieldName($from) . ' ' . $this->fieldName($to) . ' ' . $definition . ';');
}

public function dropColumn($table, $column): void {
$this->exec('ALTER TABLE ' . $this->tableName($table) . ' DROP COLUMN ' . $this->fieldName($column) . ';');
}

public function renameTable($from, $to): void {
$this->exec('RENAME TABLE ' . $this->tableName($from) . ' TO ' . $this->tableName($to) . ';');
}

public function dropTable($table, $ifExists = true): void {
$this->exec('DROP TABLE ' . ($ifExists ? 'IF EXISTS' : '') . ' ' . $this->tableName($table) . ';');
}
/**
* LIMIT/OFFSET clause for queries.
*
Expand Down
12 changes: 12 additions & 0 deletions system/migrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
$db->revalidateCache();
for($i = $tmp + 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';

if (isset($up)) {
$up();
unset($up);
}

updateDatabaseConfig('database_version', $i);
}
}
Expand All @@ -26,6 +32,12 @@
$db->revalidateCache();
for($i = 1; $i <= DATABASE_VERSION; $i++) {
require SYSTEM . 'migrations/' . $i . '.php';

if (isset($up)) {
$up();
unset($up);
}

updateDatabaseConfig('database_version', $i);
}
}
8 changes: 8 additions & 0 deletions system/migrations/1-hooks.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE `myaac_hooks`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL DEFAULT '',
`type` INT(2) NOT NULL DEFAULT 0,
`file` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
28 changes: 14 additions & 14 deletions system/migrations/1.php
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<?php
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` MODIFY `ip` INT(11) NOT NULL DEFAULT 0;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` MODIFY `date` INT(11) NOT NULL DEFAULT 0;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "account_actions` MODIFY `action` VARCHAR(255) NOT NULL DEFAULT '';");
$db->query("
CREATE TABLE `myaac_hooks`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL DEFAULT '',
`type` INT(2) NOT NULL DEFAULT 0,
`file` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
/**
* @var OTS_DB_MySQL $db
*/

?>
$up = function () use ($db) {
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'ip', "INT(11) NOT NULL DEFAULT 0");
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'date', "INT(11) NOT NULL DEFAULT 0");
$db->modifyColumn(TABLE_PREFIX . 'account_actions', 'action', "VARCHAR(255) NOT NULL DEFAULT ''");

$db->query(file_get_contents(__DIR__ . '/1-hooks.sql'));
};

$down = function () use ($db) {
$db->dropTable(TABLE_PREFIX . 'hooks');
};
10 changes: 10 additions & 0 deletions system/migrations/10-admin_menu.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE `myaac_admin_menu`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`page` VARCHAR(255) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0,
`flags` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
37 changes: 22 additions & 15 deletions system/migrations/10.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
<?php
if(!$db->hasColumn(TABLE_PREFIX . 'hooks', 'ordering'))
$db->query("ALTER TABLE `" . TABLE_PREFIX . "hooks` ADD `ordering` INT(11) NOT NULL DEFAULT 0 AFTER `file`;");
/**
* @var OTS_DB_MySQL $db
*/

if(!$db->hasTable(TABLE_PREFIX . 'admin_menu'))
$db->query("
CREATE TABLE `myaac_admin_menu`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`page` VARCHAR(255) NOT NULL DEFAULT '',
`ordering` INT(11) NOT NULL DEFAULT 0,
`flags` INT(11) NOT NULL DEFAULT 0,
`enabled` INT(1) NOT NULL DEFAULT 1,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");
$up = function () use ($db) {
if (!$db->hasColumn(TABLE_PREFIX . 'hooks', 'ordering')) {
$db->addColumn(TABLE_PREFIX . 'hooks', 'ordering', "INT(11) NOT NULL DEFAULT 0 AFTER `file`");
}

if (!$db->hasTable(TABLE_PREFIX . 'admin_menu')) {
$db->query(file_get_contents(__DIR__ . '/10-admin_menu.sql'));
}
};

$down = function () use ($db) {
if ($db->hasColumn(TABLE_PREFIX . 'hooks', 'ordering')) {
$db->dropColumn(TABLE_PREFIX . 'hooks', 'ordering');
}

if ($db->hasTable(TABLE_PREFIX . 'admin_menu')) {
$db->dropTable(TABLE_PREFIX . 'admin_menu');
}
};
35 changes: 30 additions & 5 deletions system/migrations/11.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/

$up = function () use ($db) {
// rename database tables
$db->query("RENAME TABLE
" . TABLE_PREFIX . "screenshots TO " . TABLE_PREFIX . "gallery,
" . TABLE_PREFIX . "movies TO " . TABLE_PREFIX . "videos;");
$db->renameTable(TABLE_PREFIX . 'screenshots', TABLE_PREFIX . 'gallery');
$db->renameTable(TABLE_PREFIX . 'movies', TABLE_PREFIX . 'videos');

// rename images dir
if(file_exists(BASE . 'images/screenshots') && !file_exists(BASE . GALLERY_DIR)) {
if (file_exists(BASE . 'images/screenshots') && !file_exists(BASE . GALLERY_DIR)) {
rename(BASE . 'images/screenshots', BASE . GALLERY_DIR);
}

// convert old database screenshots images to gallery
$query = $db->query('SELECT `id`, `image`, `thumb` FROM `' . TABLE_PREFIX . 'gallery`;');
foreach($query->fetchAll() as $item) {
foreach ($query->fetchAll() as $item) {
$db->update(TABLE_PREFIX . 'gallery', array(
'image' => str_replace('/screenshots/', '/gallery/', $item['image']),
'thumb' => str_replace('/screenshots/', '/gallery/', $item['thumb']),
), array('id' => $item['id']));
}
};

$down = function () use ($db) {
// rename database tables
$db->renameTable(TABLE_PREFIX . 'gallery', TABLE_PREFIX . 'screenshots');
$db->renameTable(TABLE_PREFIX . 'videos', TABLE_PREFIX . 'movies');

// rename images dir
if (file_exists(BASE . GALLERY_DIR) && !file_exists(BASE . 'images/screenshots')) {
rename(BASE . GALLERY_DIR, BASE . 'images/screenshots');
}

// convert new database gallery images to screenshots
$query = $db->query('SELECT `id`, `image`, `thumb` FROM `' . TABLE_PREFIX . 'screenshots`;');
foreach ($query->fetchAll() as $item) {
$db->update(TABLE_PREFIX . 'screenshots', [
'image' => str_replace('/gallery/', '/screenshots/', $item['image']),
'thumb' => str_replace('/gallery/', '/screenshots/', $item['thumb']),
], ['id' => $item['id']]);
}
};
9 changes: 9 additions & 0 deletions system/migrations/12-items.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE `myaac_items`
(
`id` INT(11) NOT NULL,
`article` VARCHAR(5) NOT NULL DEFAULT '',
`name` VARCHAR(50) NOT NULL DEFAULT '',
`plural` VARCHAR(50) NOT NULL DEFAULT '',
`attributes` VARCHAR(500) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
8 changes: 8 additions & 0 deletions system/migrations/12-weapons.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE TABLE `myaac_weapons`
(
`id` INT(11) NOT NULL,
`level` INT(11) NOT NULL DEFAULT 0,
`maglevel` INT(11) NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
110 changes: 62 additions & 48 deletions system/migrations/12.php
Original file line number Diff line number Diff line change
@@ -1,51 +1,65 @@
<?php
/**
* @var OTS_DB_MySQL $db
*/

// add new item_id field for runes
if(!$db->hasColumn(TABLE_PREFIX . 'spells', 'item_id'))
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD `item_id` INT(11) NOT NULL DEFAULT 0 AFTER `conjure_count`;");

// change unique index from spell to name
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP INDEX `spell`;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD UNIQUE INDEX (`name`);");

// change comment of spells.type
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` MODIFY `type` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune';");

// new items table
if(!$db->hasTable(TABLE_PREFIX . 'items'))
$db->query("
CREATE TABLE `" . TABLE_PREFIX . "items`
(
`id` INT(11) NOT NULL,
`article` VARCHAR(5) NOT NULL DEFAULT '',
`name` VARCHAR(50) NOT NULL DEFAULT '',
`plural` VARCHAR(50) NOT NULL DEFAULT '',
`attributes` VARCHAR(500) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");

// new weapons table
if(!$db->hasTable(TABLE_PREFIX . 'weapons'))
$db->query("
CREATE TABLE `" . TABLE_PREFIX . "weapons`
(
`id` INT(11) NOT NULL,
`level` INT(11) NOT NULL DEFAULT 0,
`maglevel` INT(11) NOT NULL DEFAULT 0,
`vocations` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;
");

// modify vocations to support json data
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` MODIFY `vocations` VARCHAR(100) NOT NULL DEFAULT '';");
$query = $db->query('SELECT `id`, `vocations` FROM `' . TABLE_PREFIX . 'spells`');
foreach($query->fetchAll() as $spell) {
$tmp = explode(',', $spell['vocations']);
foreach($tmp as &$v) {
$v = (int)$v;
use MyAAC\Models\Spell;

$up = function () use ($db) {
// add new item_id field for runes
if (!$db->hasColumn(TABLE_PREFIX . 'spells', 'item_id')) {
$db->addColumn(TABLE_PREFIX . 'spells', 'item_id', 'INT(11) NOT NULL DEFAULT 0 AFTER `conjure_count`');
}

// change unique index from spell to name
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP INDEX `spell`;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD UNIQUE INDEX (`name`);");

// change comment of spells.type
$db->modifyColumn(TABLE_PREFIX . 'spells', 'type', "TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1 - instant, 2 - conjure, 3 - rune'");

// new items table
if (!$db->hasTable(TABLE_PREFIX . 'items')) {
$db->query(file_get_contents(__DIR__ . '/12-items.sql'));
}

// new weapons table
if (!$db->hasTable(TABLE_PREFIX . 'weapons')) {
$db->query(file_get_contents(__DIR__ . '/12-weapons.sql'));
}

// modify vocations to support json data
$db->modifyColumn(TABLE_PREFIX . 'spells', 'vocations', "VARCHAR(100) NOT NULL DEFAULT ''");

$spells = Spell::select('id', 'vocations')->get();
foreach ($spells as $spell) {
$tmp = explode(',', $spell->vocations);
foreach ($tmp as &$v) {
$v = (int)$v;
}

Spell::where('id', $spell->id)->update(['vocations' => json_encode($tmp)]);
}
};

$down = function () use ($db) {
// remove item_id field for runes
if ($db->hasColumn(TABLE_PREFIX . 'spells', 'item_id')) {
$db->dropColumn(TABLE_PREFIX . 'spells', 'item_id');
}

// change unique index from spell to name
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` DROP INDEX `name`;");
$db->query("ALTER TABLE `" . TABLE_PREFIX . "spells` ADD INDEX (`spell`);");

$db->dropTable(TABLE_PREFIX . 'items');
$db->dropTable(TABLE_PREFIX . 'weapons');

$spells = Spell::select('id', 'vocations')->get();
// modify vocations to use vocation separated by comma
foreach ($spells as $spell) {
$vocations = empty($spell->vocations) ? [] : json_decode($spell->vocations);

Spell::where('id', $spell->id)->update(['vocations' => implode(',', $vocations)]);
}
$db->update(TABLE_PREFIX . 'spells', array('vocations' => json_encode($tmp)), array('id' => $spell['id']));
}
?>
};
Loading
Loading