From 1949c197d64877e028affa5cd9d8c71b54694a8c Mon Sep 17 00:00:00 2001 From: slawkens Date: Tue, 9 Jan 2018 10:26:06 +0100 Subject: [PATCH] * installation of important stuff with help of AJAX * installation will be now done with AJAX request (jQuery), that will instaltly notify about the status of the installation (no waiting without clue anymore) * install items & weapons on installation (before monsters) --- TODO | 1 - images/loading_spinner.gif | Bin 0 -> 68488 bytes install/includes/config.php | 54 ++--- install/steps/1-welcome.php | 2 +- install/steps/5-database.php | 194 +---------------- install/steps/7-finish.php | 68 +----- install/template/template.php | 2 + install/tools/5-database.php | 208 +++++++++++++++++++ install/tools/7-finish.php | 92 ++++++++ install/tools/installer.js | 40 ++++ system/locale/de/install.php | 4 + system/locale/en/install.php | 4 + system/locale/pl/install.php | 4 + system/pages/admin/items.php | 1 - system/templates/install.installer.html.twig | 11 + 15 files changed, 401 insertions(+), 284 deletions(-) create mode 100644 images/loading_spinner.gif create mode 100644 install/tools/5-database.php create mode 100644 install/tools/7-finish.php create mode 100644 install/tools/installer.js create mode 100644 system/templates/install.installer.html.twig diff --git a/TODO b/TODO index 2ba0c32b..c2412624 100644 --- a/TODO +++ b/TODO @@ -3,7 +3,6 @@ 0.* * support duplicated vocation names with different ids * sandbox for plugins, don't install when requirements are not passed - * load items & weapons on install, preferably with ajax * add changelog management interface * plugins require: * php extension diff --git a/images/loading_spinner.gif b/images/loading_spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..b389312746bd77ab90129ff7c9c00b5f2d16a33b GIT binary patch literal 68488 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

