diff --git a/includes/database.class.php b/includes/database.class.php index d1cad02d..2182f785 100644 --- a/includes/database.class.php +++ b/includes/database.class.php @@ -49,6 +49,23 @@ class DB self::$connectionCache[$idx] = true; } + public static function test(array $options, ?string &$err = '') : bool + { + $defPort = ini_get('mysqli.default_port'); + $port = 0; + if (strstr($options['host'], ':')) + [$options['host'], $port] = explode(':', $options['host']); + + if ($link = @mysqli_connect($options['host'], $options['user'], $options['pass'], $options['db'], $port ?: $defPort)) + { + mysqli_close($link); + return true; + } + + $err = '['.mysqli_connect_errno().'] '.mysqli_connect_error(); + return false; + } + public static function errorHandler($message, $data) { if (!error_reporting()) diff --git a/setup/setup.php b/setup/setup.php index b07b722e..23ab2437 100644 --- a/setup/setup.php +++ b/setup/setup.php @@ -12,65 +12,44 @@ require_once 'setup/tools/setupScript.class.php'; require_once 'setup/tools/dbc.class.php'; require_once 'setup/tools/imagecreatefromblp.func.php'; - -function finish(bool $unlock = true) : void +function finish() : void { if (CLISetup::getOpt('delete')) // generated with TEMPORARY keyword. Manual deletion is not needed CLI::write('generated dbc_* - tables have been deleted.', CLI::LOG_INFO); - if ($unlock) - lockSite(false); - die("\n"); } -function lockSite(bool $enable = true) : void -{ - if (DB::isConnectable(DB_AOWOW)) - DB::Aowow()->query('UPDATE ?_config SET `value` = ?d WHERE `key` = "maintenance"', $enable ? 1 : 0); -} - CLISetup::init(); if (!CLISetup::getOpt(0x3)) die(CLISetup::optHelp(0x7)); -$cmd = CLISetup::getOpt(0x3)[0]; // get arguments present in argGroup 1 or 2, if set. Pick first. -$unlock = false; -$s = []; -$b = []; +$cmd = CLISetup::getOpt(0x3)[0]; // get arguments present in argGroup 1 or 2, if set. Pick first. +$s = []; +$b = []; switch ($cmd) // we accept only one main parameter { case 'setup': - lockSite(true); - require_once 'setup/tools/clisetup/firstrun.func.php'; - $success = firstrun(); - - finish($success); case 'sql': case 'build': - lockSite(true); - $unlock = true; case 'account': case 'dbconfig': case 'siteconfig': require_once 'setup/tools/clisetup/'.$cmd.'.func.php'; $cmd(); - - finish($unlock); + finish(); case 'update': - lockSite(true); require_once 'setup/tools/clisetup/update.func.php'; - [$s, $b] = update(); // return true if we do not rebuild stuff + update($s, $b); // return true if we do not rebuild stuff if (!$s && !$b) - finish(true); + finish(); case 'sync': - lockSite(true); require_once 'setup/tools/clisetup/sync.func.php'; sync($s, $b); - finish(true); + finish(); case 'dbc': foreach (CLISetup::getOpt('dbc') as $n) { diff --git a/setup/tools/CLISetup.class.php b/setup/tools/CLISetup.class.php index de5fd100..7406c386 100644 --- a/setup/tools/CLISetup.class.php +++ b/setup/tools/CLISetup.class.php @@ -24,6 +24,12 @@ class CLISetup 'ruRU' => LOCALE_RU ); + public const LOCK_OFF = 0; + public const LOCK_ON = 1; + public const LOCK_RESTORE = 2; + + private static $lock = 1; + private const ARGV_REQUIRED = 0x01; private const ARGV_OPTIONAL = 0x02; private const ARGV_ARRAY = 0x10; @@ -123,6 +129,12 @@ class CLISetup foreach (self::$locales as $idx => $str) if (!defined('CFG_LOCALES') || CFG_LOCALES & (1 << $idx)) self::$localeIds[] = $idx; + + // get site status + if (DB::isConnectable(DB_AOWOW)) + self::$lock = (int)DB::Aowow()->selectCell('SELECT `value` FROM ?_config WHERE `key` = "maintenance"'); + else + self::$lock = self::LOCK_ON; } public static function getOpt(...$args) @@ -182,6 +194,17 @@ class CLISetup } + /*******************/ + /* web page access */ + /*******************/ + + public static function siteLock(int $mode = self::LOCK_RESTORE) : void + { + if (DB::isConnectable(DB_AOWOW)) + DB::Aowow()->query('UPDATE ?_config SET `value` = ?d WHERE `key` = "maintenance"', (int)!!($mode == self::LOCK_RESTORE ? self::$lock : $mode)); + } + + /*******************/ /* MPQ-file access */ /*******************/ diff --git a/setup/tools/clisetup/account.func.php b/setup/tools/clisetup/account.func.php index 44eff9d5..a6637ecc 100644 --- a/setup/tools/clisetup/account.func.php +++ b/setup/tools/clisetup/account.func.php @@ -11,7 +11,7 @@ if (!CLI) /* Account creation */ /********************/ -function account() +function account() : void { $fields = array( 'name' => ['Username', false], diff --git a/setup/tools/clisetup/build.func.php b/setup/tools/clisetup/build.func.php index c3c0ed92..87297309 100644 --- a/setup/tools/clisetup/build.func.php +++ b/setup/tools/clisetup/build.func.php @@ -11,15 +11,17 @@ if (!CLI) /* Create required files */ /*************************/ -function build($syncMe = null) +function build($syncMe = null) : array { require_once 'setup/tools/fileGen.class.php'; - FileGen::init($syncMe !== null ? FileGen::MODE_UPDATE : FileGen::MODE_NORMAL, $syncMe ?: []); + if(!FileGen::init($syncMe !== null ? FileGen::MODE_UPDATE : FileGen::MODE_NORMAL, $syncMe ?: [])) + return []; $done = []; if (FileGen::$subScripts) { + CLISetup::siteLock(CLISetup::LOCK_ON); $allOk = true; // start file generation @@ -80,6 +82,8 @@ function build($syncMe = null) CLI::write('successfully finished file generation', CLI::LOG_OK); else CLI::write('finished file generation with errors', CLI::LOG_ERROR); + + CLISetup::siteLock(CLISetup::LOCK_RESTORE); } else if (FileGen::getMode() == FileGen::MODE_NORMAL) CLI::write('no valid script names supplied', CLI::LOG_ERROR); diff --git a/setup/tools/clisetup/dbconfig.func.php b/setup/tools/clisetup/dbconfig.func.php index 4854834c..99218012 100644 --- a/setup/tools/clisetup/dbconfig.func.php +++ b/setup/tools/clisetup/dbconfig.func.php @@ -11,7 +11,7 @@ if (!CLI) /* Configure DB connection*/ /**************************/ -function dbconfig() +function dbconfig() : void { $databases = ['aowow', 'world', 'auth', 'characters']; $AoWoWconf = []; @@ -24,21 +24,11 @@ function dbconfig() ); $testDB = function($idx, $name, $dbInfo) { - $buff = '['.CLI::bold($idx).'] '.str_pad($name, 17); - $errStr = ''; - $defPort = ini_get('mysqli.default_port'); - $port = 0; - - if (strstr($dbInfo['host'], ':')) - [$dbInfo['host'], $port] = explode(':', $dbInfo['host']); + $buff = '['.CLI::bold($idx).'] '.str_pad($name, 17); if ($dbInfo['host']) { - // test DB - if ($link = @mysqli_connect($dbInfo['host'], $dbInfo['user'], $dbInfo['pass'], $dbInfo['db'], $port ?: $defPort)) - mysqli_close($link); - else - $errStr = '['.mysqli_connect_errno().'] '.mysqli_connect_error(); + DB::test($dbInfo, $errStr); $buff .= $errStr ? CLI::red('ERR ') : CLI::green('OK '); $buff .= 'mysqli://'.$dbInfo['user'].':'.str_pad('', mb_strlen($dbInfo['pass']), '*').'@'.$dbInfo['host'].($port ? ':'.$port : null).'/'.$dbInfo['db']; @@ -54,10 +44,8 @@ function dbconfig() require 'config/config.php'; foreach ($databases as $idx => $name) - { if (empty($AoWoWconf[$name]) && $name != 'characters' ) $AoWoWconf[$name] = array_combine(array_keys($dbFields), ['', '', '', '', '']); - } while (true) { diff --git a/setup/tools/clisetup/firstrun.func.php b/setup/tools/clisetup/setup.func.php similarity index 94% rename from setup/tools/clisetup/firstrun.func.php rename to setup/tools/clisetup/setup.func.php index 07959d02..ad6dcb8b 100644 --- a/setup/tools/clisetup/firstrun.func.php +++ b/setup/tools/clisetup/setup.func.php @@ -11,7 +11,7 @@ if (!CLI) /* string setup steps together for first use */ /*********************************************/ -function firstrun() : bool +function setup() : void { require_once 'setup/tools/sqlGen.class.php'; require_once 'setup/tools/fileGen.class.php'; @@ -118,26 +118,16 @@ function firstrun() : bool require 'config/config.php'; $error = []; - $defPort = ini_get('mysqli.default_port'); - - foreach (['aowow', 'world', 'auth'] as $idx => $what) + foreach (['world', 'aowow', 'auth'] as $idx => $what) { if ($what == 'auth' && (empty($AoWoWconf['auth']) || empty($AoWoWconf['auth']['host']))) continue; - $port = 0; - if (strstr($AoWoWconf[$what]['host'], ':')) - [$AoWoWconf[$what]['host'], $port] = explode(':', $AoWoWconf[$what]['host']); - - if ($link = @mysqli_connect($AoWoWconf[$what]['host'], $AoWoWconf[$what]['user'], $AoWoWconf[$what]['pass'], $AoWoWconf[$what]['db'], $port ?: $defPort)) - { - mysqli_close($link); - - // init proper access for further setup + // init proper access for further setup + if (DB::test($AoWoWconf[$what], $err)) DB::load($idx, $AoWoWconf[$what]); - } else - $error[] = ' * '.$what.': '.'['.mysqli_connect_errno().'] '.mysqli_connect_error(); + $error[] = ' * '.$what.': '.$err; } return empty($error); @@ -247,7 +237,7 @@ function firstrun() : bool } CLI::write(); - exit; + return; } if ($startStep) @@ -274,6 +264,8 @@ function firstrun() : bool /* run */ /*******/ + CLISetup::siteLock(CLISetup::LOCK_ON); + foreach ($steps as $idx => $step) { if ($startStep > $idx) @@ -288,7 +280,7 @@ function firstrun() : bool $inp = ['x' => ['Press any key to continue', true]]; if (!CLI::read($inp, true)) // we don't actually care about the input - return false; + return; } while (true) @@ -329,20 +321,21 @@ function firstrun() : bool case 'r': break; case 'a': - return false; + return; } } else { CLI::write(); - return false; + return; } } } unlink('cache/firstrun'); + CLISetup::siteLock(CLISetup::LOCK_OFF); CLI::write('setup finished', CLI::LOG_OK); - return true; + return; } ?> diff --git a/setup/tools/clisetup/siteconfig.func.php b/setup/tools/clisetup/siteconfig.func.php index 575729d7..803dbe74 100644 --- a/setup/tools/clisetup/siteconfig.func.php +++ b/setup/tools/clisetup/siteconfig.func.php @@ -11,7 +11,7 @@ if (!CLI) /* Configure Site variables */ /****************************/ -function siteconfig() +function siteconfig() : void { $reqKeys = ['site_host', 'static_host']; $updScripts = []; diff --git a/setup/tools/clisetup/sql.func.php b/setup/tools/clisetup/sql.func.php index 362c0a97..052f6c7c 100644 --- a/setup/tools/clisetup/sql.func.php +++ b/setup/tools/clisetup/sql.func.php @@ -11,15 +11,17 @@ if (!CLI) /* Create content from world tables / dbc files */ /************************************************/ -function sql($syncMe = null) +function sql($syncMe = null) : array { require_once 'setup/tools/sqlGen.class.php'; - SqlGen::init($syncMe !== null ? SqlGen::MODE_UPDATE : SqlGen::MODE_NORMAL, $syncMe ?: []); + if (!SqlGen::init($syncMe !== null ? SqlGen::MODE_UPDATE : SqlGen::MODE_NORMAL, $syncMe ?: [])) + return []; $done = []; if (SqlGen::$subScripts) { + CLISetup::siteLock(CLISetup::LOCK_ON); $allOk = true; // start file generation @@ -46,6 +48,8 @@ function sql($syncMe = null) CLI::write('successfully finished sql generation', CLI::LOG_OK); else CLI::write('finished sql generation with errors', CLI::LOG_ERROR); + + CLISetup::siteLock(CLISetup::LOCK_RESTORE); } else if (SqlGen::getMode() == SqlGen::MODE_NORMAL) CLI::write('no valid script names supplied', CLI::LOG_ERROR); diff --git a/setup/tools/clisetup/sync.func.php b/setup/tools/clisetup/sync.func.php index f96911d2..0697efba 100644 --- a/setup/tools/clisetup/sync.func.php +++ b/setup/tools/clisetup/sync.func.php @@ -27,7 +27,7 @@ function sync(array $s = [], array $b = []) : void CLI::write(' e.g.: "php aowow --sync=creature_queststarter" causes the table aowow_quests_startend to be recreated.', -1, false); CLI::write(' Also quest-related profiler files will be recreated as they depend on aowow_quests_startend and thus indirectly on creature_queststarter.', -1, false); CLI::write(); - exit; + return; } $_s = sql($s); @@ -43,6 +43,9 @@ function sync(array $s = [], array $b = []) : void $_ = array_diff($b, $_b); DB::Aowow()->query('UPDATE ?_dbversion SET `build` = ?', $_ ? implode(' ', $_) : ''); } + + if (!$s && !$_s && !$b && !$_b) + CLI::write('no valid table names supplied', CLI::LOG_ERROR); } ?> diff --git a/setup/tools/clisetup/update.func.php b/setup/tools/clisetup/update.func.php index 3e6767f7..d61d72b4 100644 --- a/setup/tools/clisetup/update.func.php +++ b/setup/tools/clisetup/update.func.php @@ -11,7 +11,7 @@ if (!CLI) /* automaticly apply sql-updates */ /*********************************/ -function update() : array +function update(?array &$sql = [], ?array &$build = []) : void { [$date, $part] = array_values(DB::Aowow()->selectRow('SELECT `date`, `part` FROM ?_dbversion')); @@ -25,10 +25,11 @@ function update() : array CLI::write(); CLI::write(' Last Update: '.date(Util::$dateFormatInternal, $date).' (Part #'.$part.')', -1, false); CLI::write(); - exit; + return; } CLI::write('checking sql updates'); + CLISetup::siteLock(CLISetup::LOCK_ON); $nFiles = 0; foreach (glob('setup/updates/*.sql') as $file) @@ -69,6 +70,7 @@ function update() : array CLI::write(' -> '.date('d.m.Y', $fDate).' #'.$fPart.': '.$nQuerys.' queries applied', CLI::LOG_OK); } + CLISetup::siteLock(CLISetup::LOCK_RESTORE); CLI::write($nFiles ? 'applied '.$nFiles.' update(s)' : 'db is already up to date', CLI::LOG_OK); // fetch sql/build after applying updates, as they may contain sync-prompts @@ -84,8 +86,6 @@ function update() : array if ($build) CLI::write('The following file(s) require syncing: '.implode(', ', $build)); - - return [$sql, $build]; } ?> diff --git a/setup/tools/fileGen.class.php b/setup/tools/fileGen.class.php index ad78b1d4..b138da95 100644 --- a/setup/tools/fileGen.class.php +++ b/setup/tools/fileGen.class.php @@ -65,33 +65,25 @@ class FileGen 'STATIC_URL' => STATIC_URL ); - public static function init($mode = self::MODE_NORMAL, array $updScripts = []) + public static function init(int $mode = self::MODE_NORMAL, array $updScripts = []) : bool { self::$defaultExecTime = ini_get('max_execution_time'); - $doScripts = null; - self::$mode = $mode; - // handle command prompts - self::handleCLIOpts($doScripts); - if ($mode == self::MODE_NORMAL && !$doScripts) + if (!CLISetup::$localeIds) { - self::printCLIHelp(); - exit; + CLI::write('No valid locale specified. Check your config or --locales parameter, if used', CLI::LOG_ERROR); + return false; } + // handle command prompts + if (!self::handleCLIOpts($doScripts)) + return false; + // check passed subscript names; limit to real scriptNames self::$subScripts = array_merge(array_keys(self::$tplFiles), array_keys(self::$datasets)); if ($doScripts || $updScripts) self::$subScripts = array_intersect($doScripts ?: $updScripts, self::$subScripts); - else if ($doScripts === null) - self::$subScripts = []; - - if (!CLISetup::$localeIds /* todo: && this script has localized text */) - { - CLI::write('No valid locale specified. Check your config or --locales parameter, if used', CLI::LOG_ERROR); - exit; - } // create directory structure CLI::write('FileGen::init() - creating required directories'); @@ -102,9 +94,11 @@ class FileGen CLI::write('created '.$pathOk.' extra paths'.($pathOk == count(self::$reqDirs) ? '' : ' with errors')); CLI::write(); + + return true; } - private static function handleCLIOpts(&$doScripts) + private static function handleCLIOpts(?array &$doScripts) : bool { $doScripts = []; @@ -117,7 +111,7 @@ class FileGen else self::printCLIHelp(); - exit; + return false; } // required subScripts @@ -136,10 +130,19 @@ class FileGen $doScripts[] = $name; } - $doScripts = $doScripts ? array_unique($doScripts) : null; + if (!$doScripts) + return false; + + $doScripts = array_unique($doScripts); + return true; } else if ($_ = CLISetup::getOpt('build')) + { $doScripts = $_; + return true; + } + + return false; } private static function printCLIHelp() diff --git a/setup/tools/sqlGen.class.php b/setup/tools/sqlGen.class.php index aa416be7..d962bc33 100644 --- a/setup/tools/sqlGen.class.php +++ b/setup/tools/sqlGen.class.php @@ -23,13 +23,17 @@ class SqlGen public static $defaultExecTime = 30; public static $sqlBatchSize = 1000; - public static function init(int $mode = self::MODE_NORMAL, array $updScripts = []) : void + public static function init(int $mode = self::MODE_NORMAL, array $updScripts = []) : bool { self::$defaultExecTime = ini_get('max_execution_time'); - $doScripts = null; - self::$mode = $mode; + if (!CLISetup::$localeIds) + { + CLI::write('No valid locale specified. Check your config or --locales parameter, if used', CLI::LOG_ERROR); + return false; + } + // register subscripts foreach (glob('setup/tools/sqlgen/*.func.php') as $file) include_once $file; @@ -76,25 +80,15 @@ class SqlGen } // handle command prompts - self::handleCLIOpts($doScripts); - if ($mode == self::MODE_NORMAL && !$doScripts) - { - self::printCLIHelp(); - exit; - } + if (!self::handleCLIOpts($doScripts)) + return false; // check passed subscript names; limit to real scriptNames self::$subScripts = array_keys(self::$tables); if ($doScripts || $updScripts) self::$subScripts = array_intersect($doScripts ?: $updScripts, self::$subScripts); - else if ($doScripts === null) - self::$subScripts = []; - if (!CLISetup::$localeIds /* && this script has localized text */) - { - CLI::write('No valid locale specified. Check your config or --locales parameter, if used', CLI::LOG_ERROR); - exit; - } + return true; } public static function register(SetupScript $ssRef) : void @@ -138,14 +132,14 @@ class SqlGen } } - private static function handleCLIOpts(&$doTbls) : void + private static function handleCLIOpts(?array &$doTbls) : bool { $doTbls = []; if (CLISetup::getOpt('help') && self::$mode == self::MODE_NORMAL) { self::printCLIHelp(); - exit; + return false; } // required subScripts @@ -160,10 +154,19 @@ class SqlGen if (array_intersect($sync, $ssRef->getDependencies(true))) $doTbls[] = $name; - $doTbls = $doTbls ? array_unique($doTbls) : null; + if (!$doTbls) + return false; + + $doTbls = array_unique($doTbls); + return true; } else if ($_ = CLISetup::getOpt('sql')) + { $doTbls = $_; + return true; + } + + return false; } private static function printCLIHelp() : void