From 59f58f85063609bdb856317b25ba9a5d1c9fc255 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Wed, 29 Jul 2020 17:01:20 +0200 Subject: [PATCH] Setup * automatically set and unset maintenance mode when data is being edited (either sql or files) * added more verbose help prompts. They should now always appear when -h is used. * added --setup as more intuitive command for --firstrun. --firstrun is now considered deprecated and will be removed in due time. * unfuck order of indizes in --siteconfig * fixed some typos * convert echo use to CLI::write * move scattered command line argument checks to CLISetup --- includes/defines.php | 8 + includes/shared.php | 2 +- includes/utilities.php | 68 ++++++-- setup/setup.php | 95 +++++------ setup/tools/CLISetup.class.php | 165 +++++++++++++++++--- setup/tools/clisetup/account.func.php | 2 +- setup/tools/clisetup/build.func.php | 2 +- setup/tools/clisetup/dbconfig.func.php | 4 +- setup/tools/clisetup/firstrun.func.php | 64 +++++--- setup/tools/clisetup/siteconfig.func.php | 10 +- setup/tools/clisetup/sql.func.php | 2 +- setup/tools/clisetup/sync.func.php | 48 ++++++ setup/tools/clisetup/update.func.php | 15 +- setup/tools/fileGen.class.php | 122 ++++++--------- setup/tools/filegen/complexImg.func.php | 35 ++--- setup/tools/filegen/simpleImg.func.php | 24 +-- setup/tools/setupScript.class.php | 8 +- setup/tools/sqlGen.class.php | 95 +++++++---- setup/tools/sqlgen/achievement.func.php | 4 +- setup/tools/sqlgen/areatrigger.func.php | 2 +- setup/tools/sqlgen/creature.func.php | 2 +- setup/tools/sqlgen/currencies.func.php | 4 +- setup/tools/sqlgen/events.func.php | 2 +- setup/tools/sqlgen/glyphproperties.func.php | 2 +- setup/tools/sqlgen/item_stats.func.php | 2 +- setup/tools/sqlgen/itemenchantment.func.php | 2 +- setup/tools/sqlgen/items.func.php | 4 +- setup/tools/sqlgen/itemset.func.php | 4 +- setup/tools/sqlgen/objects.func.php | 2 +- setup/tools/sqlgen/pet.func.php | 4 +- setup/tools/sqlgen/quests.func.php | 2 +- setup/tools/sqlgen/quests_startend.func.php | 2 +- setup/tools/sqlgen/skillline.func.php | 2 +- setup/tools/sqlgen/source.func.php | 4 +- setup/tools/sqlgen/spawns.func.php | 2 +- setup/tools/sqlgen/spell.func.php | 4 +- setup/tools/sqlgen/spelldifficulty.func.php | 2 +- setup/tools/sqlgen/taxi.func.php | 2 +- setup/tools/sqlgen/titles.func.php | 2 +- setup/tools/sqlgen/zones.func.php | 2 +- 40 files changed, 523 insertions(+), 304 deletions(-) create mode 100644 setup/tools/clisetup/sync.func.php diff --git a/includes/defines.php b/includes/defines.php index 4f5234a6..72222380 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -17,6 +17,14 @@ define('MIME_TYPE_RSS', 'Content-Type: application/rss+xml; charset=utf-8'); define('MIME_TYPE_JPEG', 'Content-Type: image/jpeg'); define('MIME_TYPE_PNG', 'Content-Type: image/png'); +// shared setup strings +define('ERR_CREATE_FILE', 'could not create file at destination %s'); +define('ERR_WRITE_FILE', 'could not write to file at destination %s'); +define('ERR_READ_FILE', 'file %s could not be read'); +define('ERR_MISSING_FILE', 'file %s not found'); +define('ERR_NONE', 'created file %s'); +define('ERR_MISSING_INCL', 'required function %s() could not be found at %s'); + // TypeIds define('TYPE_NPC', 1); define('TYPE_OBJECT', 2); diff --git a/includes/shared.php b/includes/shared.php index a6586514..63aea5e2 100644 --- a/includes/shared.php +++ b/includes/shared.php @@ -1,6 +1,6 @@ $row) + { + if (!is_array($out[0])) + { + unset($out[$i]); + continue; + } + + if (!$nCols) + $nCols = count($row); + + for ($j = 0; $j < $nCols - 1; $j++) // don't pad last column + $pads[$j] = max($pads[$j], mb_strlen($row[$j])); + } + self::write(); + + foreach ($out as $row) + { + for ($i = 0; $i < $nCols - 1; $i++) // don't pad last column + $row[$i] = str_pad($row[$i], $pads[$i] + 2); + + self::write(' '.implode($row), -1, $timestamp); + } + + self::write(); + } + + /***********/ /* logging */ /***********/ @@ -86,12 +127,14 @@ class CLI return OS_WIN ? $str : "\e[1m".$str."\e[0m"; } - public static function write(string $txt = '', int $lvl = -1) : void + public static function write(string $txt = '', int $lvl = self::LOG_BLANK, bool $timestamp = true) : void { - $msg = "\n"; + $msg = ''; if ($txt) { - $msg = str_pad(date('H:i:s'), 10); + if ($timestamp) + $msg = str_pad(date('H:i:s'), 10); + switch ($lvl) { case self::LOG_ERROR: // red critical error @@ -106,12 +149,15 @@ class CLI case self::LOG_INFO: // blue info $msg .= '['.self::blue('INFO').'] '; break; - default: + case self::LOG_BLANK: $msg .= ' '; + break; } $msg .= $txt."\n"; } + else + $msg = "\n"; echo $msg; @@ -177,7 +223,7 @@ class CLI this also means, you can't hide input at all, least process it */ - public static function readInput(array &$fields, bool $singleChar = false) : bool + public static function read(array &$fields, bool $singleChar = false) : bool { // first time set if (self::$hasReadline === null) @@ -368,8 +414,8 @@ class Util 'large' => 'style="background-image: url(%s/images/wow/icons/large/%s.jpg)"', ); - public static $configCats = array( - 'Other', 'Site', 'Caching', 'Account', 'Session', 'Site Reputation', 'Google Analytics', 'Profiler' + public static $configCats = array( // don't mind the ordering ... please? + 1 => 'Site', 'Caching', 'Account', 'Session', 'Site Reputation', 'Google Analytics', 'Profiler', 0 => 'Other' ); public static $tcEncoding = '0zMcmVokRsaqbdrfwihuGINALpTjnyxtgevElBCDFHJKOPQSUWXYZ123456789'; diff --git a/setup/setup.php b/setup/setup.php index e385bdce..677f0538 100644 --- a/setup/setup.php +++ b/setup/setup.php @@ -7,96 +7,71 @@ if (!CLI) die('not in cli mode'); -// shared strings -define('ERR_CREATE_FILE', 'could not create file at destination %s' ); -define('ERR_WRITE_FILE', 'could not write to file at destination %s' ); -define('ERR_READ_FILE', 'file %s could not be read' ); -define('ERR_MISSING_FILE', 'file %s not found' ); -define('ERR_NONE', 'created file %s' ); -define('ERR_MISSING_INCL', 'required function %s() could not be found at %s'); - - require_once 'setup/tools/CLISetup.class.php'; require_once 'setup/tools/setupScript.class.php'; require_once 'setup/tools/dbc.class.php'; require_once 'setup/tools/imagecreatefromblp.func.php'; -function finish() + +function finish(bool $unlock = true) : void { - if (!getopt('d', ['delete'])) // generated with TEMPORARY keyword. Manual deletion is not needed - CLI::write('generated dbc_* - tables kept available', CLI::LOG_INFO); + 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"); } -$opt = getopt('h', ['help', 'account', 'dbconfig', 'siteconfig', 'sql', 'build', 'sync', 'update', 'firstrun', 'dbc:']); -if (!$opt || ((isset($opt['help']) || isset($opt['h'])) && (isset($opt['firstrun']) || isset($opt['resume'])))) +function lockSite(bool $enable = true) : void { - echo "\nAowow Setup\n"; - echo "--dbconfig : set up db connection\n"; - echo "--siteconfig : set up site variables\n"; - echo "--account : create an account with admin privileges\n"; - echo "--sql : generate db content from your world tables\n"; - echo "--build : create server specific files\n"; - echo "--sync= : regenerate tables/files that depend on given world-table\n"; - echo "--update : apply new sql updates fetched from github\n"; - echo "--firstrun : goes through the nessecary hoops of the initial setup.\n"; - echo "additional options\n"; - echo "--log logfile : write ouput to file\n"; - echo "--locales= : limit setup to enUS, frFR, deDE, esES and/or ruRU (does not override config settings)\n"; - echo "--mpqDataDir=path/ : manually point to directory with extracted mpq files; is limited to setup/ (default: setup/mpqData/)\n"; - echo "--delete | -d : delete generated dbc_* tables when script finishes\n"; - echo "--help | -h : contextual help\n"; - die("\n"); + DB::Aowow()->query('UPDATE ?_config SET `value` = ?d WHERE `key` = "maintenance"', $enable ? 1 : 0); } -else - CLISetup::init(); -$cmd = array_pop(array_keys($opt)); -$s = []; -$b = []; +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 = []; switch ($cmd) // we accept only one main parameter { - case 'firstrun': + case 'setup': + lockSite(true); require_once 'setup/tools/clisetup/firstrun.func.php'; - firstrun(); + $success = firstrun(); - finish(); + finish($success); + case 'sql': + case 'build': + lockSite(true); + $unlock = true; case 'account': case 'dbconfig': case 'siteconfig': - case 'sql': - case 'build': require_once 'setup/tools/clisetup/'.$cmd.'.func.php'; $cmd(); - finish(); + finish($unlock); case 'update': + lockSite(true); require_once 'setup/tools/clisetup/update.func.php'; + [$s, $b] = update(); // return true if we do not rebuild stuff if (!$s && !$b) - return; + finish(true); case 'sync': - require_once 'setup/tools/clisetup/sql.func.php'; - require_once 'setup/tools/clisetup/build.func.php'; - $_s = sql($s); - $_b = build($b); + lockSite(true); + require_once 'setup/tools/clisetup/sync.func.php'; - if ($s) - { - $_ = array_diff($s, $_s); - DB::Aowow()->query('UPDATE ?_dbversion SET `sql` = ?', $_ ? implode(' ', $_) : ''); - } - - if ($b) - { - $_ = array_diff($b, $_b); - DB::Aowow()->query('UPDATE ?_dbversion SET `build` = ?', $_ ? implode(' ', $_) : ''); - } - - finish(); + sync($s, $b); + finish(true); case 'dbc': - foreach (explode(',', $opt['dbc']) as $n) + foreach (CLISetup::getOpt('dbc') as $n) { if (empty($n)) continue; diff --git a/setup/tools/CLISetup.class.php b/setup/tools/CLISetup.class.php index 25678a31..de5fd100 100644 --- a/setup/tools/CLISetup.class.php +++ b/setup/tools/CLISetup.class.php @@ -14,8 +14,6 @@ class CLISetup public static $srcDir = 'setup/mpqdata/'; - public static $tmpDBC = false; - private static $mpqFiles = []; public static $expectedPaths = array( // update paths [yes, you can have en empty string as key] '' => LOCALE_EN, 'enGB' => LOCALE_EN, 'enUS' => LOCALE_EN, @@ -26,31 +24,96 @@ class CLISetup 'ruRU' => LOCALE_RU ); - public static function init() + private const ARGV_REQUIRED = 0x01; + private const ARGV_OPTIONAL = 0x02; + private const ARGV_ARRAY = 0x10; + + private static $opts = []; + private static $optGroups = ['AoWoW Setup', 'Utility Functions', 'Additional Options', 'Additional arguments specific to --build=simpleImg', 'Additional arguments specific to --build=complexImg']; + private static $optDefs = array( // cmd => [groupId, aliasses[], flags, description, appendix] + 'setup' => [0, ['s', 'firstrun'], 0x00, 'Step by step initial setup. Resumes if interrupted.', '' ], + 'update' => [0, ['u'], 0x00, 'Apply new sql updates fetched from Github and run --sync as needed.', '' ], + 'dbconfig' => [1, [], 0x00, 'Set up DB connection.', '' ], + 'siteconfig' => [1, [], 0x00, 'Set up site variables.', '' ], + 'account' => [1, [], 0x00, 'Create an account with admin privileges.', '' ], + 'sql' => [1, [], 0x12, 'Generate DB content from your world tables.', '=' ], + 'build' => [1, [], 0x12, 'Compile image files and data dumps.', '=' ], + 'sync' => [1, [], 0x12, 'Regenerate tables/files that depend on given world DB table.', '='], + 'dbc' => [1, [], 0x11, 'Extract dbc files from mpqDataDir into sql table. Structure must be defined in setup/dbc.class.php.', '=' ], + 'delete' => [2, ['d'], 0x00, 'Delete dbc_* tables generated by this prompt when done.', '' ], + 'log' => [2, [], 0x01, 'Write CLI ouput to file.', '=logfile' ], + 'help' => [2, ['h'], 0x00, 'Display contextual help, if available.', '' ], + 'force' => [2, ['f'], 0x00, 'Force existing files to be overwritten.', '' ], + 'locales' => [2, [], 0x12, 'Limit setup to enUS, frFR, deDE, zhCN, esES and/or ruRU. (does not override config settings)', '=' ], + 'mpqDataDir' => [2, [], 0x02, 'Manually point to directory with extracted mpq files. This is limited to setup/ (default: setup/mpqData/)', '=path/' ], + 'icons' => [3, ['1'], 0x00, 'Generate icons for spells, items, classes, races, ect.', '' ], + 'glyphs' => [3, ['2'], 0x00, 'Generate decorative glyph symbols displayed on related item and spell pages.', '' ], + 'pagetexts' => [3, ['3'], 0x00, 'Generate images contained in text on readable items and gameobjects.', '' ], + 'loadingscreens' => [3, ['4'], 0x00, 'Generate loading screen images (not used on page; skipped by default)', '' ], + 'talentbgs' => [4, ['1'], 0x00, 'Generate backgrounds for the talent calculator.', '' ], + 'maps' => [4, ['2'], 0x00, 'Generate zone and continental maps.', '' ], + 'spawn-maps' => [4, ['3'], 0x00, 'Fallback to generate alpha masks for each zone to match creature and gameobject spawn points.', '' ], + 'artwork' => [4, ['4'], 0x00, 'Generate images from /glues/credits (not used on page; skipped by default))', '' ], + 'area-maps' => [4, ['5'], 0x00, 'Generate additional area maps with highlighting for subzones (optional; skipped by default)', '' ] + ); + + + /**************************/ + /* command line arguments */ + /**************************/ + + public static function init() : void { - if ($_ = getopt('d', ['log::', 'locales::', 'mpqDataDir::', 'delete'])) + $short = ''; + $long = []; + $alias = []; + + foreach (self::$optDefs as $opt => [$idx, $aliasses, $flags, , ]) { - // optional logging - if (!empty($_['log'])) - CLI::initLogFile(trim($_['log'])); + if ($flags & self::ARGV_REQUIRED) + $opt .= ':'; + else if ($flags & self::ARGV_OPTIONAL) + $opt .= '::'; - // alternative data source (no quotes, use forward slash) - if (!empty($_['mpqDataDir'])) - self::$srcDir = CLI::nicePath($_['mpqDataDir']); - - // optional limit handled locales - if (!empty($_['locales'])) + $long[] = $opt; + foreach ($aliasses as $a) { - // engb and enus are identical for all intents and purposes - $from = ['engb', 'esmx', 'encn']; - $to = ['enus', 'eses', 'zhcn']; - $_['locales'] = str_ireplace($from, $to, strtolower($_['locales'])); + if ($flags & self::ARGV_REQUIRED) // neither should be set with shortOpts + $_a = $a.':'; + else if ($flags & self::ARGV_OPTIONAL) + $_a = $a.'::'; + else + $_a = $a; - self::$locales = array_intersect(Util::$localeStrings, explode(',', $_['locales'])); + $alias[$a] = $opt; + if (strlen($a) == 1) + $short .= $_a; + else + $long[] = $_a; } + } - if (isset($_['d']) || isset($_['delete'])) - self::$tmpDBC = true; + if ($opts = getopt($short, $long)) + foreach ($opts as $o => $v) + self::$opts[$alias[$o] ?? $o] = (self::$optDefs[$alias[$o] ?? $o][2] & self::ARGV_ARRAY) ? ($v ? explode(',', $v) : []) : ($v ?: true); + + // optional logging + if (self::$opts['log']) + CLI::initLogFile(trim(self::$opts['log'])); + + // alternative data source (no quotes, use forward slash) + if (self::$opts['mpqDataDir']) + self::$srcDir = CLI::nicePath($self::$opts['mpqDataDir']); + + // optional limit handled locales + if (self::$opts['locales']) + { + // engb and enus are identical for all intents and purposes + $from = ['engb', 'esmx', 'encn']; + $to = ['enus', 'eses', 'zhcn']; + $_['locales'] = str_ireplace($from, $to, strtolower($_['locales'])); + + self::$locales = array_intersect(Util::$localeStrings, explode(',', $_['locales'])); } if (!self::$locales) @@ -62,6 +125,62 @@ class CLISetup self::$localeIds[] = $idx; } + public static function getOpt(...$args) + { + if (!$args) + return false; + + $result = []; + + // groupMask case + if (is_int($args[0])) + { + foreach (self::$optDefs as $o => [$group, , , , ]) + if (((1 << $group) & $args[0]) && isset(self::$opts[$o])) + $result[] = $o; + + return $result; + } + + // single key case + if (count($args) == 1) + return self::$opts[$args[0]] ?? false; + + // multiple keys case + foreach ($args as $a) + if (isset(self::$optDefs[$a])) + $result[$a] = self::$opts[$a] ?? false; + + return $result; + } + + public static function optHelp(int $groupMask = 0x0) : void + { + $lines = []; + + foreach (self::$optGroups as $idx => $og) + { + if ($groupMask && !($groupMask & (1 << $idx))) + continue; + + $lines[] = [$og, '']; + + foreach (self::$optDefs as $opt => [$group, $alias, , $desc, $app]) + { + if ($group != $idx) + continue; + + $cmd = ' --'.$opt; + foreach ($alias as $a) + $cmd .= ' | '.(strlen($a) == 1 ? '-'.$a : '--'.$a); + + $lines[] = [$cmd.$app, $desc]; + } + } + + CLI::writeTable($lines); + } + /*******************/ /* MPQ-file access */ @@ -73,10 +192,10 @@ class CLISetup unix systems will throw a fit if you try to get from one to the other, so lets save the paths from 2) and cast it to lowercase lookups will be done in lowercase. A successfull match will return the real path. */ - private static function buildFileList() + private static function buildFileList() : bool { CLI::write(); - CLI::write('reading MPQdata from '.self::$srcDir.' to list for first time use...'); + CLI::write('indexing game data from '.self::$srcDir.' for first time use...'); $setupDirs = glob('setup/*'); foreach ($setupDirs as $sd) @@ -195,7 +314,7 @@ class CLISetup if (DB::Aowow()->selectCell('SHOW TABLES LIKE ?', 'dbc_'.$name) && DB::Aowow()->selectCell('SELECT count(1) FROM ?#', 'dbc_'.$name)) return true; - $dbc = new DBC($name, ['temporary' => self::$tmpDBC]); + $dbc = new DBC($name, ['temporary' => self::getOpt('delete')]); if ($dbc->error) { CLI::write('CLISetup::loadDBC() - required DBC '.$name.'.dbc not found!', CLI::LOG_ERROR); diff --git a/setup/tools/clisetup/account.func.php b/setup/tools/clisetup/account.func.php index 3beac4db..44eff9d5 100644 --- a/setup/tools/clisetup/account.func.php +++ b/setup/tools/clisetup/account.func.php @@ -22,7 +22,7 @@ function account() User::useLocale(LOCALE_EN); Lang::load(Util::$localeStrings[LOCALE_EN]); - if (CLI::readInput($fields)) + if (CLI::read($fields)) { CLI::write(); diff --git a/setup/tools/clisetup/build.func.php b/setup/tools/clisetup/build.func.php index 07d146b6..fb879924 100644 --- a/setup/tools/clisetup/build.func.php +++ b/setup/tools/clisetup/build.func.php @@ -81,7 +81,7 @@ function build($syncMe = null) else CLI::write('finished file generation with errors', CLI::LOG_ERROR); } - else if ($syncMe) + else if (FileGen::getMode() == FileGen::MODE_NORMAL) CLI::write('no valid script names supplied', CLI::LOG_ERROR); return $done; diff --git a/setup/tools/clisetup/dbconfig.func.php b/setup/tools/clisetup/dbconfig.func.php index c9bdef69..4854834c 100644 --- a/setup/tools/clisetup/dbconfig.func.php +++ b/setup/tools/clisetup/dbconfig.func.php @@ -79,7 +79,7 @@ function dbconfig() while (true) { $inp = ['idx' => ['', true, '/\d/']]; - if (CLI::readInput($inp, true) && $inp) + if (CLI::read($inp, true) && $inp) { if ($inp['idx'] >= 0 && $inp['idx'] <= (3 + $nCharDBs)) { @@ -88,7 +88,7 @@ function dbconfig() if ($inp['idx'] == 3 + $nCharDBs) // add new realmDB $curFields['realmId'] = ['Realm Id', false, '/[1-9][0-9]*/']; - if (CLI::readInput($curFields)) + if (CLI::read($curFields)) { if ($inp['idx'] == 0 && $curFields) $curFields['prefix'] = 'aowow_'; diff --git a/setup/tools/clisetup/firstrun.func.php b/setup/tools/clisetup/firstrun.func.php index c58f612b..175072da 100644 --- a/setup/tools/clisetup/firstrun.func.php +++ b/setup/tools/clisetup/firstrun.func.php @@ -11,7 +11,7 @@ if (!CLI) /* string setup steps together for first use */ /*********************************************/ -function firstrun() +function firstrun() : bool { require_once 'setup/tools/sqlGen.class.php'; require_once 'setup/tools/fileGen.class.php'; @@ -19,6 +19,7 @@ function firstrun() SqlGen::init(SqlGen::MODE_FIRSTRUN); FileGen::init(FileGen::MODE_FIRSTRUN); + /****************/ /* define steps */ /****************/ @@ -97,22 +98,22 @@ function firstrun() ['FileGen::generate', 'weightPresets', null, null, null], // apply sql-updates from repository ['update', null, null, null, null], - ['account', null, 'testAcc', 'Please create your admin account.', 'There is no user with administrator priviledges in the DB.'], - ['endSetup', null, null, null, null], + ['account', null, 'testAcc', 'Please create your admin account.', 'There is no user with administrator privileges in the DB.'] ); + /**********/ /* helper */ /**********/ - $saveProgress = function($nStep) + $saveProgress = function(int $nStep) : void { $h = fopen('cache/firstrun', 'w'); fwrite($h, AOWOW_REVISION."\n".($nStep + 1)."\n"); fclose($h); }; - function testDB(&$error) + function testDB(array &$error) : bool { require 'config/config.php'; @@ -137,7 +138,7 @@ function firstrun() return empty($error); } - function testSelf(&$error) + function testSelf(array &$error) : bool { $error = []; $test = function(&$protocol, &$host, $testFile, &$rCode) @@ -184,8 +185,8 @@ function firstrun() { CLI::write('self test received status '.CLI::bold($resp).' (page moved) for '.$conf.', pointing to: '.$protocol.$host.$testFile, CLI::LOG_WARN); $inp = ['x' => ['should '.CLI::bold($conf).' be set to '.CLI::bold($host).' and force_ssl be updated? (y/n)', true, '/y|n/i']]; - if (!CLI::readInput($inp, true) || !$inp || strtolower($inp['x']) == 'n') - $error[] = ' * could not access '.$protocol.$host.$testFile.' ['.$resp.']'; + if (!CLI::read($inp, true) || !$inp || strtolower($inp['x']) == 'n') + $error[] = ' * '.$protocol.$host.$testFile.' ['.$resp.']'; else { DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $host, $conf); @@ -195,7 +196,7 @@ function firstrun() CLI::write(); } else - $error[] = ' * could not access '.$protocol.$host.$testFile.' ['.$resp.']'; + $error[] = ' * '.$protocol.$host.$testFile.' ['.$resp.']'; } } else @@ -205,16 +206,12 @@ function firstrun() return empty($error); } - function testAcc(&$error) + function testAcc(array &$error) : bool { $error = []; - return !!DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE userPerms = 1'); + return !!DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `userPerms` = 1'); } - function endSetup() - { - return DB::Aowow()->query('UPDATE ?_config SET value = 0 WHERE `key` = "maintenance"'); - } /********************/ /* get current step */ @@ -228,13 +225,33 @@ function firstrun() $startStep = (int)$rows[1]; } + if (CLISetup::getOpt('help')) + { + CLI::write(); + CLI::write(' usage: php aowow --setup [--locales: --mpqDataDir:]', -1, false); + CLI::write(); + CLI::write(' Initially essential connection information are set up and basic connectivity tests are run afterwards.', -1, false); + CLI::write(' In the main stage dbc and world data is compiled into the database and required sound, image and data files are generated.', -1, false); + CLI::write(' This does not require further input and will take about 15-20 minutes, plus 10 minutes per additional locale.', -1, false); + CLI::write(' Lastly pending updates are applied and you are prompted to create an administrator account.', -1, false); + + if ($startStep) + { + CLI::write(); + CLI::write(' You are currently on step '.($startStep + 1).' / '.count($steps).'. You can resume or restart the setup process.', -1, false); + } + + CLI::write(); + exit; + } + if ($startStep) { CLI::write('Found firstrun progression info. (Halted on subscript '.($steps[$startStep][1] ?: $steps[$startStep][0]).')', CLI::LOG_INFO); $inp = ['x' => ['continue setup? (y/n)', true, '/y|n/i']]; $msg = ''; - if (!CLI::readInput($inp, true) || !$inp || strtolower($inp['x']) == 'n') + if (!CLI::read($inp, true) || !$inp || strtolower($inp['x']) == 'n') { $msg = 'Starting setup from scratch...'; $startStep = 0; @@ -247,6 +264,7 @@ function firstrun() sleep(1); } + /*******/ /* run */ /*******/ @@ -262,10 +280,10 @@ function firstrun() if ($step[3]) { CLI::write($step[3]); - $inp = ['x' => ['Press any key to continue', true]]; - if (!CLI::readInput($inp, true)) // we don't actually care about the input - return; + $inp = ['x' => ['Press any key to continue', true]]; + if (!CLI::read($inp, true)) // we don't actually care about the input + return false; } while (true) @@ -275,6 +293,7 @@ function firstrun() // check script result if ($step[2]) { + $errors = []; if (!$step[2]($errors)) { CLI::write($step[4], CLI::LOG_ERROR); @@ -294,7 +313,7 @@ function firstrun() } $inp = ['x' => ['['.CLI::bold('c').']ontinue anyway? ['.CLI::bold('r').']etry? ['.CLI::bold('a').']bort?', true, '/c|r|a/i']]; - if (CLI::readInput($inp, true) && $inp) + if (CLI::read($inp, true) && $inp) { CLI::write(); switch(strtolower($inp['x'])) @@ -305,19 +324,20 @@ function firstrun() case 'r': break; case 'a': - return; + return false; } } else { CLI::write(); - return; + return false; } } } unlink('cache/firstrun'); CLI::write('setup finished', CLI::LOG_OK); + return true; } ?> diff --git a/setup/tools/clisetup/siteconfig.func.php b/setup/tools/clisetup/siteconfig.func.php index 193198c7..3e863941 100644 --- a/setup/tools/clisetup/siteconfig.func.php +++ b/setup/tools/clisetup/siteconfig.func.php @@ -166,7 +166,7 @@ function siteconfig() } $inp = ['idx' => ['', false, '/\d/']]; - if (CLI::readInput($inp) && $inp && $inp['idx'] !== '') + if (CLI::read($inp) && $inp && $inp['idx'] !== '') { // add new php setting if ($inp['idx'] == $sumNum) @@ -180,7 +180,7 @@ function siteconfig() 'key' => ['option name', false, '/[\w_\.\-]/i'], 'val' => ['value', ] ); - if (CLI::readInput($setting) && $setting) + if (CLI::read($setting) && $setting) { CLI::write(); @@ -270,7 +270,7 @@ function siteconfig() while (true) { $action = ['idx' => ['', true, '/[edr]/i']]; - if (CLI::readInput($action, true) && $action) + if (CLI::read($action, true) && $action) { switch (strtoupper($action['idx'])) { @@ -325,7 +325,7 @@ function siteconfig() while (true) { $use = $value; - if (CLI::readInput($use, $single)) + if (CLI::read($use, $single)) { CLI::write(); @@ -408,7 +408,7 @@ function siteconfig() else { CLI::write(); - CLI::write('site configuration aborted', CLI::LOG_INFO); + CLI::write('leaving site configuration...', CLI::LOG_INFO); break; } diff --git a/setup/tools/clisetup/sql.func.php b/setup/tools/clisetup/sql.func.php index 735a910c..2e85c603 100644 --- a/setup/tools/clisetup/sql.func.php +++ b/setup/tools/clisetup/sql.func.php @@ -47,7 +47,7 @@ function sql($syncMe = null) else CLI::write('finished sql generation with errors', CLI::LOG_ERROR); } - else if ($syncMe) + else if (SqlGen::getMode() == SqlGen::MODE_NORMAL) CLI::write('no valid script names supplied', CLI::LOG_ERROR); return $done; diff --git a/setup/tools/clisetup/sync.func.php b/setup/tools/clisetup/sync.func.php new file mode 100644 index 00000000..f96911d2 --- /dev/null +++ b/setup/tools/clisetup/sync.func.php @@ -0,0 +1,48 @@ + [--locales: --mpqDataDir: --force -f]', -1, false); + CLI::write(); + CLI::write(' Truncates and recreates AoWoW tables and static data files that depend on the given TC world table. Use this command after you updated your world database.', -1, false); + CLI::write(); + 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; + } + + $_s = sql($s); + if ($s) + { + $_ = array_diff($s, $_s); + DB::Aowow()->query('UPDATE ?_dbversion SET `sql` = ?', $_ ? implode(' ', $_) : ''); + } + + $_b = build($b); + if ($b) + { + $_ = array_diff($b, $_b); + DB::Aowow()->query('UPDATE ?_dbversion SET `build` = ?', $_ ? implode(' ', $_) : ''); + } +} + +?> diff --git a/setup/tools/clisetup/update.func.php b/setup/tools/clisetup/update.func.php index 5958e088..3e6767f7 100644 --- a/setup/tools/clisetup/update.func.php +++ b/setup/tools/clisetup/update.func.php @@ -11,10 +11,23 @@ if (!CLI) /* automaticly apply sql-updates */ /*********************************/ -function update() +function update() : array { [$date, $part] = array_values(DB::Aowow()->selectRow('SELECT `date`, `part` FROM ?_dbversion')); + if (CLISetup::getOpt('help')) + { + CLI::write(); + CLI::write(' usage: php aowow --update', -1, false); + CLI::write(); + CLI::write(' Checks /setup/updates for new *.sql files and applies them. If required by an applied update, the --sql and --build command are triggered afterwards.', -1, false); + CLI::write(' Use this after fetching the latest rev. from Github.', -1, false); + CLI::write(); + CLI::write(' Last Update: '.date(Util::$dateFormatInternal, $date).' (Part #'.$part.')', -1, false); + CLI::write(); + exit; + } + CLI::write('checking sql updates'); $nFiles = 0; diff --git a/setup/tools/fileGen.class.php b/setup/tools/fileGen.class.php index 542e240d..ad78b1d4 100644 --- a/setup/tools/fileGen.class.php +++ b/setup/tools/fileGen.class.php @@ -7,26 +7,18 @@ if (!CLI) die('not in cli mode'); - class FileGen { const MODE_NORMAL = 1; const MODE_FIRSTRUN = 2; const MODE_UPDATE = 3; + private static $mode = 0; + public static $tplPath = 'setup/tools/filegen/templates/'; - public static $cliOpts = []; - private static $shortOpts = 'fh'; - private static $longOpts = array( - 'build::', 'help', 'force', 'sync:', // general - 'icons', 'glyphs', 'pagetexts', 'loadingscreens', // whole images - 'artwork', 'talentbgs', 'maps', 'spawn-maps', 'area-maps' // images from image parts - ); - private static $mode = 0; - public static $subScripts = []; - public static $tplFiles = array( + public static $tplFiles = array( // name => [file, path, TCDeps] 'searchplugin' => ['aowow.xml', 'static/download/searchplugins/', []], 'power' => ['power.js', 'static/widgets/', []], 'searchboxScript' => ['searchbox.js', 'static/widgets/', []], @@ -36,21 +28,21 @@ class FileGen 'locales' => ['locale.js', 'static/js/', []], 'itemScaling' => ['item-scaling', 'datasets/', []] ); - public static $datasets = array( // name => [AowowDeps, TCDeps] - 'realms' => [null, ['realmlist']], - 'statistics' => [null, ['player_levelstats', 'player_classlevelstats']], - 'simpleImg' => [null, null], - 'complexImg' => [null, null], - 'talentCalc' => [null, null], - 'pets' => [['spawns', 'creature'], null], - 'talentIcons' => [null, null], - 'glyphs' => [['items', 'spell'], null], - 'itemsets' => [['itemset', 'spell'], null], - 'enchants' => [['items', 'spell', 'itemenchantment'], null], - 'gems' => [['items', 'spell', 'itemenchantment'], null], - 'profiler' => [['quests', 'quests_startend', 'spell', 'currencies', 'achievement', 'titles'], null], - 'weightPresets' => [null, null], - 'soundfiles' => [['sounds'], null] + public static $datasets = array( // name => [AowowDeps, TCDeps, info] + 'realms' => [null, ['realmlist'], 'datasets/realms'], + 'statistics' => [null, ['player_levelstats', 'player_classlevelstats'], 'datasets/statistics'], + 'simpleImg' => [null, null, 'static/images/wow/[icons, Interface, ]/*'], + 'complexImg' => [null, null, 'static/images/wow/[maps, talents/backgrounds, ]/*'], + 'talentCalc' => [null, null, 'datasets//talents-*'], + 'pets' => [['spawns', 'creature'], null, 'datasets//pets'], + 'talentIcons' => [null, null, 'static/images/wow/talents/icons/*'], + 'glyphs' => [['items', 'spell'], null, 'datasets//glyphs'], + 'itemsets' => [['itemset', 'spell'], null, 'datasets//itemsets'], + 'enchants' => [['items', 'spell', 'itemenchantment'], null, 'datasets//enchants'], + 'gems' => [['items', 'spell', 'itemenchantment'], null, 'datasets//gems'], + 'profiler' => [['quests', 'quests_startend', 'spell', 'currencies', 'achievement', 'titles'], null, 'datasets//p-*'], + 'weightPresets' => [null, null, 'datasets/weight-presets'], + 'soundfiles' => [['sounds'], null, 'static/wowsounds/*'] ); public static $defaultExecTime = 30; @@ -78,9 +70,11 @@ class FileGen self::$defaultExecTime = ini_get('max_execution_time'); $doScripts = null; - if (getopt(self::$shortOpts, self::$longOpts) || $mode == self::MODE_FIRSTRUN) - self::handleCLIOpts($doScripts); - else if ($mode != self::MODE_UPDATE) + self::$mode = $mode; + + // handle command prompts + self::handleCLIOpts($doScripts); + if ($mode == self::MODE_NORMAL && !$doScripts) { self::printCLIHelp(); exit; @@ -108,24 +102,27 @@ class FileGen CLI::write('created '.$pathOk.' extra paths'.($pathOk == count(self::$reqDirs) ? '' : ' with errors')); CLI::write(); - - self::$mode = $mode; } private static function handleCLIOpts(&$doScripts) { - $_ = getopt(self::$shortOpts, self::$longOpts); + $doScripts = []; - if ((isset($_['help']) || isset($_['h'])) && empty($_['build'])) + if (CLISetup::getOpt('help') && self::$mode == self::MODE_NORMAL) { - self::printCLIHelp(); + if (in_array('simpleImg', CLISetup::getOpt('build'))) + CLISetup::optHelp(1 << 3); + else if (in_array('complexImg', CLISetup::getOpt('build'))) + CLISetup::optHelp(1 << 4); + else + self::printCLIHelp(); + exit; } // required subScripts - if (!empty($_['sync'])) + if ($sync = CLISetup::getOpt('sync')) { - $sync = explode(',', $_['sync']); foreach (self::$tplFiles as $name => $info) if (!empty($info[2]) && array_intersect($sync, $info[2])) $doScripts[] = $name; @@ -141,50 +138,27 @@ class FileGen $doScripts = $doScripts ? array_unique($doScripts) : null; } - else if (!empty($_['build'])) - $doScripts = explode(',', $_['build']); - - // optional, overwrite existing files - if (isset($_['f'])) - self::$cliOpts['force'] = true; - - if (isset($_['h'])) - self::$cliOpts['help'] = true; - - // mostly build-instructions from longOpts - foreach (self::$longOpts as $opt) - if (!strstr($opt, ':') && isset($_[$opt])) - self::$cliOpts[$opt] = true; + else if ($_ = CLISetup::getOpt('build')) + $doScripts = $_; } - public static function hasOpt(string ...$opts) : int + private static function printCLIHelp() { - $result = 0x0; - foreach ($opts as $idx => $arg) - { - if (!is_string($arg)) - continue; + CLI::write(); + CLI::write(' usage: php aowow --build= [--mpqDataDir: --locales:]', -1, false); + CLI::write(); + CLI::write(' Compiles files for a given subScript. Existing files are kept by default. Dependencies are taken into account by the triggered calls of --sync and --update', -1, false); - if (isset(self::$cliOpts[$arg])) - $result |= (1 << $idx); - } - - return $result; - } - - public static function printCLIHelp() - { - echo "\nusage: php aowow --build= [-h --help] [-f --force]\n\n"; - echo "--build : available subScripts:\n"; + $lines = [['available subScripts', 'affected files', 'TC dependencies', 'AoWoW dependencies']]; foreach (array_merge(array_keys(self::$tplFiles), array_keys(self::$datasets)) as $s) - { - echo " * ".str_pad($s, 20).str_pad(isset(self::$tplFiles[$s]) ? self::$tplFiles[$s][1].self::$tplFiles[$s][0] : 'static data file', 45). - (!empty(self::$tplFiles[$s][2]) ? ' - TC deps: '.implode(', ', self::$tplFiles[$s][2]) : (!empty(self::$datasets[$s][1]) ? ' - TC deps: '.implode(', ', self::$datasets[$s][1]) : '')). - (!empty(self::$datasets[$s][0]) ? ' - Aowow deps: '.implode(', ', self::$datasets[$s][0]) : '')."\n"; - } + $lines[] = array( + ' * '.$s, + isset(self::$tplFiles[$s]) ? self::$tplFiles[$s][1].self::$tplFiles[$s][0] : self::$datasets[$s][2], + !empty(self::$tplFiles[$s][2]) ? implode(' ', self::$tplFiles[$s][2]) : (!empty(self::$datasets[$s][1]) ? implode(' ', self::$datasets[$s][1]) : ''), + !empty(self::$datasets[$s][0]) ? implode(' ', self::$datasets[$s][0]) : '' + ); - echo "-h --help : shows this info\n"; - echo "-f --force : enforces overwriting existing files\n"; + CLI::writeTable($lines); } public static function generate($key, array $updateIds = []) diff --git a/setup/tools/filegen/complexImg.func.php b/setup/tools/filegen/complexImg.func.php index 0c2d1857..056ebb65 100644 --- a/setup/tools/filegen/complexImg.func.php +++ b/setup/tools/filegen/complexImg.func.php @@ -30,19 +30,6 @@ if (!CLI) function complexImg() { - if (isset(FileGen::$cliOpts['help'])) - { - echo "\n"; - echo "available options for subScript 'complexImg':\n"; // modeMask - echo "--talentbgs (backgrounds for talent calculator)\n"; // 0x01 - echo "--maps (generates worldmaps)\n"; // 0x02 - echo "--spawn-maps (creates alphaMasks of each zone to check spawns against)\n"; // 0x04 - echo "--artwork (optional: imagery from /glues/credits (not used, skipped by default))\n"; // 0x08 - echo "--area-maps (optional: renders maps with highlighted subZones for each area)\n"; // 0x10 - - return true; - } - $mapWidth = 1002; $mapHeight = 668; $threshold = 95; // alpha threshold to define subZones: set it too low and you have unspawnable areas inside a zone; set it too high and the border regions overlap @@ -212,8 +199,18 @@ if (!CLI) }; // do not change order of params! - if ($_ = FileGen::hasOpt('talentbgs', 'maps', 'spawn-maps', 'artwork', 'area-maps')) - $modeMask = $_; + $o = CLISetup::getOpt('talentbgs', 'maps', 'spawn-maps', 'artwork', 'area-maps'); + $m = 0x0; + $i = 0; + foreach ($o as $k => $v) + { + if ($v) + $m |= 1 << $i; + $i++; + } + + if ($m) + $modeMask = $m; foreach ($paths as $mode => $__) if (!($mode & $modeMask)) @@ -318,7 +315,7 @@ if (!CLI) $name = $destDir.'talents/backgrounds/'.strtolower($tt['fileString']).'_'.($tt['tabNumber'] + 1); } - if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.jpg')) + if (!CLISetup::getOpt('force') && file_exists($name.'.jpg')) { CLI::write($done.' - file '.$name.'.jpg was already processed'); continue; @@ -570,7 +567,7 @@ if (!CLI) if ($multiLeveled && !(isset($baseLevelFix[$zoneId]) && $i == $baseLevelFix[$zoneId])) $outFile[$idx] .= '-'.$floor; - if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1])) + if (!CLISetup::getOpt('force') && file_exists($outFile[$idx].'.'.$info[1])) { CLI::write($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed'); $doSkip |= (1 << $idx); @@ -619,7 +616,7 @@ if (!CLI) foreach ($mapDirs as $idx => $info) { $outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]).'/') . $row['areaTableId']; - if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1])) + if (!CLISetup::getOpt('force') && file_exists($outFile[$idx].'.'.$info[1])) { CLI::write($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed'); $doSkip |= (1 << $idx); @@ -719,7 +716,7 @@ if (!CLI) $done = ' - '.str_pad($sum.'/'.$total, 8).str_pad('('.number_format($sum * 100 / $total, 2).'%)', 9); $name = $destDir.'Interface/Glues/Credits/'.$file; - if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.png')) + if (!CLISetup::getOpt('force') && file_exists($name.'.png')) { CLI::write($done.' - file '.$name.'.png was already processed'); continue; diff --git a/setup/tools/filegen/simpleImg.func.php b/setup/tools/filegen/simpleImg.func.php index 25221feb..f7b59c1c 100644 --- a/setup/tools/filegen/simpleImg.func.php +++ b/setup/tools/filegen/simpleImg.func.php @@ -41,18 +41,6 @@ if (!CLI) return $result; }; - if (isset(FileGen::$cliOpts['help'])) - { - echo "\n"; - echo "available options for subScript 'simpleImg':\n"; - echo " --icons (generates square icons that are used for basicly everything)\n"; - echo " --glyphs (decorative tidbit displayed on Infobox for Glyph Spells)\n"; - echo " --pagetexts (imagery contained in PageTexts on readable GameObjects or Items)\n"; - echo " --loadingscreens (loading screens (not used, skipped by default))\n"; - - return true; - } - $groups = []; $imgPath = CLISetup::$srcDir.'%sInterface/'; $destDir = 'static/images/wow/'; @@ -208,13 +196,13 @@ if (!CLI) return !$hasMissing; }; - if (isset(FileGen::$cliOpts['icons'])) + if (CLISetup::getOpt('icons')) array_push($groups, 0, 2, 3, 4, 5, 10); - if (isset(FileGen::$cliOpts['glyphs'])) + if (CLISetup::getOpt('glyphs')) $groups[] = 1; - if (isset(FileGen::$cliOpts['pagetexts'])) + if (CLISetup::getOpt('pagetexts')) array_push($groups, 7, 8, 9); - if (isset(FileGen::$cliOpts['loadingscreens'])) + if (CLISetup::getOpt('loadingscreens')) $groups[] = 11; // filter by passed options @@ -358,7 +346,7 @@ if (!CLI) $img = $isIcon ? strtolower($name) : $name; $done = ' - '.str_pad($j.'/'.$nFiles, 12).str_pad('('.number_format($j * 100 / $nFiles, 2).'%)', 9); - if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$dest.$img.$ext)) + if (!CLISetup::getOpt('force') && file_exists($destDir.$dest.$img.$ext)) { CLI::write($done.' - file '.$dest.$img.$ext.' was already processed'); continue; @@ -427,7 +415,7 @@ if (!CLI) $j++; $done = ' - '.str_pad($j.'/'.$nFiles, 12).str_pad('('.number_format($j * 100 / $nFiles, 2).'%)', 9); - if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$dest.$img.$ext)) + if (!CLISetup::getOpt('force') && file_exists($destDir.$dest.$img.$ext)) { CLI::write($done.' - file '.$dest.$img.$ext.' was already processed'); continue; diff --git a/setup/tools/setupScript.class.php b/setup/tools/setupScript.class.php index 11543208..c22fc292 100644 --- a/setup/tools/setupScript.class.php +++ b/setup/tools/setupScript.class.php @@ -48,8 +48,8 @@ abstract class SetupScript protected $fileTemplatePath = ''; protected $fileTemplateFile = ''; - protected $tblDependancyAowow = []; - protected $tblDependancyTC = []; + protected $tblDependencyAowow = []; + protected $tblDependencyTC = []; protected $dbcSourceFiles = []; @@ -62,9 +62,9 @@ abstract class SetupScript return $this->dbcSourceFiles; } - public function getDependancies(bool $aowow) : array + public function getDependencies(bool $aowow) : array { - return $aowow ? $this->tblDependancyAowow : $this->tblDependancyTC; + return $aowow ? $this->tblDependencyAowow : $this->tblDependencyTC; } public function getName() : string diff --git a/setup/tools/sqlGen.class.php b/setup/tools/sqlGen.class.php index 522c6cd9..aa416be7 100644 --- a/setup/tools/sqlGen.class.php +++ b/setup/tools/sqlGen.class.php @@ -13,14 +13,11 @@ class SqlGen const MODE_FIRSTRUN = 2; const MODE_UPDATE = 3; + private static $mode = 0; + private static $tables = []; private static $tmpStore = []; - public static $cliOpts = []; - private static $shortOpts = 'h'; - private static $longOpts = ['sql::', 'help', 'sync:']; // general - private static $mode = 0; - public static $subScripts = []; public static $defaultExecTime = 30; @@ -31,6 +28,7 @@ class SqlGen self::$defaultExecTime = ini_get('max_execution_time'); $doScripts = null; + self::$mode = $mode; // register subscripts foreach (glob('setup/tools/sqlgen/*.func.php') as $file) @@ -43,7 +41,7 @@ class SqlGen foreach (self::$tmpStore as $idx => $ts) { $depsOK = true; - foreach ($ts->getDependancies(true) as $d) + foreach ($ts->getDependencies(true) as $d) { if (isset(self::$tables[$d])) continue; @@ -68,20 +66,18 @@ class SqlGen if ($nDepsMissing == count(self::$tmpStore)) { - CLI::write('the flollowing SetupScripts have unresolved dependancies and have not been registered:', CLI::LOG_ERROR); + CLI::write('the following SetupScripts have unresolved dependencies and have not been registered:', CLI::LOG_ERROR); foreach (self::$tmpStore as $ts) - CLI::write(' * '.CLI::bold($ts->getName()).' => '.implode(', ', $ts->getDependancies(true))); + CLI::write(' * '.CLI::bold($ts->getName()).' => '.implode(', ', $ts->getDependencies(true))); self::$tmpStore = []; break; } } - // handle command prompts - if (getopt(self::$shortOpts, self::$longOpts) || $mode == self::MODE_FIRSTRUN) - self::handleCLIOpts($doScripts); - else if ($mode != self::MODE_UPDATE) + self::handleCLIOpts($doScripts); + if ($mode == self::MODE_NORMAL && !$doScripts) { self::printCLIHelp(); exit; @@ -99,14 +95,12 @@ class SqlGen CLI::write('No valid locale specified. Check your config or --locales parameter, if used', CLI::LOG_ERROR); exit; } - - self::$mode = $mode; } public static function register(SetupScript $ssRef) : void { - // if dependancies haven't been stored yet, put aside for later use - foreach ($ssRef->getDependancies(true) as $d) + // if dependencies haven't been stored yet, put aside for later use + foreach ($ssRef->getDependencies(true) as $d) { if (isset(self::$tables[$d])) continue; @@ -123,11 +117,11 @@ class SqlGen self::$tables[$ssRef->getName()] = $ssRef; - // recheck temp stored dependancies + // recheck temp stored dependencies foreach (self::$tmpStore as $idx => $ts) { $depsOK = true; - foreach ($ts->getDependancies(true) as $d) + foreach ($ts->getDependencies(true) as $d) { if (isset(self::$tables[$d])) continue; @@ -147,41 +141,78 @@ class SqlGen private static function handleCLIOpts(&$doTbls) : void { $doTbls = []; - $_ = getopt(self::$shortOpts, self::$longOpts); - if ((isset($_['help']) || isset($_['h'])) && empty($_['sql'])) + if (CLISetup::getOpt('help') && self::$mode == self::MODE_NORMAL) { self::printCLIHelp(); exit; } // required subScripts - if (!empty($_['sync'])) + if ($sync = CLISetup::getOpt('sync')) { - $sync = explode(',', $_['sync']); foreach (self::$tables as $name => &$ssRef) - if (array_intersect($sync, $ssRef->getDependancies(false))) + if (array_intersect($sync, $ssRef->getDependencies(false))) $doTbls[] = $name; // recursive dependencies foreach (self::$tables as $name => &$ssRef) - if (array_intersect($sync, $ssRef->getDependancies(true))) + if (array_intersect($sync, $ssRef->getDependencies(true))) $doTbls[] = $name; $doTbls = $doTbls ? array_unique($doTbls) : null; } - else if (!empty($_['sql'])) - $doTbls = explode(',', $_['sql']); + else if ($_ = CLISetup::getOpt('sql')) + $doTbls = $_; } - public static function printCLIHelp() : void + private static function printCLIHelp() : void { - echo "\nusage: php aowow --sql= [-h --help]\n\n"; - echo "--sql : available tables:\n"; - foreach (self::$tables as $t => &$ssRef) - echo " * ".str_pad($t, 24).($ssRef->getDependancies(false) ? ' - TC deps: '.implode(', ', $ssRef->getDependancies(false)) : '').($ssRef->getDependancies(true) ? ' - Aowow deps: '.implode(', ', $ssRef->getDependancies(true)) : '')."\n"; + CLI::write(); + CLI::write(' usage: php aowow --sql= [--mpqDataDir: --locales:]', -1, false); + CLI::write(); + CLI::write(' Regenerates DB table content for a given subScript. Dependencies are taken into account by the triggered calls of --sync and --update', -1, false); - echo "-h --help : shows this info\n"; + $lines = [['available subScripts', 'TC dependencies', 'AoWoW dependencies']]; + foreach (self::$tables as $tbl => &$ssRef) + { + $aoRef = $ssRef->getDependencies(true); + $len = 0; + $first = true; + + $row = [" * ".$tbl, '', '']; + + if ($tc = $ssRef->getDependencies(false)) + { + $len = 0; + foreach ($tc as $t) + { + $n = strlen($t) + 1; + if ($n + $len > 60) + { + // max 2 tables, no multi-row shenanigans required + if ($first && $aoRef) + $row[2] = implode(' ', $aoRef); + + $lines[] = $row; + $row = ['', '', '']; + $len = $n; + $first = false; + } + else + $len += $n; + + $row[1] .= $t." "; + } + } + + if ($first && $aoRef) + $row[2] = implode(' ', $aoRef); + + $lines[] = $row; + } + + CLI::writeTable($lines); } public static function generate(string $tableName, array $updateIds = []) : bool diff --git a/setup/tools/sqlgen/achievement.func.php b/setup/tools/sqlgen/achievement.func.php index 5e1d5e9c..8a528bbe 100644 --- a/setup/tools/sqlgen/achievement.func.php +++ b/setup/tools/sqlgen/achievement.func.php @@ -13,8 +13,8 @@ SqlGen::register(new class extends SetupScript protected $command = 'achievement'; - protected $tblDependancyAowow = ['icons']; - protected $tblDependancyTC = ['dbc_achievement', 'disables']; + protected $tblDependencyAowow = ['icons']; + protected $tblDependencyTC = ['dbc_achievement', 'disables']; protected $dbcSourceFiles = ['achievement_category', 'achievement', 'spellicon']; private $customData = array( diff --git a/setup/tools/sqlgen/areatrigger.func.php b/setup/tools/sqlgen/areatrigger.func.php index 407f5c84..7916904e 100644 --- a/setup/tools/sqlgen/areatrigger.func.php +++ b/setup/tools/sqlgen/areatrigger.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'areatrigger'; - protected $tblDependancyTC = ['areatrigger_involvedrelation', 'areatrigger_scripts', 'areatrigger_tavern', 'areatrigger_teleport', 'quest_template', 'quest_template_addon']; + protected $tblDependencyTC = ['areatrigger_involvedrelation', 'areatrigger_scripts', 'areatrigger_tavern', 'areatrigger_teleport', 'quest_template', 'quest_template_addon']; protected $dbcSourceFiles = ['areatrigger', 'worldmaparea', 'dungeonmap']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/creature.func.php b/setup/tools/sqlgen/creature.func.php index 4da6ccf1..7cc7bc04 100644 --- a/setup/tools/sqlgen/creature.func.php +++ b/setup/tools/sqlgen/creature.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'creature'; - protected $tblDependancyTC = ['creature_template', 'creature_template_locale', 'creature_template_resistance', 'creature_template_spell', 'creature_classlevelstats', 'instance_encounters']; + protected $tblDependencyTC = ['creature_template', 'creature_template_locale', 'creature_template_resistance', 'creature_template_spell', 'creature_classlevelstats', 'instance_encounters']; protected $dbcSourceFiles = ['creaturedisplayinfo', 'creaturedisplayinfoextra']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/currencies.func.php b/setup/tools/sqlgen/currencies.func.php index e1c1b68d..b62bb729 100644 --- a/setup/tools/sqlgen/currencies.func.php +++ b/setup/tools/sqlgen/currencies.func.php @@ -13,8 +13,8 @@ SqlGen::register(new class extends SetupScript protected $command = 'currencies'; - protected $tblDependancyAowow = ['icons']; - protected $tblDependancyTC = ['item_template', 'item_template_locale']; + protected $tblDependencyAowow = ['icons']; + protected $tblDependencyTC = ['item_template', 'item_template_locale']; protected $dbcSourceFiles = ['itemdisplayinfo', 'currencytypes']; // hide test tokens and move them to unused diff --git a/setup/tools/sqlgen/events.func.php b/setup/tools/sqlgen/events.func.php index ab0c8a3d..4290381a 100644 --- a/setup/tools/sqlgen/events.func.php +++ b/setup/tools/sqlgen/events.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'events'; - protected $tblDependancyTC = ['game_event', 'game_event_prerequisite']; + protected $tblDependencyTC = ['game_event', 'game_event_prerequisite']; public function generate(array $ids = []) : bool { diff --git a/setup/tools/sqlgen/glyphproperties.func.php b/setup/tools/sqlgen/glyphproperties.func.php index 69a4103f..c46d30d9 100644 --- a/setup/tools/sqlgen/glyphproperties.func.php +++ b/setup/tools/sqlgen/glyphproperties.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'glyphproperties'; - protected $tblDependancyAowow = ['icons']; + protected $tblDependencyAowow = ['icons']; protected $dbcSourceFiles = ['glyphproperties', 'spellicon']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/item_stats.func.php b/setup/tools/sqlgen/item_stats.func.php index b14dc3dd..ba2b53a8 100644 --- a/setup/tools/sqlgen/item_stats.func.php +++ b/setup/tools/sqlgen/item_stats.func.php @@ -132,7 +132,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'item_stats'; // and enchantment stats - protected $tblDependancyAowow = ['items', 'spell']; + protected $tblDependencyAowow = ['items', 'spell']; protected $dbcSourceFiles = ['spellitemenchantment']; private function enchantment_stats() : array diff --git a/setup/tools/sqlgen/itemenchantment.func.php b/setup/tools/sqlgen/itemenchantment.func.php index a36d9ebf..14560bd2 100644 --- a/setup/tools/sqlgen/itemenchantment.func.php +++ b/setup/tools/sqlgen/itemenchantment.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'itemenchantment'; - protected $tblDependancyTC = ['spell_enchant_proc_data']; + protected $tblDependencyTC = ['spell_enchant_proc_data']; protected $dbcSourceFiles = ['spellitemenchantment']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/items.func.php b/setup/tools/sqlgen/items.func.php index aff091e6..9ede7368 100644 --- a/setup/tools/sqlgen/items.func.php +++ b/setup/tools/sqlgen/items.func.php @@ -13,8 +13,8 @@ SqlGen::register(new class extends SetupScript protected $command = 'items'; - protected $tblDependancyAowow = ['icons']; - protected $tblDependancyTC = ['item_template', 'item_template_locale', 'spell_group', 'game_event']; + protected $tblDependencyAowow = ['icons']; + protected $tblDependencyTC = ['item_template', 'item_template_locale', 'spell_group', 'game_event']; protected $dbcSourceFiles = ['gemproperties', 'itemdisplayinfo', 'spell', 'glyphproperties', 'durabilityquality', 'durabilitycosts']; private $customData = array( diff --git a/setup/tools/sqlgen/itemset.func.php b/setup/tools/sqlgen/itemset.func.php index 07dfc1fb..7e1aae3b 100644 --- a/setup/tools/sqlgen/itemset.func.php +++ b/setup/tools/sqlgen/itemset.func.php @@ -19,8 +19,8 @@ SqlGen::register(new class extends SetupScript protected $command = 'itemset'; - protected $tblDependancyAowow = ['spell']; - protected $tblDependancyTC = ['item_template', 'game_event']; + protected $tblDependencyAowow = ['spell']; + protected $tblDependencyTC = ['item_template', 'game_event']; protected $dbcSourceFiles = ['itemset']; private $customData = array( diff --git a/setup/tools/sqlgen/objects.func.php b/setup/tools/sqlgen/objects.func.php index 6d6b4746..0e6012bd 100644 --- a/setup/tools/sqlgen/objects.func.php +++ b/setup/tools/sqlgen/objects.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'objects'; - protected $tblDependancyTC = ['gameobject_template', 'gameobject_template_locale', 'gameobject_questitem']; + protected $tblDependencyTC = ['gameobject_template', 'gameobject_template_locale', 'gameobject_questitem']; protected $dbcSourceFiles = ['lock']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/pet.func.php b/setup/tools/sqlgen/pet.func.php index 199b3437..fd620cdf 100644 --- a/setup/tools/sqlgen/pet.func.php +++ b/setup/tools/sqlgen/pet.func.php @@ -11,8 +11,8 @@ SqlGen::register(new class extends SetupScript { protected $command = 'pet'; - protected $tblDependancyAowow = ['icons']; - protected $tblDependancyTC = ['creature_template', 'creature']; + protected $tblDependencyAowow = ['icons']; + protected $tblDependencyTC = ['creature_template', 'creature']; protected $dbcSourceFiles = ['talent', 'spell', 'skilllineability', 'creaturefamily']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/quests.func.php b/setup/tools/sqlgen/quests.func.php index 33ef6ce0..dd9e093e 100644 --- a/setup/tools/sqlgen/quests.func.php +++ b/setup/tools/sqlgen/quests.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'quests'; - protected $tblDependancyTC = ['quest_template', 'quest_template_addon', 'quest_template_locale', 'game_event', 'game_event_seasonal_questrelation', 'disables']; + protected $tblDependencyTC = ['quest_template', 'quest_template_addon', 'quest_template_locale', 'game_event', 'game_event_seasonal_questrelation', 'disables']; protected $dbcSourceFiles = ['questxp', 'questfactionreward']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/quests_startend.func.php b/setup/tools/sqlgen/quests_startend.func.php index d807ba97..639158d2 100644 --- a/setup/tools/sqlgen/quests_startend.func.php +++ b/setup/tools/sqlgen/quests_startend.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'quests_startend'; - protected $tblDependancyTC = ['creature_queststarter', 'creature_questender', 'game_event_creature_quest', 'gameobject_queststarter', 'gameobject_questender', 'game_event_gameobject_quest', 'item_template']; + protected $tblDependencyTC = ['creature_queststarter', 'creature_questender', 'game_event_creature_quest', 'gameobject_queststarter', 'gameobject_questender', 'game_event_gameobject_quest', 'item_template']; public function generate(array $ids = []) : bool { diff --git a/setup/tools/sqlgen/skillline.func.php b/setup/tools/sqlgen/skillline.func.php index b6728acc..a316feb2 100644 --- a/setup/tools/sqlgen/skillline.func.php +++ b/setup/tools/sqlgen/skillline.func.php @@ -13,7 +13,7 @@ SqlGen::register(new class extends SetupScript protected $command = 'skillline'; - protected $tblDependancyAowow = ['icons']; + protected $tblDependencyAowow = ['icons']; protected $dbcSourceFiles = ['skillline', 'spell', 'skilllineability']; private $customData = array( diff --git a/setup/tools/sqlgen/source.func.php b/setup/tools/sqlgen/source.func.php index 198d5875..ccfb9dd1 100644 --- a/setup/tools/sqlgen/source.func.php +++ b/setup/tools/sqlgen/source.func.php @@ -11,8 +11,8 @@ SqlGen::register(new class extends SetupScript { protected $command = 'source'; - protected $tblDependancyAowow = ['spell', 'achievement']; - protected $tblDependancyTC = ['playercreateinfo_skills', 'playercreateinfo_item', 'skill_discovery_template', 'achievement_reward', 'skill_perfect_item_template', 'item_template', 'gameobject_template', 'quest_template', 'quest_template_addon', 'creature_template', 'creature', 'trainer_spell', 'npc_vendor', 'game_event_npc_vendor', 'reference_loot_template', 'item_loot_template', 'creature_loot_template', 'gameobject_loot_template', 'mail_loot_template', 'disenchant_loot_template', 'fishing_loot_template', 'skinning_loot_template', 'milling_loot_template', 'prospecting_loot_template', 'pickpocketing_loot_template']; + protected $tblDependencyAowow = ['spell', 'achievement']; + protected $tblDependencyTC = ['playercreateinfo_skills', 'playercreateinfo_item', 'skill_discovery_template', 'achievement_reward', 'skill_perfect_item_template', 'item_template', 'gameobject_template', 'quest_template', 'quest_template_addon', 'creature_template', 'creature', 'trainer_spell', 'npc_vendor', 'game_event_npc_vendor', 'reference_loot_template', 'item_loot_template', 'creature_loot_template', 'gameobject_loot_template', 'mail_loot_template', 'disenchant_loot_template', 'fishing_loot_template', 'skinning_loot_template', 'milling_loot_template', 'prospecting_loot_template', 'pickpocketing_loot_template']; protected $dbcSourceFiles = ['charstartoutfit', 'talent', 'spell', 'skilllineability', 'itemextendedcost', 'lock']; private function queryfy(array $data, string $query) : string diff --git a/setup/tools/sqlgen/spawns.func.php b/setup/tools/sqlgen/spawns.func.php index f850a2d4..e301db19 100644 --- a/setup/tools/sqlgen/spawns.func.php +++ b/setup/tools/sqlgen/spawns.func.php @@ -13,7 +13,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'spawns'; // and waypoints - protected $tblDependancyTC = ['creature', 'creature_addon', 'gameobject', 'gameobject_template', 'vehicle_accessory', 'vehicle_accessory_template', 'script_waypoint', 'waypoints', 'waypoint_data']; + protected $tblDependencyTC = ['creature', 'creature_addon', 'gameobject', 'gameobject_template', 'vehicle_accessory', 'vehicle_accessory_template', 'script_waypoint', 'waypoints', 'waypoint_data']; protected $dbcSourceFiles = ['worldmaparea', 'map', 'dungeonmap', 'taxipathnode', 'soundemitters', 'areatrigger', 'areatable']; private $querys = array( diff --git a/setup/tools/sqlgen/spell.func.php b/setup/tools/sqlgen/spell.func.php index fcbe44d2..0a309b8c 100644 --- a/setup/tools/sqlgen/spell.func.php +++ b/setup/tools/sqlgen/spell.func.php @@ -11,8 +11,8 @@ SqlGen::register(new class extends SetupScript { protected $command = 'spell'; - protected $tblDependancyAowow = ['icons']; - protected $tblDependancyTC = ['item_template', 'creature_template', 'creature_template_addon', 'smart_scripts', 'trainer_spell', 'disables', 'spell_ranks', 'spell_dbc', 'skill_discovery_template']; + protected $tblDependencyAowow = ['icons']; + protected $tblDependencyTC = ['item_template', 'creature_template', 'creature_template_addon', 'smart_scripts', 'trainer_spell', 'disables', 'spell_ranks', 'spell_dbc', 'skill_discovery_template']; protected $dbcSourceFiles = ['spell', 'spellradius', 'spellduration', 'spellrunecost', 'spellcasttimes', 'skillline', 'skilllineability', 'skillraceclassinfo', 'talent', 'talenttab', 'glyphproperties', 'spellicon']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/spelldifficulty.func.php b/setup/tools/sqlgen/spelldifficulty.func.php index 1efb15ed..24ed2315 100644 --- a/setup/tools/sqlgen/spelldifficulty.func.php +++ b/setup/tools/sqlgen/spelldifficulty.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'spelldifficulty'; - protected $tblDependancyTC = ['spelldifficulty_dbc']; + protected $tblDependencyTC = ['spelldifficulty_dbc']; protected $dbcSourceFiles = ['spelldifficulty']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/taxi.func.php b/setup/tools/sqlgen/taxi.func.php index 022b7b10..788a0afe 100644 --- a/setup/tools/sqlgen/taxi.func.php +++ b/setup/tools/sqlgen/taxi.func.php @@ -11,7 +11,7 @@ SqlGen::register(new class extends SetupScript { protected $command = 'taxi'; // path & nodes - protected $tblDependancyTC = ['creature', 'creature_template']; + protected $tblDependencyTC = ['creature', 'creature_template']; protected $dbcSourceFiles = ['taxipath', 'taxinodes', 'worldmaparea', 'worldmaptransforms', 'factiontemplate']; public function generate(array $ids = []) : bool diff --git a/setup/tools/sqlgen/titles.func.php b/setup/tools/sqlgen/titles.func.php index 07e52cec..23b6ca78 100644 --- a/setup/tools/sqlgen/titles.func.php +++ b/setup/tools/sqlgen/titles.func.php @@ -13,7 +13,7 @@ SqlGen::register(new class extends SetupScript protected $command = 'titles'; - protected $tblDependancyTC = ['quest_template', 'game_event_seasonal_questrelation', 'game_event', 'achievement_reward']; + protected $tblDependencyTC = ['quest_template', 'game_event_seasonal_questrelation', 'game_event', 'achievement_reward']; protected $dbcSourceFiles = ['chartitles']; private $customData = array( diff --git a/setup/tools/sqlgen/zones.func.php b/setup/tools/sqlgen/zones.func.php index 068cbc99..b21cd536 100644 --- a/setup/tools/sqlgen/zones.func.php +++ b/setup/tools/sqlgen/zones.func.php @@ -13,7 +13,7 @@ SqlGen::register(new class extends SetupScript protected $command = 'zones'; - protected $tblDependancyTC = ['access_requirement']; + protected $tblDependencyTC = ['access_requirement']; protected $dbcSourceFiles = ['worldmaptransforms', 'worldmaparea', 'map', 'mapdifficulty', 'areatable', 'lfgdungeons', 'battlemasterlist']; private $customData = array(