`M 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 Cn|N~o literal 0 HcmV?d00001 diff --git a/install/includes/config.php b/install/includes/config.php index 67a73e03..ccb38f72 100644 --- a/install/includes/config.php +++ b/install/includes/config.php @@ -6,36 +6,36 @@ if(!isset($_SESSION['var_server_path'])) { $error = true; } - $config['server_path'] = $_SESSION['var_server_path']; - // take care of trailing slash at the end - if($config['server_path'][strlen($config['server_path']) - 1] != '/') - $config['server_path'] .= '/'; +$config['server_path'] = $_SESSION['var_server_path']; +// take care of trailing slash at the end +if($config['server_path'][strlen($config['server_path']) - 1] != '/') + $config['server_path'] .= '/'; if((!isset($error) || !$error) && !file_exists($config['server_path'] . 'config.lua')) { - error($locale['step_database_error_config']); + error($locale['step_database_error_config']); + $error = true; +} + +if(!isset($error) || !$error) { + $config['lua'] = load_config_lua($config['server_path'] . 'config.lua'); + if(isset($config['lua']['sqlType'])) // tfs 0.3 + $config['database_type'] = $config['lua']['sqlType']; + else if(isset($config['lua']['mysqlHost'])) // tfs 0.2/1.0 + $config['database_type'] = 'mysql'; + else if(isset($config['lua']['database_type'])) // otserv + $config['database_type'] = $config['lua']['database_type']; + else if(isset($config['lua']['sql_type'])) // otserv + $config['database_type'] = $config['lua']['sql_type']; + + $config['database_type'] = strtolower($config['database_type']); + if(empty($config['database_type'])) { + error($locale['step_database_error_database_empty']); $error = true; } - - if(!isset($error) || !$error) { - $config['lua'] = load_config_lua($config['server_path'] . 'config.lua'); - if(isset($config['lua']['sqlType'])) // tfs 0.3 - $config['database_type'] = $config['lua']['sqlType']; - else if(isset($config['lua']['mysqlHost'])) // tfs 0.2/1.0 - $config['database_type'] = 'mysql'; - else if(isset($config['lua']['database_type'])) // otserv - $config['database_type'] = $config['lua']['database_type']; - else if(isset($config['lua']['sql_type'])) // otserv - $config['database_type'] = $config['lua']['sql_type']; - - $config['database_type'] = strtolower($config['database_type']); - if(empty($config['database_type'])) { - error($locale['step_database_error_database_empty']); - $error = true; - } - else if($config['database_type'] != 'mysql') { - $locale['step_database_error_only_mysql'] = str_replace('$DATABASE_TYPE$', '' . $config['database_type'] . '', $locale['step_database_error_only_mysql']); - error($locale['step_database_error_only_mysql']); - $error = true; - } + else if($config['database_type'] != 'mysql') { + $locale['step_database_error_only_mysql'] = str_replace('$DATABASE_TYPE$', '' . $config['database_type'] . '', $locale['step_database_error_only_mysql']); + error($locale['step_database_error_only_mysql']); + $error = true; } +} ?> \ No newline at end of file diff --git a/install/steps/1-welcome.php b/install/steps/1-welcome.php index 54391e9e..8a38e8ce 100644 --- a/install/steps/1-welcome.php +++ b/install/steps/1-welcome.php @@ -1,6 +1,6 @@ ' . $locale['already_installed'] . '

'; } else { diff --git a/install/steps/5-database.php b/install/steps/5-database.php index 23494e14..479503b8 100644 --- a/install/steps/5-database.php +++ b/install/steps/5-database.php @@ -47,197 +47,11 @@ if(!$error) { success($locale['step_database_importing']); require(BASE . 'install/includes/database.php'); - if(!$db->hasTable('accounts')) { - $locale['step_database_error_table'] = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']); - error($locale['step_database_error_table']); - $error = true; - } - else if(!$db->hasTable('players')) { - $locale['step_database_error_table'] = str_replace('$TABLE$', 'players', $locale['step_database_error_table']); - error($locale['step_database_error_table']); - $error = true; - } - else if(!$db->hasTable('guilds')) { - $locale['step_database_error_table'] = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']); - error($locale['step_database_error_table']); - $error = true; - } + echo $twig->render('install.installer.html.twig', array( + 'url' => 'tools/5-database.php', + 'message' => $locale['loading_spinner'] + )); - if($db->hasTable(TABLE_PREFIX . 'account_actions')) { - $locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']); - warning($locale['step_database_error_table_exist']); - } - else if(!$error) { - // import schema - try { - $db->query(file_get_contents(BASE . 'install/includes/schema.sql')); - } - catch(PDOException $error_) { - error($locale['step_database_error_schema'] . ' ' . $error_); - $error = true; - } - - if(!$error) { - registerDatabaseConfig('database_version', DATABASE_VERSION); - $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); - success($locale['step_database_success_schema']); - } - } - - if(!$error) { - if($db->hasColumn('accounts', 'key')) { - if(query("ALTER TABLE `accounts` MODIFY `key` VARCHAR(64) NOT NULL DEFAULT '';")) - success($locale['step_database_modifying_field'] . ' accounts.key...'); - } - else { - if(query("ALTER TABLE `accounts` ADD `key` VARCHAR(64) NOT NULL DEFAULT '' AFTER `email`;")) - success($locale['step_database_adding_field'] . ' accounts.key...'); - } - - if(!$db->hasColumn('accounts', 'blocked')) { - if(query("ALTER TABLE `accounts` ADD `blocked` TINYINT(1) NOT NULL DEFAULT FALSE COMMENT 'internal usage' AFTER `key`;")) - success($locale['step_database_adding_field'] . ' accounts.blocked...'); - } - - if(!$db->hasColumn('accounts', 'created')) { - if(query("ALTER TABLE `accounts` ADD `created` INT(11) NOT NULL DEFAULT 0 AFTER `" . ($db->hasColumn('accounts', 'group_id') ? 'group_id' : 'blocked') . "`;")) - success($locale['step_database_adding_field'] . ' accounts.created...'); - } - - if(!$db->hasColumn('accounts', 'rlname')) { - if(query("ALTER TABLE `accounts` ADD `rlname` VARCHAR(255) NOT NULL DEFAULT '' AFTER `created`;")) - success($locale['step_database_adding_field'] . ' accounts.rlname...'); - } - - if(!$db->hasColumn('accounts', 'location')) { - if(query("ALTER TABLE `accounts` ADD `location` VARCHAR(255) NOT NULL DEFAULT '' AFTER `rlname`;")) - success($locale['step_database_adding_field'] . ' accounts.location...'); - } - - if(!$db->hasColumn('accounts', 'country')) { - if(query("ALTER TABLE `accounts` ADD `country` VARCHAR(3) NOT NULL DEFAULT '' AFTER `location`;")) - success($locale['step_database_adding_field'] . ' accounts.country...'); - } - - if($db->hasColumn('accounts', 'page_lastday')) { - if(query("ALTER TABLE `accounts` CHANGE `page_lastday` `web_lastlogin` INT(11) NOT NULL DEFAULT 0;")) { - $tmp = str_replace('$FIELD$', 'accounts.page_lastday', $locale['step_database_changing_field']); - $tmp = str_replace('$FIELD_NEW$', 'accounts.web_lastlogin', $tmp); - success($tmp); - } - } - else if(!$db->hasColumn('accounts', 'web_lastlogin')) { - if(query("ALTER TABLE `accounts` ADD `web_lastlogin` INT(11) NOT NULL DEFAULT 0 AFTER `country`;")) - success($locale['step_database_adding_field'] . ' accounts.web_lastlogin...'); - } - - if(!$db->hasColumn('accounts', 'web_flags')) { - if(query("ALTER TABLE `accounts` ADD `web_flags` INT(11) NOT NULL DEFAULT 0 AFTER `web_lastlogin`;")) - success($locale['step_database_adding_field'] . ' accounts.web_flags...'); - } - - if(!$db->hasColumn('accounts', 'email_hash')) { - if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;")) - success($locale['step_database_adding_field'] . ' accounts.email_hash...'); - } - - if(!$db->hasColumn('accounts', 'email_verified')) { - if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;")) - success($locale['step_database_adding_field'] . ' accounts.email_verified...'); - } - - if(!$db->hasColumn('accounts', 'email_new')) { - if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;")) - success($locale['step_database_adding_field'] . ' accounts.email_new...'); - } - - if(!$db->hasColumn('accounts', 'email_new_time')) { - if(query("ALTER TABLE `accounts` ADD `email_new_time` INT(11) NOT NULL DEFAULT 0 AFTER `email_new`;")) - success($locale['step_database_adding_field'] . ' accounts.email_new_time...'); - } - - if(!$db->hasColumn('accounts', 'email_code')) { - if(query("ALTER TABLE `accounts` ADD `email_code` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_new_time`;")) - success($locale['step_database_adding_field'] . ' accounts.email_code...'); - } - - if($db->hasColumn('accounts', 'next_email')) { - if(!$db->hasColumn('accounts', 'email_next')) { - if(query("ALTER TABLE `accounts` CHANGE `next_email` `email_next` INT(11) NOT NULL DEFAULT 0;")) { - $tmp = str_replace('$FIELD$', 'accounts.next_email', $locale['step_database_changing_field']); - $tmp = str_replace('$FIELD_NEW$', 'accounts.email_next', $tmp); - success($tmp); - } - } - } - else if(!$db->hasColumn('accounts', 'email_next')) { - if(query("ALTER TABLE `accounts` ADD `email_next` INT(11) NOT NULL DEFAULT 0 AFTER `email_code`;")) - success($locale['step_database_adding_field'] . ' accounts.email_next...'); - } - - if(!$db->hasColumn('accounts', 'premium_points')) { - if(query("ALTER TABLE `accounts` ADD `premium_points` INT(11) NOT NULL DEFAULT 0 AFTER `email_next`;")) - success($locale['step_database_adding_field'] . ' accounts.premium_points...'); - } - - if(!$db->hasColumn('guilds', 'description')) { - if(query("ALTER TABLE `guilds` ADD `description` TEXT NOT NULL;")) - success($locale['step_database_adding_field'] . ' guilds.description...'); - } - - if($db->hasColumn('guilds', 'logo_gfx_name')) { - if(query("ALTER TABLE `guilds` CHANGE `logo_gfx_name` `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) { - $tmp = str_replace('$FIELD$', 'guilds.logo_gfx_name', $locale['step_database_changing_field']); - $tmp = str_replace('$FIELD_NEW$', 'guilds.logo_name', $tmp); - success($tmp); - } - } - else if(!$db->hasColumn('guilds', 'logo_name')) { - if(query("ALTER TABLE `guilds` ADD `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) - success($locale['step_database_adding_field'] . ' guilds.logo_name...'); - } - - if(!$db->hasColumn('players', 'created')) { - if(query("ALTER TABLE `players` ADD `created` INT(11) NOT NULL DEFAULT 0;")) - success($locale['step_database_adding_field'] . ' players.created...'); - } - - if(!$db->hasColumn('players', 'deleted') && !$db->hasColumn('players', 'deletion')) { - if(query("ALTER TABLE `players` ADD `deleted` TINYINT(1) NOT NULL DEFAULT 0;")) - success($locale['step_database_adding_field'] . ' players.comment...'); - } - - if($db->hasColumn('players', 'hide_char')) { - if(!$db->hasColumn('players', 'hidden')) { - if(query("ALTER TABLE `players` CHANGE `hide_char` `hidden` TINYINT(1) NOT NULL DEFAULT 0;")) { - $tmp = str_replace('$FIELD$', 'players.hide_char', $locale['step_database_changing_field']); - $tmp = str_replace('$FIELD_NEW$', 'players.hidden', $tmp); - success($tmp); - } - } - } - else if(!$db->hasColumn('players', 'hidden')) { - if(query("ALTER TABLE `players` ADD `hidden` TINYINT(1) NOT NULL DEFAULT 0;")) - success($locale['step_database_adding_field'] . ' players.hidden...'); - } - - if(!$db->hasColumn('players', 'comment')) { - if(query("ALTER TABLE `players` ADD `comment` TEXT NOT NULL;")) - success($locale['step_database_adding_field'] . ' players.comment...'); - } - - if($db->hasColumn('players', 'rank_id')) { - if(query("ALTER TABLE players MODIFY `rank_id` INT(11) NOT NULL DEFAULT 0;")) - success($locale['step_database_modifying_field'] . ' players.rank_id...'); - - if($db->hasColumn('players', 'guildnick')) { - if(query("ALTER TABLE players MODIFY `guildnick` VARCHAR(255) NOT NULL DEFAULT '';")) { - success($locale['step_database_modifying_field'] . ' players.guildnick...'); - } - } - } - } - if(!$error) { if(!Validator::email($_SESSION['var_mail_admin'])) { error($locale['step_config_mail_admin_error']); diff --git a/install/steps/7-finish.php b/install/steps/7-finish.php index ac18cb19..30d30732 100644 --- a/install/steps/7-finish.php +++ b/install/steps/7-finish.php @@ -114,71 +114,11 @@ else { success($locale['step_database_created_news']); } } - - $deleted = 'deleted'; - if($db->hasColumn('players', 'deletion')) - $deleted = 'deletion'; - - $time = time(); - function insert_sample_if_not_exist($p) { - global $db, $success, $deleted, $time; - - $query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name'])); - if($query->rowCount() == 0) { - if(!query("INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `lastlogout`, `balance`, `$deleted`, `created`, `hidden`, `comment`) VALUES (null, " . $db->quote($p['name']) . ", 1, " . getSession('account') . ", " . $p['level'] . ", " . $p['vocation_id'] . ", " . $p['health'] . ", " . $p['healthmax'] . ", " . $p['experience'] . ", 118, 114, 38, 57, " . $p['looktype'] . ", 0, " . $p['mana'] . ", " . $p['manamax'] . ", 0, " . $p['soul'] . ", 1, 1000, 1000, 7, '', " . $p['cap'] . ", 1, " . $time . ", 2130706433, 1, " . $time . ", 0, 0, " . $time . ", 1, '');")) - $success = false; - } - } - - $success = true; - insert_sample_if_not_exist(array('name' => 'Rook Sample', 'level' => 1, 'vocation_id' => 0, 'health' => 150, 'healthmax' => 150, 'experience' => 0, 'looktype' => 130, 'mana' => 0, 'manamax' => 0, 'soul' => 100, 'cap' => 400)); - insert_sample_if_not_exist(array('name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); - insert_sample_if_not_exist(array('name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); - insert_sample_if_not_exist(array('name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); - insert_sample_if_not_exist(array('name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); - - if($success) { - success($locale['step_database_imported_players']); - } - require(LIBS . 'creatures.php'); - if(Creatures::loadFromXML()) { - success($locale['step_database_loaded_monsters']); - - if(Creatures::getMonstersList()->hasErrors()) { - $locale['step_database_error_monsters'] = str_replace('$LOG$', 'system/logs/error.log', $locale['step_database_error_monsters']); - warning($locale['step_database_error_monsters']); - } - } - else { - error(Creatures::getLastError()); - } - - require(LIBS . 'spells.php'); - if(Spells::loadFromXML()) { - success($locale['step_database_loaded_spells']); - } - else { - error(Spells::getLastError()); - } - - $query = $db->query("SELECT `id` FROM `players` WHERE (`name` = " . $db->quote("Rook Sample") . " OR `name` = " . $db->quote("Sorcerer Sample") . " OR `name` = " . $db->quote("Druid Sample") . " OR `name` = " . $db->quote("Paladin Sample") . " OR `name` = " . $db->quote("Knight Sample") . " OR `name` = " . $db->quote("Account Manager") . ") ORDER BY `id`;"); - - // update config.highscores_ids_hidden - require_once(SYSTEM . 'migrations/20.php'); - $database_migration_20 = true; - $content = ''; - if(!databaseMigration20($content)) { - $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.local.php', $locale['step_database_error_file']); - warning($locale['step_database_error_file'] . '
- '); - } - - $locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(ADMIN_URL, $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']); - $locale['step_finish_desc'] = str_replace('$HOMEPAGE$', generateLink(BASE_URL, $locale['step_finish_homepage'], true), $locale['step_finish_desc']); - $locale['step_finish_desc'] = str_replace('$LINK$', generateLink('http://my-aac.org', 'http://my-aac.org', true), $locale['step_finish_desc']); - - success($locale['step_finish_desc']); + echo $twig->render('install.installer.html.twig', array( + 'url' => 'tools/7-finish.php', + 'message' => $locale['importing_spinner'] + )); if(!isset($_SESSION['installed'])) { file_get_contents('http://my-aac.org/report_install.php?v=' . MYAAC_VERSION . '&b=' . urlencode(BASE_URL)); diff --git a/install/template/template.php b/install/template/template.php index e5422831..5ea685c7 100644 --- a/install/template/template.php +++ b/install/template/template.php @@ -3,6 +3,8 @@ MyAAC - <?php echo $locale['installation']; ?> + +
diff --git a/install/tools/5-database.php b/install/tools/5-database.php new file mode 100644 index 00000000..251f5331 --- /dev/null +++ b/install/tools/5-database.php @@ -0,0 +1,208 @@ +hasTable('accounts')) { + $locale['step_database_error_table'] = str_replace('$TABLE$', 'accounts', $locale['step_database_error_table']); + error($locale['step_database_error_table']); + $error = true; +} +else if(!$db->hasTable('players')) { + $locale['step_database_error_table'] = str_replace('$TABLE$', 'players', $locale['step_database_error_table']); + error($locale['step_database_error_table']); + $error = true; +} +else if(!$db->hasTable('guilds')) { + $locale['step_database_error_table'] = str_replace('$TABLE$', 'guilds', $locale['step_database_error_table']); + error($locale['step_database_error_table']); + $error = true; +} + +if($db->hasTable(TABLE_PREFIX . 'account_actions')) { + $locale['step_database_error_table_exist'] = str_replace('$TABLE$', TABLE_PREFIX . 'account_actions', $locale['step_database_error_table_exist']); + warning($locale['step_database_error_table_exist']); +} +else if(!$error) { + // import schema + try { + $db->query(file_get_contents(BASE . 'install/includes/schema.sql')); + + registerDatabaseConfig('database_version', DATABASE_VERSION); + $locale['step_database_success_schema'] = str_replace('$PREFIX$', TABLE_PREFIX, $locale['step_database_success_schema']); + success($locale['step_database_success_schema']); + } + catch(PDOException $error_) { + error($locale['step_database_error_schema'] . ' ' . $error_); + $error = true; + } +} + +if($error) { + return; +} + +if($db->hasColumn('accounts', 'key')) { + if(query("ALTER TABLE `accounts` MODIFY `key` VARCHAR(64) NOT NULL DEFAULT '';")) + success($locale['step_database_modifying_field'] . ' accounts.key...'); +} +else { + if(query("ALTER TABLE `accounts` ADD `key` VARCHAR(64) NOT NULL DEFAULT '' AFTER `email`;")) + success($locale['step_database_adding_field'] . ' accounts.key...'); +} + +if(!$db->hasColumn('accounts', 'blocked')) { + if(query("ALTER TABLE `accounts` ADD `blocked` TINYINT(1) NOT NULL DEFAULT FALSE COMMENT 'internal usage' AFTER `key`;")) + success($locale['step_database_adding_field'] . ' accounts.blocked...'); +} + +if(!$db->hasColumn('accounts', 'created')) { + if(query("ALTER TABLE `accounts` ADD `created` INT(11) NOT NULL DEFAULT 0 AFTER `" . ($db->hasColumn('accounts', 'group_id') ? 'group_id' : 'blocked') . "`;")) + success($locale['step_database_adding_field'] . ' accounts.created...'); +} + +if(!$db->hasColumn('accounts', 'rlname')) { + if(query("ALTER TABLE `accounts` ADD `rlname` VARCHAR(255) NOT NULL DEFAULT '' AFTER `created`;")) + success($locale['step_database_adding_field'] . ' accounts.rlname...'); +} + +if(!$db->hasColumn('accounts', 'location')) { + if(query("ALTER TABLE `accounts` ADD `location` VARCHAR(255) NOT NULL DEFAULT '' AFTER `rlname`;")) + success($locale['step_database_adding_field'] . ' accounts.location...'); +} + +if(!$db->hasColumn('accounts', 'country')) { + if(query("ALTER TABLE `accounts` ADD `country` VARCHAR(3) NOT NULL DEFAULT '' AFTER `location`;")) + success($locale['step_database_adding_field'] . ' accounts.country...'); +} + +if($db->hasColumn('accounts', 'page_lastday')) { + if(query("ALTER TABLE `accounts` CHANGE `page_lastday` `web_lastlogin` INT(11) NOT NULL DEFAULT 0;")) { + $tmp = str_replace('$FIELD$', 'accounts.page_lastday', $locale['step_database_changing_field']); + $tmp = str_replace('$FIELD_NEW$', 'accounts.web_lastlogin', $tmp); + success($tmp); + } +} +else if(!$db->hasColumn('accounts', 'web_lastlogin')) { + if(query("ALTER TABLE `accounts` ADD `web_lastlogin` INT(11) NOT NULL DEFAULT 0 AFTER `country`;")) + success($locale['step_database_adding_field'] . ' accounts.web_lastlogin...'); +} + +if(!$db->hasColumn('accounts', 'web_flags')) { + if(query("ALTER TABLE `accounts` ADD `web_flags` INT(11) NOT NULL DEFAULT 0 AFTER `web_lastlogin`;")) + success($locale['step_database_adding_field'] . ' accounts.web_flags...'); +} + +if(!$db->hasColumn('accounts', 'email_hash')) { + if(query("ALTER TABLE `accounts` ADD `email_hash` VARCHAR(32) NOT NULL DEFAULT '' AFTER `web_flags`;")) + success($locale['step_database_adding_field'] . ' accounts.email_hash...'); +} + +if(!$db->hasColumn('accounts', 'email_verified')) { + if(query("ALTER TABLE `accounts` ADD `email_verified` TINYINT(1) NOT NULL DEFAULT 0 AFTER `email_hash`;")) + success($locale['step_database_adding_field'] . ' accounts.email_verified...'); +} + +if(!$db->hasColumn('accounts', 'email_new')) { + if(query("ALTER TABLE `accounts` ADD `email_new` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_hash`;")) + success($locale['step_database_adding_field'] . ' accounts.email_new...'); +} + +if(!$db->hasColumn('accounts', 'email_new_time')) { + if(query("ALTER TABLE `accounts` ADD `email_new_time` INT(11) NOT NULL DEFAULT 0 AFTER `email_new`;")) + success($locale['step_database_adding_field'] . ' accounts.email_new_time...'); +} + +if(!$db->hasColumn('accounts', 'email_code')) { + if(query("ALTER TABLE `accounts` ADD `email_code` VARCHAR(255) NOT NULL DEFAULT '' AFTER `email_new_time`;")) + success($locale['step_database_adding_field'] . ' accounts.email_code...'); +} + +if($db->hasColumn('accounts', 'next_email')) { + if(!$db->hasColumn('accounts', 'email_next')) { + if(query("ALTER TABLE `accounts` CHANGE `next_email` `email_next` INT(11) NOT NULL DEFAULT 0;")) { + $tmp = str_replace('$FIELD$', 'accounts.next_email', $locale['step_database_changing_field']); + $tmp = str_replace('$FIELD_NEW$', 'accounts.email_next', $tmp); + success($tmp); + } + } +} +else if(!$db->hasColumn('accounts', 'email_next')) { + if(query("ALTER TABLE `accounts` ADD `email_next` INT(11) NOT NULL DEFAULT 0 AFTER `email_code`;")) + success($locale['step_database_adding_field'] . ' accounts.email_next...'); +} + +if(!$db->hasColumn('accounts', 'premium_points')) { + if(query("ALTER TABLE `accounts` ADD `premium_points` INT(11) NOT NULL DEFAULT 0 AFTER `email_next`;")) + success($locale['step_database_adding_field'] . ' accounts.premium_points...'); +} + +if(!$db->hasColumn('guilds', 'description')) { + if(query("ALTER TABLE `guilds` ADD `description` TEXT NOT NULL;")) + success($locale['step_database_adding_field'] . ' guilds.description...'); +} + +if($db->hasColumn('guilds', 'logo_gfx_name')) { + if(query("ALTER TABLE `guilds` CHANGE `logo_gfx_name` `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) { + $tmp = str_replace('$FIELD$', 'guilds.logo_gfx_name', $locale['step_database_changing_field']); + $tmp = str_replace('$FIELD_NEW$', 'guilds.logo_name', $tmp); + success($tmp); + } +} +else if(!$db->hasColumn('guilds', 'logo_name')) { + if(query("ALTER TABLE `guilds` ADD `logo_name` VARCHAR( 255 ) NOT NULL DEFAULT 'default.gif';")) + success($locale['step_database_adding_field'] . ' guilds.logo_name...'); +} + +if(!$db->hasColumn('players', 'created')) { + if(query("ALTER TABLE `players` ADD `created` INT(11) NOT NULL DEFAULT 0;")) + success($locale['step_database_adding_field'] . ' players.created...'); +} + +if(!$db->hasColumn('players', 'deleted') && !$db->hasColumn('players', 'deletion')) { + if(query("ALTER TABLE `players` ADD `deleted` TINYINT(1) NOT NULL DEFAULT 0;")) + success($locale['step_database_adding_field'] . ' players.comment...'); +} + +if($db->hasColumn('players', 'hide_char')) { + if(!$db->hasColumn('players', 'hidden')) { + if(query("ALTER TABLE `players` CHANGE `hide_char` `hidden` TINYINT(1) NOT NULL DEFAULT 0;")) { + $tmp = str_replace('$FIELD$', 'players.hide_char', $locale['step_database_changing_field']); + $tmp = str_replace('$FIELD_NEW$', 'players.hidden', $tmp); + success($tmp); + } + } +} +else if(!$db->hasColumn('players', 'hidden')) { + if(query("ALTER TABLE `players` ADD `hidden` TINYINT(1) NOT NULL DEFAULT 0;")) + success($locale['step_database_adding_field'] . ' players.hidden...'); +} + +if(!$db->hasColumn('players', 'comment')) { + if(query("ALTER TABLE `players` ADD `comment` TEXT NOT NULL;")) + success($locale['step_database_adding_field'] . ' players.comment...'); +} + +if($db->hasColumn('players', 'rank_id')) { + if(query("ALTER TABLE players MODIFY `rank_id` INT(11) NOT NULL DEFAULT 0;")) + success($locale['step_database_modifying_field'] . ' players.rank_id...'); + + if($db->hasColumn('players', 'guildnick')) { + if(query("ALTER TABLE players MODIFY `guildnick` VARCHAR(255) NOT NULL DEFAULT '';")) { + success($locale['step_database_modifying_field'] . ' players.guildnick...'); + } + } +} diff --git a/install/tools/7-finish.php b/install/tools/7-finish.php new file mode 100644 index 00000000..a4145351 --- /dev/null +++ b/install/tools/7-finish.php @@ -0,0 +1,92 @@ +hasColumn('players', 'deletion')) + $deleted = 'deletion'; + +$time = time(); +function insert_sample_if_not_exist($p) { + global $db, $success, $deleted, $time; + + $query = $db->query('SELECT `id` FROM `players` WHERE `name` = ' . $db->quote($p['name'])); + if($query->rowCount() == 0) { + if(!query("INSERT INTO `players` (`id`, `name`, `group_id`, `account_id`, `level`, `vocation`, `health`, `healthmax`, `experience`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `maglevel`, `mana`, `manamax`, `manaspent`, `soul`, `town_id`, `posx`, `posy`, `posz`, `conditions`, `cap`, `sex`, `lastlogin`, `lastip`, `save`, `lastlogout`, `balance`, `$deleted`, `created`, `hidden`, `comment`) VALUES (null, " . $db->quote($p['name']) . ", 1, " . getSession('account') . ", " . $p['level'] . ", " . $p['vocation_id'] . ", " . $p['health'] . ", " . $p['healthmax'] . ", " . $p['experience'] . ", 118, 114, 38, 57, " . $p['looktype'] . ", 0, " . $p['mana'] . ", " . $p['manamax'] . ", 0, " . $p['soul'] . ", 1, 1000, 1000, 7, '', " . $p['cap'] . ", 1, " . $time . ", 2130706433, 1, " . $time . ", 0, 0, " . $time . ", 1, '');")) + $success = false; + } +} + +$success = true; +insert_sample_if_not_exist(array('name' => 'Rook Sample', 'level' => 1, 'vocation_id' => 0, 'health' => 150, 'healthmax' => 150, 'experience' => 0, 'looktype' => 130, 'mana' => 0, 'manamax' => 0, 'soul' => 100, 'cap' => 400)); +insert_sample_if_not_exist(array('name' => 'Sorcerer Sample', 'level' => 8, 'vocation_id' => 1, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); +insert_sample_if_not_exist(array('name' => 'Druid Sample', 'level' => 8, 'vocation_id' => 2, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 130, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); +insert_sample_if_not_exist(array('name' => 'Paladin Sample', 'level' => 8, 'vocation_id' => 3, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 129, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); +insert_sample_if_not_exist(array('name' => 'Knight Sample', 'level' => 8, 'vocation_id' => 4, 'health' => 185, 'healthmax' => 185, 'experience' => 4200, 'looktype' => 131, 'mana' => 35, 'manamax' => 35, 'soul' => 100, 'cap' => 470)); + +if($success) { + success($locale['step_database_imported_players']); +} + +require(LIBS . 'items.php'); +if(Items::loadFromXML()) + success($locale['step_database_loaded_items']); +else + error(Items::getError()); + +require(LIBS . 'weapons.php'); +if(Weapons::loadFromXML()) + success($locale['step_database_loaded_weapons']); +else + error(Weapons::getError()); + +require(LIBS . 'creatures.php'); +if(Creatures::loadFromXML()) { + success($locale['step_database_loaded_monsters']); + + if(Creatures::getMonstersList()->hasErrors()) { + $locale['step_database_error_monsters'] = str_replace('$LOG$', 'system/logs/error.log', $locale['step_database_error_monsters']); + warning($locale['step_database_error_monsters']); + } +} +else { + error(Creatures::getLastError()); +} + +require(LIBS . 'spells.php'); +if(Spells::loadFromXML()) { + success($locale['step_database_loaded_spells']); +} +else { + error(Spells::getLastError()); +} + +// update config.highscores_ids_hidden +require_once(SYSTEM . 'migrations/20.php'); +$database_migration_20 = true; +$content = ''; +if(!databaseMigration20($content)) { + $locale['step_database_error_file'] = str_replace('$FILE$', '' . BASE . 'config.local.php', $locale['step_database_error_file']); + warning($locale['step_database_error_file'] . '
+ '); +} + +$locale['step_finish_desc'] = str_replace('$ADMIN_PANEL$', generateLink(str_replace('tools/', '',ADMIN_URL), $locale['step_finish_admin_panel'], true), $locale['step_finish_desc']); +$locale['step_finish_desc'] = str_replace('$HOMEPAGE$', generateLink(str_replace('tools/', '', BASE_URL), $locale['step_finish_homepage'], true), $locale['step_finish_desc']); +$locale['step_finish_desc'] = str_replace('$LINK$', generateLink('http://my-aac.org', 'http://my-aac.org', true), $locale['step_finish_desc']); + +success($locale['step_finish_desc']); \ No newline at end of file diff --git a/install/tools/installer.js b/install/tools/installer.js new file mode 100644 index 00000000..9f7492ba --- /dev/null +++ b/install/tools/installer.js @@ -0,0 +1,40 @@ +function performInstall(url) { + var lastResponseLength = false; + var lastId = 1; + + var ajaxRequest = $.ajax({ + type: 'get', + url: url, + data: {}, + dataType: 'html', + processData: false, + xhrFields: { + // Getting on progress streaming response + onprogress: function (e) { + var progressResponse; + var response = e.currentTarget.response; + progressResponse = response; + if (lastResponseLength === false) { + progressResponse = response; + lastResponseLength = response.length; + } + else { + progressResponse = response.substring(lastResponseLength); + lastResponseLength = response.length; + } + + $('
' + progressResponse + '
').insertAfter("#success-" + lastId); + lastId = lastId + 1; + } + } + }); + // On completed + ajaxRequest.done(function(data) { + $('#spinner').hide(); + }); + // On failed + ajaxRequest.fail(function(error){ + console.log('Error: ', error); + $('Error while doing AJAX request. Please refresh the page.').insertAfter("#success-" + lastId); + }); +} \ No newline at end of file diff --git a/system/locale/de/install.php b/system/locale/de/install.php index 98e0fa8e..0f971681 100644 --- a/system/locale/de/install.php +++ b/system/locale/de/install.php @@ -17,6 +17,8 @@ $locale['off'] = 'Aus'; $locale['loaded'] = 'Geladen'; $locale['not_loaded'] = 'Nicht geladen'; +$locale['loading_spinner'] = 'Bitte warten, installieren...'; +$locale['importing_spinner'] = 'Bitte warte, Daten werden importiert...'; $locale['please_fill_all'] = 'Bitte füllen Sie alle Felder aus!'; $locale['already_installed'] = 'MyAAC wurde bereits installiert. Bitte löschen install/ Verzeichnis.'; @@ -75,6 +77,8 @@ $locale['step_database_adding_field'] = 'Folgendes Feld wurde hinzugefügt: '; $locale['step_database_modifying_field'] = 'Folgendes Feld wurde geändert: '; $locale['step_database_changing_field'] = 'Änderung von $FIELD$ zu $FIELD_NEW$...'; $locale['step_database_imported_players'] = 'Spielerproben wurden importiert...'; +$locale['step_database_loaded_items'] = 'Items wurden geladen...'; +$locale['step_database_loaded_weapons'] = 'Weapons wurden geladen...'; $locale['step_database_loaded_monsters'] = 'Monster wurden geladen...'; $locale['step_database_error_monsters'] = 'Beim Laden der Datei monsters.xml sind einige Probleme aufgetreten. Bitte überprüfen Sie $LOG$ für weitere Informationen.'; $locale['step_database_loaded_spells'] = 'Zauber wurden geladen...'; diff --git a/system/locale/en/install.php b/system/locale/en/install.php index c365c58e..60279315 100644 --- a/system/locale/en/install.php +++ b/system/locale/en/install.php @@ -17,6 +17,8 @@ $locale['off'] = 'Off'; $locale['loaded'] = 'Loaded'; $locale['not_loaded'] = 'Not loaded'; +$locale['loading_spinner'] = 'Please wait, installing...'; +$locale['importing_spinner'] = 'Please wait, importing data...'; $locale['please_fill_all'] = 'Please fill all inputs!'; $locale['already_installed'] = 'MyAAC has been already installed. Please delete install/ directory.'; @@ -75,6 +77,8 @@ $locale['step_database_adding_field'] = 'Adding field'; $locale['step_database_modifying_field'] = 'Modifying field'; $locale['step_database_changing_field'] = 'Changing $FIELD$ to $FIELD_NEW$...'; $locale['step_database_imported_players'] = 'Player samples has been imported...'; +$locale['step_database_loaded_items'] = 'Items has been loaded...'; +$locale['step_database_loaded_weapons'] = 'Weapons has been loaded...'; $locale['step_database_loaded_monsters'] = 'Monsters has been loaded...'; $locale['step_database_error_monsters'] = 'There were some problems loading your monsters.xml file. Please check $LOG$ for more info.'; $locale['step_database_loaded_spells'] = 'Spells has been loaded...'; diff --git a/system/locale/pl/install.php b/system/locale/pl/install.php index c76fd526..1e179860 100644 --- a/system/locale/pl/install.php +++ b/system/locale/pl/install.php @@ -17,6 +17,8 @@ $locale['off'] = 'Wyłączone'; $locale['loaded'] = 'Załadowane'; $locale['not_loaded'] = 'Nie załadowane'; +$locale['loading_spinner'] = 'Proszę czekać, trwa instalacja...'; +$locale['importing_spinner'] = 'Proszę czekać, trwa importowanie danych...'; $locale['please_fill_all'] = 'Proszę wypełnić wszystkie pola!'; $locale['already_installed'] = 'MyAAC został już zainstalowany. Proszę usunąć katalog install/.'; @@ -70,6 +72,8 @@ $locale['step_database_adding_field'] = 'Dodawanie pola'; $locale['step_database_modifying_field'] = 'Modyfikacja pola'; $locale['step_database_changing_field'] = 'Zmiana $FIELD$ na $FIELD_NEW$...'; $locale['step_database_imported_players'] = 'Importowanie schematów graczy...'; +$locale['step_database_loaded_items'] = 'Załadowano przedmioty (items)...'; +$locale['step_database_loaded_weapons'] = 'Załadowano bronie (weapons)...'; $locale['step_database_loaded_monsters'] = 'Załadowano potworki (monsters)...'; $locale['step_database_error_monsters'] = 'Wystąpiły problemy podczas ładowania pliku monsters.xml. Zobacz $LOG$ po więcej informacji.'; $locale['step_database_loaded_spells'] = 'Załadowano czary (spells)...'; diff --git a/system/pages/admin/items.php b/system/pages/admin/items.php index 24033a6f..1d0d8269 100644 --- a/system/pages/admin/items.php +++ b/system/pages/admin/items.php @@ -26,5 +26,4 @@ if($reload) { success('Successfully loaded weapons.'); else error(Weapons::getError()); - } \ No newline at end of file diff --git a/system/templates/install.installer.html.twig b/system/templates/install.installer.html.twig new file mode 100644 index 00000000..d0694034 --- /dev/null +++ b/system/templates/install.installer.html.twig @@ -0,0 +1,11 @@ +
+
+ + {{ message }} +
+ + \ No newline at end of file