From 398b93e9a734dd44a03379b557a716cfbdf25b36 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Mon, 27 Jan 2025 07:47:19 +0100 Subject: [PATCH] Locale * detatch from User and Util and move to its own enum class * added definitions for all locales the 12340 client could in theory have * this is incompatble with the Intl extension * version bump and php requirement bump --- README.md | 2 +- includes/ajaxHandler/account.class.php | 14 +- includes/ajaxHandler/comment.class.php | 2 +- includes/ajaxHandler/data.class.php | 10 +- includes/ajaxHandler/locale.class.php | 9 +- includes/ajaxHandler/profile.class.php | 18 +- includes/basetype.class.php | 2 +- includes/defines.php | 16 -- includes/game.php | 38 ++- includes/kernel.php | 36 +-- includes/locale.class.php | 209 ++++++++++++++ includes/smartAI.class.php | 24 +- includes/types/achievement.class.php | 4 +- includes/types/creature.class.php | 4 +- includes/types/enchantment.class.php | 16 +- includes/types/gameobject.class.php | 2 +- includes/types/item.class.php | 6 +- includes/types/itemset.class.php | 2 +- includes/types/quest.class.php | 4 +- includes/types/spell.class.php | 10 +- includes/types/title.class.php | 10 +- includes/user.class.php | 299 +++++++++------------ includes/utilities.php | 54 +--- index.php | 4 +- localization/lang.class.php | 86 +++--- pages/account.php | 2 +- pages/achievement.php | 14 +- pages/compare.php | 8 +- pages/currency.php | 12 +- pages/emote.php | 2 +- pages/event.php | 12 +- pages/genericPage.class.php | 56 ++-- pages/guide.php | 8 +- pages/guides.php | 2 +- pages/home.php | 4 +- pages/item.php | 20 +- pages/itemset.php | 12 +- pages/npc.php | 12 +- pages/object.php | 10 +- pages/profile.php | 18 +- pages/quest.php | 12 +- pages/search.php | 20 +- pages/spell.php | 20 +- pages/utility.php | 4 +- pages/zone.php | 4 +- setup/tools/CLISetup.class.php | 75 +++--- setup/tools/clisetup/account.us.php | 17 +- setup/tools/clisetup/dbconfig.us.php | 2 +- setup/tools/dbc.class.php | 38 +-- setup/tools/filegen/enchants.ss.php | 31 ++- setup/tools/filegen/gems.ss.php | 31 ++- setup/tools/filegen/glyphs.ss.php | 35 ++- setup/tools/filegen/img-artwork.ss.php | 2 +- setup/tools/filegen/img-maps.ss.php | 74 ++--- setup/tools/filegen/itemsets.ss.php | 9 +- setup/tools/filegen/locales.ss.php | 92 ++++--- setup/tools/filegen/pets.ss.php | 39 +-- setup/tools/filegen/profiler.ss.php | 81 +++--- setup/tools/filegen/realmmenu.ss.php | 3 +- setup/tools/filegen/simpleimg.ss.php | 22 +- setup/tools/filegen/soundfiles.ss.php | 36 +-- setup/tools/filegen/talentcalc.ss.php | 28 +- setup/tools/filegen/templates/locale.js.in | 4 +- setup/tools/setupScript.class.php | 64 ++--- setup/tools/sqlgen/achievement.ss.php | 14 +- setup/tools/sqlgen/emotes.ss.php | 26 +- setup/tools/sqlgen/itemset.ss.php | 60 ++--- template/bricks/contribute.tpl.php | 2 +- template/bricks/pageTemplate.tpl.php | 5 +- template/pages/home.tpl.php | 4 +- template/pages/itemset.tpl.php | 2 +- template/pages/screenshot.tpl.php | 2 +- 72 files changed, 1007 insertions(+), 924 deletions(-) create mode 100644 includes/locale.class.php diff --git a/README.md b/README.md index f8b8ccd5..8d7cc99c 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Also, this project is not meant to be used for commercial puposes of any kind! ## Requirements -+ Webserver running PHP ≥ 8.0 including extensions: ++ Webserver running PHP ≥ 8.2 including extensions: + [SimpleXML](https://www.php.net/manual/en/book.simplexml.php) + [GD](https://www.php.net/manual/en/book.image) + [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php) diff --git a/includes/ajaxHandler/account.class.php b/includes/ajaxHandler/account.class.php index c6ad3ce3..f887f165 100644 --- a/includes/ajaxHandler/account.class.php +++ b/includes/ajaxHandler/account.class.php @@ -20,17 +20,11 @@ class AjaxAccount extends AjaxHandler 'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT], // 'sessionKey' => ['filter' => FILTER_SANITIZE_NUMBER_INT] ); - protected $_get = array( - 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale'] - ); public function __construct(array $params) { parent::__construct($params); - if (is_numeric($this->_get['locale'])) - User::useLocale($this->_get['locale']); - if (!$this->params || !User::$id) return; @@ -60,12 +54,12 @@ class AjaxAccount extends AjaxHandler // we don't get signaled whether an id should be added to or removed from either includes or excludes // so we throw everything into one table and toggle the mode if its already in here - $includes = DB::Aowow()->selectCol('SELECT typeId FROM ?_profiler_excludes WHERE type = ?d AND typeId IN (?a)', $type, $ids); + $includes = DB::Aowow()->selectCol('SELECT `typeId` FROM ?_profiler_excludes WHERE `type` = ?d AND `typeId` IN (?a)', $type, $ids); foreach ($ids as $typeId) - DB::Aowow()->query('INSERT INTO ?_account_excludes (`userId`, `type`, `typeId`, `mode`) VALUES (?a) ON DUPLICATE KEY UPDATE mode = (mode ^ 0x3)', array( - User::$id, $type, $typeId, in_array($typeId, $includes) ? 2 : 1 - )); + DB::Aowow()->query('INSERT INTO ?_account_excludes (`userId`, `type`, `typeId`, `mode`) VALUES (?a) ON DUPLICATE KEY UPDATE `mode` = (`mode` ^ 0x3)', + [User::$id, $type, $typeId, in_array($typeId, $includes) ? 2 : 1] + ); return; } diff --git a/includes/ajaxHandler/comment.class.php b/includes/ajaxHandler/comment.class.php index 9fbf2b11..12bf766e 100644 --- a/includes/ajaxHandler/comment.class.php +++ b/includes/ajaxHandler/comment.class.php @@ -248,7 +248,7 @@ class AjaxComment extends AjaxHandler if ($this->_get['rating'] < 0) $val *= -1; - if (User::getCurDailyVotes() <= 0) + if (User::getCurrentDailyVotes() <= 0) return Util::toJSON(['error' => 1, 'message' => Lang::main('tooManyVotes')]); else if (!$target || $val != $this->_get['rating']) return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]); diff --git a/includes/ajaxHandler/data.class.php b/includes/ajaxHandler/data.class.php index bc1f8adc..ec57e1ea 100644 --- a/includes/ajaxHandler/data.class.php +++ b/includes/ajaxHandler/data.class.php @@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION')) class AjaxData extends AjaxHandler { protected $_get = array( - 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale' ], + 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFrom' ], 't' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], 'catg' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], 'skill' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkSkill' ], @@ -18,8 +18,8 @@ class AjaxData extends AjaxHandler { parent::__construct($params); - if (is_numeric($this->_get['locale'])) - User::useLocale($this->_get['locale']); + if ($this->_get['locale']?->validate()) + Lang::load($this->_get['locale']); // always this one $this->handler = 'handleData'; @@ -103,7 +103,7 @@ class AjaxData extends AjaxHandler case 'pets': case 'zones': if (!Util::loadStaticFile($set, $result, true) && Cfg::get('DEBUG')) - $result .= "alert('could not fetch static data: ".$set." for locale: ".User::$localeString."');"; + $result .= "alert('could not fetch static data: ".$set." for locale: ".Lang::getLocale()->json()."');"; $result .= "\n\n"; break; @@ -118,7 +118,7 @@ class AjaxData extends AjaxHandler protected static function checkSkill(string $val) : array { - return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val)); + return array_intersect(array_merge(SKILLS_TRADE_PRIMARY, [SKILL_FIRST_AID, SKILL_COOKING, SKILL_FISHING]), explode(',', $val)); } protected static function checkCallback(string $val) : bool diff --git a/includes/ajaxHandler/locale.class.php b/includes/ajaxHandler/locale.class.php index b6c64d22..e89fb33a 100644 --- a/includes/ajaxHandler/locale.class.php +++ b/includes/ajaxHandler/locale.class.php @@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION')) class AjaxLocale extends AjaxHandler { protected $_get = array( - 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale'] + 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFrom'] ); public function __construct(array $params) @@ -23,8 +23,11 @@ class AjaxLocale extends AjaxHandler */ protected function handleLocale() : string { - User::setLocale($this->_get['locale']); - User::save(); + if ($this->_get['locale']?->validate()) + { + User::$preferedLoc = $this->_get['locale']; + User::save(true); + } return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '.'; } diff --git a/includes/ajaxHandler/profile.class.php b/includes/ajaxHandler/profile.class.php index 4e90a835..00aa72ce 100644 --- a/includes/ajaxHandler/profile.class.php +++ b/includes/ajaxHandler/profile.class.php @@ -654,10 +654,10 @@ class AjaxProfile extends AjaxHandler { // get and apply inventory $gItems[$iId] = array( - 'name_'.User::$localeString => $phItems->getField('name', true), - 'quality' => $phItems->getField('quality'), - 'icon' => $phItems->getField('iconString'), - 'jsonequip' => $data[$iId] + 'name_'.Lang::getLocale()->json() => $phItems->getField('name', true), + 'quality' => $phItems->getField('quality'), + 'icon' => $phItems->getField('iconString'), + 'jsonequip' => $data[$iId] ); $profile['inventory'][$slot] = [$iId, 0, 0, 0, 0, 0, 0, 0]; @@ -682,10 +682,10 @@ class AjaxProfile extends AjaxHandler { // get and apply inventory $gItems[$i['item']] = array( - 'name_'.User::$localeString => $itemz->getField('name', true), - 'quality' => $itemz->getField('quality'), - 'icon' => $itemz->getField('iconString'), - 'jsonequip' => $data[$i['item']] + 'name_'.Lang::getLocale()->json() => $itemz->getField('name', true), + 'quality' => $itemz->getField('quality'), + 'icon' => $itemz->getField('iconString'), + 'jsonequip' => $data[$i['item']] ); $profile['inventory'][$i['slot']] = [$i['item'], $i['subItem'], $i['permEnchant'], $i['tempEnchant'], $i['gem1'], $i['gem2'], $i['gem3'], $i['gem4']]; } @@ -719,7 +719,7 @@ class AjaxProfile extends AjaxHandler // } // } - // $buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', modifier:".Util::toJSON($mods)."});\n"; + // $buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', callback:".Util::toJSON($mods)."});\n"; // } // $buff .= "\n"; // } diff --git a/includes/basetype.class.php b/includes/basetype.class.php index e9889fb7..5f65f5bf 100644 --- a/includes/basetype.class.php +++ b/includes/basetype.class.php @@ -1479,7 +1479,7 @@ abstract class Filter private function genericString($field, $value, $strFlags) { if ($strFlags & STR_LOCALIZED) - $field .= '_loc'.User::$localeId; + $field .= '_loc'.Lang::getLocale()->value; return $this->modularizeString([$field], (string)$value, $strFlags & STR_MATCH_EXACT, $strFlags & STR_ALLOW_SHORT); } diff --git a/includes/defines.php b/includes/defines.php index 2940324b..00f21947 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -139,21 +139,6 @@ define('U_GROUP_MODERATOR', (U_GROUP_ADMIN|U_GROUP_MOD|U_GROUP_B define('U_GROUP_COMMENTS_MODERATOR', (U_GROUP_MODERATOR|U_GROUP_LOCALIZER)); define('U_GROUP_PREMIUM_PERMISSIONS', (U_GROUP_PREMIUM|U_GROUP_STAFF|U_GROUP_VIP)); -// Locales -define('LOCALE_EN', 0); // enGB, enUS -define('LOCALE_KR', 1); // koKR [aowwo unused] -define('LOCALE_FR', 2); // frFR -define('LOCALE_DE', 3); // deDE -define('LOCALE_CN', 4); // zhCN, enCN -define('LOCALE_TW', 5); // zhTW, enTW [aowow unused] -define('LOCALE_ES', 6); // esES -define('LOCALE_MX', 7); // esMX [aowow unused] -define('LOCALE_RU', 8); // ruRU -define('LOCALE_JP', 9); // jaJP [aowow & 335 unused] -define('LOCALE_PT', 10); // ptPT, ptBR [aowow unused] -define('LOCALE_IT', 11); // itIT [aowow & 335 unused] -define('LOCALE_MASK_ALL', 0b000101011101); - // red buttons on the top of the page define('BUTTON_WOWHEAD', 0); define('BUTTON_UPGRADE', 1); @@ -330,7 +315,6 @@ define('GUIDE_CU_NO_RATING', 0x200); define('MAX_LEVEL', 80); define('MAX_SKILL', 450); -define('MAX_LOCALES', 16); // technical limitation, 6 in use here define('WOW_BUILD', 12340); // Loot handles diff --git a/includes/game.php b/includes/game.php index 30a57b0c..a856389e 100644 --- a/includes/game.php +++ b/includes/game.php @@ -220,7 +220,7 @@ class Game $pages = []; while ($ptId) { - if ($row = DB::World()->selectRow('SELECT ptl.Text AS Text_loc?d, pt.* FROM page_text pt LEFT JOIN page_text_locale ptl ON pt.ID = ptl.ID AND locale = ? WHERE pt.ID = ?d', User::$localeId, User::$localeString, $ptId)) + if ($row = DB::World()->selectRow('SELECT ptl.Text AS Text_loc?d, pt.* FROM page_text pt LEFT JOIN page_text_locale ptl ON pt.ID = ptl.ID AND locale = ? WHERE pt.ID = ?d', Lang::getLocale()->value, Lang::getLocale()->json(), $ptId)) { $ptId = $row['NextPageID']; $pages[] = Util::parseHtmlText(Util::localizedString($row, 'Text')); @@ -392,28 +392,20 @@ class Game $quotes = []; $soundIds = []; - $quoteSrc = DB::World()->select(' - SELECT - ct.GroupID AS ARRAY_KEY, ct.ID as ARRAY_KEY2, - ct.`Type` AS `talkType`, - ct.TextRange AS `range`, - IFNULL(bct.`LanguageID`, ct.`Language`) AS lang, - IFNULL(NULLIF(bct.Text, ""), IFNULL(NULLIF(bct.Text1, ""), IFNULL(ct.`Text`, ""))) AS text_loc0, - {IFNULL(NULLIF(bctl.Text, ""), IFNULL(NULLIF(bctl.Text1, ""), IFNULL(ctl.Text, ""))) AS text_loc?d,} - IF(bct.SoundEntriesID > 0, bct.SoundEntriesID, ct.Sound) AS soundId - FROM - creature_text ct - {LEFT JOIN - creature_text_locale ctl ON ct.CreatureID = ctl.CreatureID AND ct.GroupID = ctl.GroupID AND ct.ID = ctl.ID AND ctl.Locale = ?} - LEFT JOIN - broadcast_text bct ON ct.BroadcastTextId = bct.ID - {LEFT JOIN - broadcast_text_locale bctl ON ct.BroadcastTextId = bctl.ID AND bctl.locale = ?} - WHERE - ct.CreatureID = ?d', - User::$localeId ?: DBSIMPLE_SKIP, - User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP, - User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP, + $quoteSrc = DB::World()->select( + 'SELECT ct.`GroupID` AS ARRAY_KEY, ct.`ID` AS ARRAY_KEY2, ct.`Type` AS "talkType", ct.TextRange AS "range", + IFNULL(bct.`LanguageID`, ct.`Language`) AS "lang", + IFNULL(NULLIF(bct.`Text`, ""), IFNULL(NULLIF(bct.`Text1`, ""), IFNULL(ct.`Text`, ""))) AS "text_loc0", + { IFNULL(NULLIF(bctl.`Text`, ""), IFNULL(NULLIF(bctl.`Text1`, ""), IFNULL(ctl.`Text`, ""))) AS text_loc?d, } + IF(bct.`SoundEntriesID` > 0, bct.`SoundEntriesID`, ct.`Sound`) AS "soundId" + FROM creature_text ct + { LEFT JOIN creature_text_locale ctl ON ct.`CreatureID` = ctl.`CreatureID` AND ct.`GroupID` = ctl.`GroupID` AND ct.`ID` = ctl.`ID` AND ctl.`Locale` = ? } + LEFT JOIN broadcast_text bct ON ct.`BroadcastTextId` = bct.`ID` + { LEFT JOIN broadcast_text_locale bctl ON ct.`BroadcastTextId` = bctl.`ID` AND bctl.`locale` = ? } + WHERE ct.`CreatureID` = ?d', + Lang::getLocale()->value ?: DBSIMPLE_SKIP, + Lang::getLocale()->value ? Lang::getLocale()->json() : DBSIMPLE_SKIP, + Lang::getLocale()->value ? Lang::getLocale()->json() : DBSIMPLE_SKIP, $creatureId ); diff --git a/includes/kernel.php b/includes/kernel.php index 5a8d5527..72c01fac 100644 --- a/includes/kernel.php +++ b/includes/kernel.php @@ -3,7 +3,7 @@ mb_internal_encoding('UTF-8'); mysqli_report(MYSQLI_REPORT_ERROR); -define('AOWOW_REVISION', 39); +define('AOWOW_REVISION', 40); define('OS_WIN', substr(PHP_OS, 0, 3) == 'WIN'); // OS_WIN as per compile info of php define('CLI', PHP_SAPI === 'cli'); define('CLI_HAS_E', CLI && // WIN10 and later usually support ANSI escape sequences @@ -11,25 +11,30 @@ define('CLI_HAS_E', CLI && // WIN10 and later u $reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'/*, 'gmp'*/]; +$badExt = ['Intl']; // Intl contains its own class Locale. What? Namespaces? Never heard of those! $error = ''; -if ($ext = array_filter($reqExt, function($x) { return !extension_loaded($x); })) +if ($ext = array_filter($reqExt, fn($x) => !extension_loaded($x))) $error .= 'Required Extension '.implode(', ', $ext)." was not found. Please check if it should exist, using \"php -m\"\n\n"; -if (version_compare(PHP_VERSION, '8.0.0') < 0) - $error .= 'PHP Version 8.0 or higher required! Your version is '.PHP_VERSION.".\nCore functions are unavailable!\n"; +if ($ext = array_filter($badExt, fn($x) => extension_loaded($x))) + $error .= 'Loaded Extension '.implode(', ', $ext)." is incompatible and must be disabled.\n\n"; + +if (version_compare(PHP_VERSION, '8.2.0') < 0) + $error .= 'PHP Version 8.2 or higher required! Your version is '.PHP_VERSION.".\nCore functions are unavailable!\n"; if ($error) die(CLI ? strip_tags($error) : $error); require_once 'includes/defines.php'; +require_once 'includes/locale.class.php'; require_once 'includes/stats.class.php'; // Game entity statistics conversion require_once 'includes/libs/DbSimple/Generic.php'; // Libraray: http://en.dklab.ru/lib/DbSimple (using variant: https://github.com/ivan1986/DbSimple/tree/master) require_once 'includes/utilities.php'; // helper functions require_once 'includes/config.class.php'; // Config holder require_once 'includes/game.php'; // game related data & functions -require_once 'includes/profiler.class.php'; -require_once 'includes/user.class.php'; +require_once 'includes/profiler.class.php'; // Profiler feature +require_once 'includes/user.class.php'; // Session handling require_once 'includes/markup.class.php'; // manipulate markup text require_once 'includes/database.class.php'; // wrap DBSimple require_once 'includes/community.class.php'; // handle comments, screenshots and videos @@ -213,6 +218,12 @@ if (!CLI) if (User::init()) User::save(); // save user-variables in session + // hard override locale for this call (should this be here..?) + if (isset($_GET['locale']) && ($loc = Locale::tryFrom($_GET['locale']))) + Lang::load($loc); + else + Lang::load(User::$preferedLoc); + // set up some logging (~10 queries will execute before we init the user and load the config) if (Cfg::get('DEBUG') >= CLI::LOG_INFO && User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN)) { @@ -227,17 +238,6 @@ if (!CLI) DB::Characters($idx)->setLogger(['DB', 'profiler']); } - // hard-override locale for this call (should this be here..?) - // all strings attached.. - if (isset($_GET['locale'])) - { - $loc = intVal($_GET['locale']); - if ($loc <= MAX_LOCALES && $loc >= 0 && (Cfg::get('LOCALES') & (1 << $loc))) - User::useLocale($loc); - } - - Lang::load(User::$localeId); - // parse page-parameters .. sanitize before use! $str = explode('&', $_SERVER['QUERY_STRING'] ?? '', 2)[0]; $_ = explode('=', $str, 2); @@ -245,6 +245,6 @@ if (!CLI) $pageParam = $_[1] ?? ''; } else if (DB::isConnected(DB_AOWOW)) - Lang::load(LOCALE_EN); + Lang::load(Locale::EN); ?> diff --git a/includes/locale.class.php b/includes/locale.class.php new file mode 100644 index 00000000..cc7d08e6 --- /dev/null +++ b/includes/locale.class.php @@ -0,0 +1,209 @@ + 'en', + self::KR => 'kt', + self::FR => 'fr', + self::DE => 'de', + self::CN => 'cn', + self::TW => 'tw', + self::ES => 'es', + self::MX => 'mx', + self::RU => 'ru', + self::JP => 'jp', + self::PT => 'pt', + self::IT => 'it' + }; + } + + public function json() : string // internal usage / json string + { + return match ($this) + { + self::EN => 'enus', + self::KR => 'kokr', + self::FR => 'frfr', + self::DE => 'dede', + self::CN => 'zhcn', + self::TW => 'zhtw', + self::ES => 'eses', + self::MX => 'esmx', + self::RU => 'ruru', + self::JP => 'jajp', + self::PT => 'ptpt', + self::IT => 'itit' + }; + } + + public function title() : string // localized language name + { + return match ($this) + { + self::EN => 'English', + self::KR => '한국어', + self::FR => 'Français', + self::DE => 'Deutsch', + self::CN => '简体中文', + self::TW => '繁體中文', + self::ES => 'Español', + self::MX => 'Mexicano', + self::RU => 'Русский', + self::JP => '日本語', + self::PT => 'Português', + self::IT => 'Italiano' + }; + } + + public function gameDirs() : array // setup data source / wow client locale code + { + return match ($this) + { + self::EN => ['enGB', 'enUS', ''], + self::KR => ['koKR'], + self::FR => ['frFR'], + self::DE => ['deDE'], + self::CN => ['zhCN', 'enCN'], + self::TW => ['zhTW', 'enTW'], + self::ES => ['esES'], + self::MX => ['esMX'], + self::RU => ['ruRU'], + self::JP => ['jaJP'], + self::PT => ['ptPT', 'ptBR'], + self::IT => ['itIT'] + }; + } + + public function httpCode() : array // HTTP_ACCEPT_LANGUAGE + { + return match ($this) + { + self::EN => ['en', 'en-au', 'en-bz', 'en-ca', 'en-ie', 'en-jm', 'en-nz', 'en-ph', 'en-za', 'en-tt', 'en-gb', 'en-us', 'en-zw'], + self::KR => ['ko', 'ko-kp', 'ko-kr'], + self::FR => ['fr', 'fr-be', 'fr-ca', 'fr-fr', 'fr-lu', 'fr-mc', 'fr-ch'], + self::DE => ['de', 'de-at', 'de-de', 'de-li', 'de-lu', 'de-ch'], + self::CN => ['zh', 'zh-hk', 'zh-cn', 'zh-sg'], + self::TW => ['tw', 'zh-tw'], + self::ES => ['es', 'es-ar', 'es-bo', 'es-cl', 'es-co', 'es-cr', 'es-do', 'es-ec', 'es-sv', 'es-gt', 'es-hn', 'es-ni', 'es-pa', 'es-py', 'es-pe', 'es-pr', 'es-es', 'es-uy', 'es-ve'], + self::MX => ['mx', 'es-mx'], + self::RU => ['ru', 'ru-mo'], + self::JP => ['ja'], + self::PT => ['pt', 'pt-br'], + self::IT => ['it', 'it-ch'] + }; + } + + public function isLogographic() : bool + { + return $this == Locale::CN || $this == Locale::TW || $this == Locale::KR; + } + + public function validate() : ?self + { + return ($this->maskBit() & self::MASK_ALL & (Cfg::get('LOCALES') ?: 0xFFFF)) ? $this : null; + } + + public function maskBit() : int + { + return (1 << $this->value); + } + + public static function tryFromDomain(string $str) : ?self + { + foreach (self::cases() as $l) + if ($l->validate() && $str == $l->domain()) + return $l; + + return null; + } + + public static function tryFromHttpAcceptLanguage(string $httpAccept) : ?self + { + if (!$httpAccept) + return null; + + $available = []; + + // e.g.: de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 + foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $loc) + if (preg_match('/([a-z\-]+)(?:\s*;\s*q\s*=\s*([\.\d]+))?/ui', $loc, $m, PREG_UNMATCHED_AS_NULL)) + $available[Util::lower($m[1])] = floatVal($m[2] ?? 1); // no quality set: assume 100% + + arsort($available, SORT_NUMERIC); // highest quality on top + + foreach ($available as $code => $_) + foreach (self::cases() as $l) + if ($l->validate() && in_array($code, $l->httpCode())) + return $l; + + return null; + } + + public static function getFallback() : self + { + foreach (Locale::cases() as $l) + if ($l->validate()) + return $l; + + // wow, you really fucked up your config mate! + trigger_error('Locale::getFallback - there are no valid locales', E_USER_ERROR); + return self::EN; + } +} + + +/* The shape of things to come */ +class LocString +{ + private WeakMap $store; + + public function __construct(array $data, string $key = 'name', ?callable $callback = null) + { + $this->store = new WeakMap(); + + $callback ??= fn($x) => $x; + + if (!array_filter($data, fn($v, $k) => $v && strstr($k, $key.'_loc'), ARRAY_FILTER_USE_BOTH)) + trigger_error('LocString - is entrirely empty', E_USER_WARNING); + + foreach (Locale::cases() as $l) + $this->store[$l] = (string)$callback($data[$key.'_loc'.$l->value] ?? ''); + } + + public function __toString() : string + { + if ($str = $this->store[Lang::getLocale()]) + return $str; + + foreach (Locale::cases() as $l) // desired loc not set, use any other + if ($str = $this->store[$l]) + return Cfg::get('DEBUG') ? '['.$str.']' : $str; + + return Cfg::get('DEBUG') ? '[LOCSTRING]' : ''; + } +} + +?> diff --git a/includes/smartAI.class.php b/includes/smartAI.class.php index 67b7649e..40ecd7ff 100644 --- a/includes/smartAI.class.php +++ b/includes/smartAI.class.php @@ -918,16 +918,18 @@ class SmartAI $this->jsGlobals[Type::NPC][] = $e['param'][1]; break; case SAI_EVENT_LINK: // 61 - Used to link together multiple events as a chain of events. - $e['param'][10] = LANG::concat(DB::World()->selectCol('SELECT CONCAT("#[b]", id, "[/b]") FROM smart_scripts WHERE link = ?d AND entryorguid = ?d AND source_type = ?d', $this->itr['id'], $this->entry, $this->srcType), false); + if ($links = DB::World()->selectCol('SELECT `id` FROM smart_scripts WHERE `link` = ?d AND `entryorguid` = ?d AND `source_type` = ?d', $this->itr['id'], $this->entry, $this->srcType)) + $e['param'][10] = LANG::concat($links, false, fn($x) => "#[b]".$x."[/b]"); break; case SAI_EVENT_GOSSIP_SELECT: // 62 - On gossip clicked (gossip_menu_option335). - $gmo = DB::World()->selectRow('SELECT gmo.OptionText AS text_loc0 {, gmol.OptionText AS text_loc?d} - FROM gossip_menu_option gmo LEFT JOIN gossip_menu_option_locale gmol ON gmo.MenuID = gmol.MenuID AND gmo.OptionID = gmol.OptionID AND gmol.Locale = ?d - WHERE gmo.MenuId = ?d AND gmo.OptionID = ?d', - User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP, - User::$localeId, - $e['param'][0], - $e['param'][1] + $gmo = DB::World()->selectRow( + 'SELECT gmo.`OptionText` AS "text_loc0" {, gmol.`OptionText` AS text_loc?d } + FROM gossip_menu_option gmo + LEFT JOIN gossip_menu_option_locale gmol ON gmo.`MenuID` = gmol.`MenuID` AND gmo.`OptionID` = gmol.`OptionID` AND gmol.`Locale` = ?d + WHERE gmo.`MenuId` = ?d AND gmo.`OptionID` = ?d', + Lang::getLocale() != Locale::EN ? Lang::getLocale()->json() : DBSIMPLE_SKIP, + Lang::getLocale()->value, + $e['param'][0], $e['param'][1] ); if ($gmo) @@ -941,11 +943,11 @@ class SmartAI break; case SAI_EVENT_DISTANCE_CREATURE: // 75 - On creature guid OR any instance of creature entry is within distance. if ($e['param'][0]) - $e['param'][10] = DB::World()->selectCell('SELECT id FROM creature WHERE guid = ?d', $e['param'][0]); + $e['param'][10] = DB::World()->selectCell('SELECT `id` FROM creature WHERE `guid` = ?d', $e['param'][0]); // do not break; case SAI_EVENT_DISTANCE_GAMEOBJECT: // 76 - On gameobject guid OR any instance of gameobject entry is within distance. if ($e['param'][0] && !$e['param'][10]) - $e['param'][10] = DB::World()->selectCell('SELECT id FROM gameobject WHERE guid = ?d', $e['param'][0]); + $e['param'][10] = DB::World()->selectCell('SELECT `id` FROM gameobject WHERE `guid` = ?d', $e['param'][0]); else if ($e['param'][1]) $e['param'][10] = $e['param'][1]; else if (!$e['param'][10]) @@ -1244,7 +1246,7 @@ class SmartAI JOIN ?_taxinodes tn1 ON tp.startNodeId = tn1.id JOIN ?_taxinodes tn2 ON tp.endNodeId = tn2.id WHERE tp.id = ?d', - User::$localeId, User::$localeId, User::$localeId, User::$localeId, $a['param'][0] + Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, $a['param'][0] ); $a['param'][6] = Util::localizedString($nodes, 'start'); $a['param'][7] = Util::localizedString($nodes, 'end'); diff --git a/includes/types/achievement.class.php b/includes/types/achievement.class.php index c349888f..329d9b33 100644 --- a/includes/types/achievement.class.php +++ b/includes/types/achievement.class.php @@ -343,9 +343,9 @@ class AchievementListFilter extends Filter { $_ = []; if (isset($_v['ex']) && $_v['ex'] == 'on') - $_ = $this->modularizeString(['name_loc'.User::$localeId, 'reward_loc'.User::$localeId, 'description_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'reward_loc'.Lang::getLocale()->value, 'description_loc'.Lang::getLocale()->value]); else - $_ = $this->modularizeString(['name_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]); if ($_) $parts[] = $_; diff --git a/includes/types/creature.class.php b/includes/types/creature.class.php index 909256a1..63ff9126 100644 --- a/includes/types/creature.class.php +++ b/includes/types/creature.class.php @@ -353,9 +353,9 @@ class CreatureListFilter extends Filter { $_ = []; if (isset($_v['ex']) && $_v['ex'] == 'on') - $_ = $this->modularizeString(['name_loc'.User::$localeId, 'subname_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'subname_loc'.Lang::getLocale()->value]); else - $_ = $this->modularizeString(['name_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]); if ($_) $parts[] = $_; diff --git a/includes/types/enchantment.class.php b/includes/types/enchantment.class.php index 7080ab9b..aaad7e95 100644 --- a/includes/types/enchantment.class.php +++ b/includes/types/enchantment.class.php @@ -13,7 +13,7 @@ class EnchantmentList extends BaseType public static $dataTable = '?_itemenchantment'; private $jsonStats = []; - private $relSpells = []; + private SpellList $relSpells; private $triggerIds = []; protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie'; @@ -26,6 +26,8 @@ class EnchantmentList extends BaseType { parent::__construct($conditions, $miscData); + $relSpells = []; + // post processing foreach ($this->iterate() as &$curTpl) { @@ -40,15 +42,15 @@ class EnchantmentList extends BaseType case ENCHANTMENT_TYPE_COMBAT_SPELL: $proc = -$this->getField('ppmRate') ?: ($this->getField('procChance') ?: $this->getField('amount'.$i)); $curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_HIT, $curTpl['charges'], $proc]; - $this->relSpells[] = $curTpl['object'.$i]; + $relSpells[] = $curTpl['object'.$i]; break; case ENCHANTMENT_TYPE_EQUIP_SPELL: $curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_EQUIP, $curTpl['charges'], 0]; - $this->relSpells[] = $curTpl['object'.$i]; + $relSpells[] = $curTpl['object'.$i]; break; case ENCHANTMENT_TYPE_USE_SPELL: $curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_USE, $curTpl['charges'], 0]; - $this->relSpells[] = $curTpl['object'.$i]; + $relSpells[] = $curTpl['object'.$i]; break; } } @@ -56,8 +58,8 @@ class EnchantmentList extends BaseType $this->jsonStats[$this->id] = (new StatsContainer)->fromJson($curTpl, true); } - if ($this->relSpells) - $this->relSpells = new SpellList(array(['id', $this->relSpells])); + if ($relSpells) + $this->relSpells = new SpellList(array(['id', $relSpells])); } // use if you JUST need the name @@ -241,7 +243,7 @@ class EnchantmentListFilter extends Filter //string if (isset($_v['na'])) - if ($_ = $this->modularizeString(['name_loc'.User::$localeId])) + if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value])) $parts[] = $_; // type diff --git a/includes/types/gameobject.class.php b/includes/types/gameobject.class.php index 4802cf26..38bfc97d 100644 --- a/includes/types/gameobject.class.php +++ b/includes/types/gameobject.class.php @@ -180,7 +180,7 @@ class GameObjectListFilter extends Filter // name if (isset($_v['na'])) - if ($_ = $this->modularizeString(['name_loc'.User::$localeId])) + if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value])) $parts[] = $_; return $parts; diff --git a/includes/types/item.class.php b/includes/types/item.class.php index 1b8d2960..5e6e1248 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -1935,7 +1935,7 @@ class ItemListFilter extends Filter 104 => [FILTER_CR_STRING, 'description', STR_LOCALIZED ], // flavortext 105 => [FILTER_CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 1 ], // dropsinnormal [heroicdungeon-any] 106 => [FILTER_CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 2 ], // dropsinheroic [heroicdungeon-any] - 107 => [FILTER_CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.User::$localeId, $cr[2]] + 107 => [FILTER_CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.Lang::getLocale()->value, $cr[2]] 109 => [FILTER_CR_CALLBACK, 'cbArmorBonus', null, null ], // armorbonus [op] [int] 111 => [FILTER_CR_NUMERIC, 'requiredSkillRank', NUM_CAST_INT, true ], // reqskillrank 113 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots @@ -2122,7 +2122,7 @@ class ItemListFilter extends Filter // name if (isset($_v['na'])) - if ($_ = $this->modularizeString(['name_loc'.User::$localeId])) + if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value])) $parts[] = $_; // usable-by (not excluded by requiredClass && armor or weapons match mask from ?_classes) @@ -2277,7 +2277,7 @@ class ItemListFilter extends Filter $n = preg_replace(Filter::PATTERN_NAME, '', $cr[2]); $n = $this->transformString($n, false); - $randIds = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, ABS(`id`) AS `id`, name_loc?d, `name_loc0` FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', User::$localeId, User::$localeId, $n); + $randIds = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, ABS(`id`) AS `id`, name_loc?d, `name_loc0` FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', Lang::getLocale()->value, Lang::getLocale()->value, $n); $tplIds = $randIds ? DB::World()->select('SELECT `entry`, `ench` FROM item_enchantment_template WHERE `ench` IN (?a)', array_column($randIds, 'id')) : []; foreach ($tplIds as &$set) { diff --git a/includes/types/itemset.class.php b/includes/types/itemset.class.php index b89d55f1..2c8255d9 100644 --- a/includes/types/itemset.class.php +++ b/includes/types/itemset.class.php @@ -211,7 +211,7 @@ class ItemsetListFilter extends Filter // name [str] if (isset($_v['na'])) - if ($_ = $this->modularizeString(['name_loc'.User::$localeId])) + if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value])) $parts[] = $_; // quality [enum] diff --git a/includes/types/quest.class.php b/includes/types/quest.class.php index 9566be48..4355e673 100644 --- a/includes/types/quest.class.php +++ b/includes/types/quest.class.php @@ -498,9 +498,9 @@ class QuestListFilter extends Filter { $_ = []; if (isset($_v['ex']) && $_v['ex'] == 'on') - $_ = $this->modularizeString(['name_loc'.User::$localeId, 'objectives_loc'.User::$localeId, 'details_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'objectives_loc'.Lang::getLocale()->value, 'details_loc'.Lang::getLocale()->value]); else - $_ = $this->modularizeString(['name_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]); if ($_) $parts[] = $_; diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index 2d9ce1af..d6ec6e42 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -1436,8 +1436,8 @@ class SpellList extends BaseType $this->charLevel = $level; // step -1: already handled? - if (isset($this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive])) - return $this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive]; + if (isset($this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive])) + return $this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive]; // step 0: get text $data = $this->getField($type, true); @@ -1543,7 +1543,7 @@ class SpellList extends BaseType $data = strtr($data, ["\r" => '', "\n" => '
']); // cache result - $this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive] = [$data, $relSpells, $this->scaling[$this->id]]; + $this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive] = [$data, $relSpells, $this->scaling[$this->id]]; return [$data, $relSpells, $this->scaling[$this->id]]; } @@ -2451,9 +2451,9 @@ class SpellListFilter extends Filter { $_ = []; if (isset($_v['ex']) && $_v['ex'] == 'on') - $_ = $this->modularizeString(['name_loc'.User::$localeId, 'buff_loc'.User::$localeId, 'description_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'buff_loc'.Lang::getLocale()->value, 'description_loc'.Lang::getLocale()->value]); else - $_ = $this->modularizeString(['name_loc'.User::$localeId]); + $_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]); if ($_) $parts[] = $_; diff --git a/includes/types/title.class.php b/includes/types/title.class.php index b1360e5b..88a42843 100644 --- a/includes/types/title.class.php +++ b/includes/types/title.class.php @@ -45,9 +45,13 @@ class TitleList extends BaseType unset($_curTpl['src3']); // shorthand for more generic access - foreach (Util::$localeStrings as $i => $str) - if ($str) - $_curTpl['name_loc'.$i] = trim(str_replace('%s', '', $_curTpl['male_loc'.$i])); + // i don't see it being used anywhere..? + /* + foreach (Locale::cases() as $loc) + if ($loc->validate()) + $_curTpl['name'] = new LocString($_curTpl, 'male', fn($x) => trim(str_replace('%s', '', $x))); + // $_curTpl['name_loc'.$loc->value] = trim(str_replace('%s', '', $_curTpl['male_loc'.$loc->value])); + */ } } diff --git a/includes/user.class.php b/includes/user.class.php index 5686a144..e453797a 100644 --- a/includes/user.class.php +++ b/includes/user.class.php @@ -6,28 +6,34 @@ if (!defined('AOWOW_REVISION')) class User { - public static $id = 0; - public static $displayName = ''; - public static $banStatus = 0x0; // see ACC_BAN_* defines - public static $groups = 0x0; - public static $perms = 0; - public static $localeId = 0; - public static $localeString = 'enus'; - public static $avatar = 'inv_misc_questionmark'; - public static $dailyVotes = 0; + public static int $id = 0; + public static string $displayName = ''; + public static int $banStatus = 0x0; // see ACC_BAN_* defines + public static int $groups = 0x0; + public static int $perms = 0; + public static string $avatar = 'inv_misc_questionmark'; + public static int $dailyVotes = 0; public static $ip = null; - private static $reputation = 0; - private static $dataKey = ''; - private static $expires = false; - private static $passHash = ''; - private static $excludeGroups = 1; - private static $profiles = null; + private static int $reputation = 0; + private static string $dataKey = ''; + private static bool $expires = false; + private static string $passHash = ''; + private static int $excludeGroups = 1; + + public static Locale $preferedLoc; + private static LocalProfileList $profiles; public static function init() { self::setIP(); - self::setLocale(); + + if (isset($_SESSION['locale']) && $_SESSION['locale'] instanceof Locale) + self::$preferedLoc = $_SESSION['locale']->validate() ?? Locale::getFallback(); + else if (!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]) && ($loc = Locale::tryFromHttpAcceptLanguage($_SERVER["HTTP_ACCEPT_LANGUAGE"]))) + self::$preferedLoc = $loc; + else + self::$preferedLoc = Locale::getFallback(); // session have a dataKey to access the JScripts (yes, also the anons) if (empty($_SESSION['dataKey'])) @@ -39,12 +45,12 @@ class User return false; // check IP bans - if ($ipBan = DB::Aowow()->selectRow('SELECT count, unbanDate FROM ?_account_bannedips WHERE ip = ? AND type = 0', self::$ip)) + if ($ipBan = DB::Aowow()->selectRow('SELECT `count`, `unbanDate` FROM ?_account_bannedips WHERE `ip` = ? AND `type` = 0', self::$ip)) { if ($ipBan['count'] > Cfg::get('ACC_FAILED_AUTH_COUNT') && $ipBan['unbanDate'] > time()) return false; else if ($ipBan['unbanDate'] <= time()) - DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE ip = ?', self::$ip); + DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE `ip` = ?', self::$ip); } // try to restore session @@ -55,36 +61,39 @@ class User if (!empty($_SESSION['timeout']) && $_SESSION['timeout'] <= time()) return false; - $query = DB::Aowow()->SelectRow(' - SELECT a.id, a.passHash, a.displayName, a.locale, a.userGroups, a.userPerms, a.allowExpire, BIT_OR(ab.typeMask) AS bans, IFNULL(SUM(r.amount), 0) as reputation, a.avatar, a.dailyVotes, a.excludeGroups + $uData = DB::Aowow()->SelectRow( + 'SELECT a.`id`, a.`passHash`, a.`displayName`, a.`locale`, a.`userGroups`, a.`userPerms`, a.`allowExpire`, BIT_OR(ab.`typeMask`) AS "bans", IFNULL(SUM(r.`amount`), 0) AS "reputation", a.`avatar`, a.`dailyVotes`, a.`excludeGroups` FROM ?_account a - LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP() - LEFT JOIN ?_account_reputation r ON a.id = r.userId - WHERE a.id = ?d - GROUP BY a.id', + LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP() + LEFT JOIN ?_account_reputation r ON a.`id` = r.`userId` + WHERE a.`id` = ?d + GROUP BY a.`id`', $_SESSION['user'] ); - if (!$query) + if (!$uData) return false; + if ($loc = Locale::tryFrom($uData['locale'])) + self::$preferedLoc = $loc; + // password changed, terminate session - if (AUTH_MODE_SELF && $query['passHash'] != $_SESSION['hash']) + if (AUTH_MODE_SELF && $uData['passHash'] != $_SESSION['hash']) { self::destroy(); return false; } - self::$id = intval($query['id']); - self::$displayName = $query['displayName']; - self::$passHash = $query['passHash']; - self::$expires = (bool)$query['allowExpire']; - self::$reputation = $query['reputation']; - self::$banStatus = $query['bans']; - self::$groups = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userGroups']); - self::$perms = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userPerms']); - self::$dailyVotes = $query['dailyVotes']; - self::$excludeGroups = $query['excludeGroups']; + self::$id = intVal($uData['id']); + self::$displayName = $uData['displayName']; + self::$passHash = $uData['passHash']; + self::$expires = (bool)$uData['allowExpire']; + self::$reputation = $uData['reputation']; + self::$banStatus = $uData['bans']; + self::$groups = $uData['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($uData['userGroups']); + self::$perms = $uData['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($uData['userPerms']); + self::$dailyVotes = $uData['dailyVotes']; + self::$excludeGroups = $uData['excludeGroups']; $conditions = array( [['cuFlags', PROFILER_CU_DELETED, '&'], 0], @@ -96,11 +105,8 @@ class User self::$profiles = (new LocalProfileList($conditions)); - if ($query['avatar']) - self::$avatar = $query['avatar']; - - if (self::$localeId != $query['locale']) // reset, if changed - self::setLocale(intVal($query['locale'])); + if ($uData['avatar']) + self::$avatar = $uData['avatar']; // stuff, that updates on a daily basis goes here (if you keep you session alive indefinitly, the signin-handler doesn't do very much) // - conscutive visits @@ -115,10 +121,10 @@ class User // daily votes (we need to reset this one) self::$dailyVotes = self::getMaxDailyVotes(); - DB::Aowow()->query(' - UPDATE ?_account - SET dailyVotes = ?d, prevLogin = curLogin, curLogin = UNIX_TIMESTAMP(), prevIP = curIP, curIP = ? - WHERE id = ?d', + DB::Aowow()->query( + 'UPDATE ?_account + SET `dailyVotes` = ?d, `prevLogin` = `curLogin`, `curLogin` = UNIX_TIMESTAMP(), `prevIP` = `curIP`, `curIP` = ? + WHERE `id` = ?d', self::$dailyVotes, self::$ip, self::$id @@ -131,16 +137,16 @@ class User // increment consecutive visits (next day or first of new month and not more than 48h) // i bet my ass i forgott a corner case if ((date('j', $lastLogin) + 1 == date('j') || (date('j') == 1 && date('n', $lastLogin) != date('n'))) && (time() - $lastLogin) < 2 * DAY) - DB::Aowow()->query('UPDATE ?_account SET consecutiveVisits = consecutiveVisits + 1 WHERE id = ?d', self::$id); + DB::Aowow()->query('UPDATE ?_account SET `consecutiveVisits` = `consecutiveVisits` + 1 WHERE `id` = ?d', self::$id); else - DB::Aowow()->query('UPDATE ?_account SET consecutiveVisits = 0 WHERE id = ?d', self::$id); + DB::Aowow()->query('UPDATE ?_account SET `consecutiveVisits` = 0 WHERE `id` = ?d', self::$id); } } return true; } - private static function setIP() + private static function setIP() : void { $ipAddr = ''; $method = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR']; @@ -165,68 +171,32 @@ class User self::$ip = $ipAddr ?: null; } - /****************/ - /* set language */ - /****************/ - - // set and save - public static function setLocale($set = -1) + public static function save(bool $toDB = false) { - $loc = LOCALE_EN; + $_SESSION['user'] = self::$id; + $_SESSION['hash'] = self::$passHash; + $_SESSION['locale'] = self::$preferedLoc; + $_SESSION['timeout'] = self::$expires ? time() + Cfg::get('SESSION_TIMEOUT_DELAY') : 0; + // $_SESSION['dataKey'] does not depend on user login status and is set in User::init() - // get - if ($set != -1 && isset(Util::$localeStrings[$set])) - $loc = $set; - else if (isset($_SESSION['locale']) && isset(Util::$localeStrings[$_SESSION['locale']])) - $loc = $_SESSION['locale']; - else if (!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"])) - { - $loc = strtolower(substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2)); - switch ($loc) { - case 'fr': $loc = LOCALE_FR; break; - case 'de': $loc = LOCALE_DE; break; - case 'zh': $loc = LOCALE_CN; break; // may cause issues in future with zh-tw - case 'es': $loc = LOCALE_ES; break; - case 'ru': $loc = LOCALE_RU; break; - default: $loc = LOCALE_EN; - } - } - - // check; pick first viable if failed - $allowedLoc = Cfg::get('LOCALES'); - if ($allowedLoc && !($allowedLoc & (1 << $loc))) - { - foreach (Util::$localeStrings as $idx => $__) - { - if ($allowedLoc & (1 << $idx)) - { - $loc = $idx; - break; - } - } - } - - // set - if (self::$id) - DB::Aowow()->query('UPDATE ?_account SET locale = ? WHERE id = ?', $loc, self::$id); - - self::useLocale($loc); + if (self::$id && $toDB) + DB::Aowow()->query('UPDATE ?_account SET `locale` = ? WHERE `id` = ?', self::$preferedLoc->value, self::$id); } - // only use once - public static function useLocale($use) + public static function destroy() { - self::$localeId = isset(Util::$localeStrings[$use]) ? $use : LOCALE_EN; - self::$localeString = self::localeString(self::$localeId); + session_regenerate_id(true); // session itself is not destroyed; status changed => regenerate id + session_unset(); + + $_SESSION['locale'] = self::$preferedLoc; // keep locale + $_SESSION['dataKey'] = self::$dataKey; // keep dataKey + + self::$id = 0; + self::$displayName = ''; + self::$perms = 0; + self::$groups = U_GROUP_NONE; } - private static function localeString($loc = -1) - { - if (!isset(Util::$localeStrings[$loc])) - $loc = 0; - - return Util::$localeStrings[$loc]; - } /*******************/ /* auth mechanisms */ @@ -245,21 +215,21 @@ class User return AUTH_INTERNAL_ERR; // handle login try limitation - $ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip); + $ip = DB::Aowow()->selectRow('SELECT `ip`, `count`, `unbanDate` FROM ?_account_bannedips WHERE `type` = 0 AND `ip` = ?', self::$ip); if (!$ip || $ip['unbanDate'] < time()) // no entry exists or time expired; set count to 1 - DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, Cfg::get('ACC_FAILED_AUTH_BLOCK')); + DB::Aowow()->query('REPLACE INTO ?_account_bannedips (`ip`, `type`, `count`, `unbanDate`) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, Cfg::get('ACC_FAILED_AUTH_BLOCK')); else // entry already exists; increment count - DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ?', Cfg::get('ACC_FAILED_AUTH_BLOCK'), self::$ip); + DB::Aowow()->query('UPDATE ?_account_bannedips SET `count` = `count` + 1, `unbanDate` = UNIX_TIMESTAMP() + ?d WHERE `ip` = ?', Cfg::get('ACC_FAILED_AUTH_BLOCK'), self::$ip); if ($ip && $ip['count'] >= Cfg::get('ACC_FAILED_AUTH_COUNT') && $ip['unbanDate'] >= time()) return AUTH_IPBANNED; - $query = DB::Aowow()->SelectRow(' - SELECT a.id, a.passHash, BIT_OR(ab.typeMask) AS bans, a.status + $query = DB::Aowow()->SelectRow( + 'SELECT a.`id`, a.`passHash`, BIT_OR(ab.`typeMask`) AS "bans", a.`status` FROM ?_account a - LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP() - WHERE a.user = ? - GROUP BY a.id', + LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP() + WHERE a.`user` = ? + GROUP BY a.`id`', $name ); if (!$query) @@ -270,7 +240,7 @@ class User return AUTH_WRONGPASS; // successfull auth; clear bans for this IP - DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip); + DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE `type` = 0 AND `ip` = ?', self::$ip); if ($query['bans'] & (ACC_BAN_PERM | ACC_BAN_TEMP)) return AUTH_BANNED; @@ -304,10 +274,19 @@ class User case AUTH_MODE_EXTERNAL: { if (!file_exists('config/extAuth.php')) + { + trigger_error('config/extAuth.php not found'); return AUTH_INTERNAL_ERR; + } require 'config/extAuth.php'; + if (!function_exists('extAuth')) + { + trigger_error('external auth function extAuth() not defined in config/extAuth.php'); + return AUTH_INTERNAL_ERR; + } + $extGroup = -1; $result = extAuth($name, $pass, $extId, $extGroup); @@ -335,27 +314,22 @@ class User return AUTH_OK; } - // create a linked account for our settings if nessecary - private static function checkOrCreateInDB($extId, $name, $userGroup = -1) + // create a linked account for our settings if necessary + private static function checkOrCreateInDB(int $extId, string $name, int $userGroup = -1) : int { - if (!intVal($extId)) - return 0; - - $userGroup = intVal($userGroup); - - if ($_ = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE extId = ?d', $extId)) + if ($_ = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `extId` = ?d', $extId)) { if ($userGroup >= U_GROUP_NONE) - DB::Aowow()->query('UPDATE ?_account SET userGroups = ?d WHERE extId = ?d', $userGroup, $extId); + DB::Aowow()->query('UPDATE ?_account SET `userGroups` = ?d WHERE `extId` = ?d', $userGroup, $extId); return $_; } - $newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (extId, user, displayName, joinDate, prevIP, prevLogin, locale, status, userGroups) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)', + $newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (`extId`, `user`, `displayName`, `joinDate`, `prevIP`, `prevLogin`, `locale`, `status`, `userGroups`) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)', $extId, $name, Util::ucFirst($name), - isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '', - User::$localeId, + $_SERVER["REMOTE_ADDR"] ?? '', + self::$preferedLoc->value, ACC_STATUS_OK, $userGroup >= U_GROUP_NONE ? $userGroup : U_GROUP_NONE ); @@ -439,39 +413,17 @@ class User return $errCode == 0; } - public static function save() - { - $_SESSION['user'] = self::$id; - $_SESSION['hash'] = self::$passHash; - $_SESSION['locale'] = self::$localeId; - $_SESSION['timeout'] = self::$expires ? time() + Cfg::get('SESSION_TIMEOUT_DELAY') : 0; - // $_SESSION['dataKey'] does not depend on user login status and is set in User::init() - } - - public static function destroy() - { - session_regenerate_id(true); // session itself is not destroyed; status changed => regenerate id - session_unset(); - - $_SESSION['locale'] = self::$localeId; // keep locale - $_SESSION['dataKey'] = self::$dataKey; // keep dataKey - - self::$id = 0; - self::$displayName = ''; - self::$perms = 0; - self::$groups = U_GROUP_NONE; - } /*********************/ /* access management */ /*********************/ - public static function isInGroup($group) + public static function isInGroup($group) : bool { return (self::$groups & $group) != 0; } - public static function canComment() + public static function canComment() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -479,7 +431,7 @@ class User return self::$perms || self::$reputation >= Cfg::get('REP_REQ_COMMENT'); } - public static function canReply() + public static function canReply() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -487,7 +439,7 @@ class User return self::$perms || self::$reputation >= Cfg::get('REP_REQ_REPLY'); } - public static function canUpvote() + public static function canUpvote() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -495,7 +447,7 @@ class User return self::$perms || (self::$reputation >= Cfg::get('REP_REQ_UPVOTE') && self::$dailyVotes > 0); } - public static function canDownvote() + public static function canDownvote() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_RATE | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -503,7 +455,7 @@ class User return self::$perms || (self::$reputation >= Cfg::get('REP_REQ_DOWNVOTE') && self::$dailyVotes > 0); } - public static function canSupervote() + public static function canSupervote() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_RATE | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -511,7 +463,7 @@ class User return self::$reputation >= Cfg::get('REP_REQ_SUPERVOTE'); } - public static function canUploadScreenshot() + public static function canUploadScreenshot() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_SCREENSHOT | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -519,7 +471,7 @@ class User return true; } - public static function canWriteGuide() + public static function canWriteGuide() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_GUIDE | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -527,7 +479,7 @@ class User return true; } - public static function canSuggestVideo() + public static function canSuggestVideo() : bool { if (!self::$id || self::$banStatus & (ACC_BAN_VIDEO | ACC_BAN_PERM | ACC_BAN_TEMP)) return false; @@ -535,27 +487,28 @@ class User return true; } - public static function isPremium() + public static function isPremium() : bool { return self::isInGroup(U_GROUP_PREMIUM) || self::$reputation >= Cfg::get('REP_REQ_PREMIUM'); } + /**************/ /* js-related */ /**************/ - public static function decrementDailyVotes() + public static function decrementDailyVotes() : void { self::$dailyVotes--; - DB::Aowow()->query('UPDATE ?_account SET dailyVotes = ?d WHERE id = ?d', self::$dailyVotes, self::$id); + DB::Aowow()->query('UPDATE ?_account SET `dailyVotes` = ?d WHERE `id` = ?d', self::$dailyVotes, self::$id); } - public static function getCurDailyVotes() + public static function getCurrentDailyVotes() : int { return self::$dailyVotes; } - public static function getMaxDailyVotes() + public static function getMaxDailyVotes() : int { if (!self::$id || self::$banStatus & (ACC_BAN_PERM | ACC_BAN_TEMP)) return 0; @@ -563,12 +516,12 @@ class User return Cfg::get('USER_MAX_VOTES') + (self::$reputation >= Cfg::get('REP_REQ_VOTEMORE_BASE') ? 1 + intVal((self::$reputation - Cfg::get('REP_REQ_VOTEMORE_BASE')) / Cfg::get('REP_REQ_VOTEMORE_ADD')) : 0); } - public static function getReputation() + public static function getReputation() : int { return self::$reputation; } - public static function getUserGlobals() + public static function getUserGlobals() : array { $gUser = array( 'id' => self::$id, @@ -613,34 +566,34 @@ class User return $gUser; } - public static function getWeightScales() + public static function getWeightScales() : array { $result = []; - $res = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, name FROM ?_account_weightscales WHERE userId = ?d', self::$id); + $res = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `name` FROM ?_account_weightscales WHERE `userId` = ?d', self::$id); if (!$res) return $result; - $weights = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, `field` AS ARRAY_KEY2, val FROM ?_account_weightscale_data WHERE id IN (?a)', array_keys($res)); + $weights = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `field` AS ARRAY_KEY2, `val` FROM ?_account_weightscale_data WHERE `id` IN (?a)', array_keys($res)); foreach ($weights as $id => $data) $result[] = array_merge(['name' => $res[$id], 'id' => $id], $data); return $result; } - public static function getProfilerExclusions() + public static function getProfilerExclusions() : array { $result = []; $modes = [1 => 'excludes', 2 => 'includes']; foreach ($modes as $mode => $field) - if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, typeId AS ARRAY_KEY2, typeId FROM ?_account_excludes WHERE mode = ?d AND userId = ?d', $mode, self::$id)) + if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, `typeId` AS ARRAY_KEY2, `typeId` FROM ?_account_excludes WHERE `mode` = ?d AND `userId` = ?d', $mode, self::$id)) foreach ($ex as $type => $ids) $result[$field][$type] = array_values($ids); return $result; } - public static function getCharacters() + public static function getCharacters() : array { if (!self::$profiles) return []; @@ -648,7 +601,7 @@ class User return self::$profiles->getJSGlobals(PROFILEINFO_CHARACTER); } - public static function getProfiles() + public static function getProfiles() : array { if (!self::$profiles) return []; @@ -675,7 +628,7 @@ class User return []; } - public static function getGuides() + public static function getGuides() : array { $result = []; @@ -689,17 +642,17 @@ class User return $result; } - public static function getCookies() + public static function getCookies() : array { $data = []; if (self::$id) - $data = DB::Aowow()->selectCol('SELECT name AS ARRAY_KEY, data FROM ?_account_cookies WHERE userId = ?d', self::$id); + $data = DB::Aowow()->selectCol('SELECT `name` AS ARRAY_KEY, `data` FROM ?_account_cookies WHERE `userId` = ?d', self::$id); return $data; } - public static function getFavorites() + public static function getFavorites() : array { if (!self::$id) return []; diff --git a/includes/utilities.php b/includes/utilities.php index 2467de88..7186e146 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -77,22 +77,6 @@ trait TrRequestData return 0; } - private static function checkLocale(string $val) : int - { - if (preg_match('/^'.implode('|', array_keys(array_filter(Util::$localeStrings))).'$/', $val)) - return intVal($val); - - return -1; - } - - private static function checkDomain(string $val) : string - { - if (preg_match('/^'.implode('|', array_filter(Util::$subDomains)).'$/i', $val)) - return strtolower($val); - - return ''; - } - private static function checkIdList(string $val) : array { if (preg_match('/^-?\d+(,-?\d+)*$/', $val)) @@ -538,14 +522,6 @@ abstract class Util private static $perfectGems = null; - public static $localeStrings = array( // zero-indexed - 'enus', null, 'frfr', 'dede', 'zhcn', null, 'eses', null, 'ruru' - ); - - public static $subDomains = array( - 'en', null, 'fr', 'de', 'cn', null, 'es', null, 'ru' - ); - public static $regions = array( 'us', 'eu', 'kr', 'tw', 'cn', 'dev' ); @@ -919,19 +895,19 @@ abstract class Util $silent = true; // default case: selected locale available - if (!empty($data[$field.'_loc'.User::$localeId])) - return $data[$field.'_loc'.User::$localeId]; + if (!empty($data[$field.'_loc'.Lang::getLocale()->value])) + return $data[$field.'_loc'.Lang::getLocale()->value]; // locale not enUS; aowow-type localization available; add brackets if not silent - else if (User::$localeId != LOCALE_EN && !empty($data[$field.'_loc0'])) + else if (Lang::getLocale() != Locale::EN && !empty($data[$field.'_loc0'])) return $silent ? $data[$field.'_loc0'] : '['.$data[$field.'_loc0'].']'; // locale not enUS; TC localization; add brackets if not silent - else if (User::$localeId != LOCALE_EN && !empty($data[$field])) + else if (Lang::getLocale() != Locale::EN && !empty($data[$field])) return $silent ? $data[$field] : '['.$data[$field].']'; // locale enUS; TC localization; return normal - else if (User::$localeId == LOCALE_EN && !empty($data[$field])) + else if (Lang::getLocale() == Locale::EN && !empty($data[$field])) return $data[$field]; // nothing to find; be empty @@ -969,22 +945,6 @@ abstract class Util return Lang::item('ratingString', [$statId, $result, $level]); } - public static function powerUseLocale(string $domain = 'en') : void - { - foreach (Util::$subDomains as $k => $v) - { - if ($domain != $v) - continue; - - User::useLocale($k); - Lang::load($k); - return; - } - - User::useLocale(LOCALE_EN); - Lang::load(LOCALE_EN); - } - // default ucFirst doesn't convert UTF-8 chars public static function ucFirst($str) { @@ -1097,8 +1057,8 @@ abstract class Util $success = true; if ($localized) { - if (file_exists('datasets/'.User::$localeString.'/'.$file)) - $result .= file_get_contents('datasets/'.User::$localeString.'/'.$file); + if (file_exists('datasets/'.Lang::getLocale()->json().'/'.$file)) + $result .= file_get_contents('datasets/'.Lang::getLocale()->json().'/'.$file); else if (file_exists('datasets/enus/'.$file)) $result .= file_get_contents('datasets/enus/'.$file); else diff --git a/index.php b/index.php index e570eeeb..74c9dfbc 100644 --- a/index.php +++ b/index.php @@ -121,7 +121,7 @@ switch ($pageCall) if (is_callable([$classInstance, 'display'])) $classInstance->display(); else if (isset($_GET['power'])) - die('$WowheadPower.register(0, '.User::$localeId.', {})'); + die('$WowheadPower.register(0, '.Lang::getLocale()->value.', {})'); else // in conjunction with a proper rewriteRule in .htaccess... (new GenericPage($pageCall))->error(); } @@ -153,7 +153,7 @@ switch ($pageCall) break; default: // unk parameter given -> ErrorPage if (isset($_GET['power'])) - die('$WowheadPower.register(0, '.User::$localeId.', {})'); + die('$WowheadPower.register(0, '.Lang::getLocale()->value.', {})'); else // in conjunction with a proper rewriteRule in .htaccess... (new GenericPage($pageCall))->error(); break; diff --git a/localization/lang.class.php b/localization/lang.class.php index 12d8c820..30711951 100644 --- a/localization/lang.class.php +++ b/localization/lang.class.php @@ -44,28 +44,21 @@ class Lang private static $emote; private static $enchantment; - private static $locId; - private static $locales = array( - LOCALE_EN => 'English', - LOCALE_FR => 'Français', - LOCALE_DE => 'Deutsch', - LOCALE_CN => '简体中文', - LOCALE_ES => 'Español', - LOCALE_RU => 'Русский' - ); + private static ?Locale $locale = null; public const FMT_RAW = 0; public const FMT_HTML = 1; public const FMT_MARKUP = 2; - public static function load(int $locale) : void + public static function load(Locale $loc) : void { - if (!isset(Util::$localeStrings[$locale])) - die($locale.' is not a known locale!'); - if (!file_exists('localization/locale_'.Util::$localeStrings[$locale].'.php')) - die('File for locale '.$locale.' not found.'); + if (self::$locale == $loc) + return; + + if (!file_exists('localization/locale_'.$loc->json().'.php')) + die('File for locale '.$loc->name.' not found.'); else - require 'localization/locale_'.Util::$localeStrings[$locale].'.php'; + require 'localization/locale_'.$loc->json().'.php'; foreach ($lang as $k => $v) self::$$k = $v; @@ -75,10 +68,15 @@ class Lang self::$item['cat'][2][1][14] .= ' ('.self::$item['cat'][2][0].')'; self::$main['moreTitles']['privilege'] = self::$privileges['_privileges']; - self::$locId = $locale; + self::$locale = $loc; } - public static function __callStatic(string $prop, array $args) // : ?string|array + public static function getLocale() : Locale + { + return self::$locale; + } + + public static function __callStatic(string $prop, ?array $args = []) : string|array|null { $vspfArgs = []; foreach ($args as $i => $arg) @@ -96,9 +94,11 @@ class Lang $dbt = debug_backtrace()[0]; $file = explode(DIRECTORY_SEPARATOR, $dbt['file']); trigger_error('Lang - undefined property Lang::$'.$prop.'[\''.implode('\'][\'', $args).'\'], called in '.array_pop($file).':'.$dbt['line'], E_USER_WARNING); + + return null; } - public static function exist(string $prop, ...$args) + public static function exist(string $prop, string ...$args) : string|array|null { if (!isset(self::$$prop)) return null; @@ -120,12 +120,12 @@ class Lang $b = ''; $i = 0; $n = count($args); + + $callback ??= fn($x) => $x; + foreach ($args as $k => $arg) { - if (is_callable($callback)) - $b .= $callback($arg, $k); - else - $b .= $arg; + $b .= $callback($arg, $k); if ($n > 1 && $i < ($n - 2)) $b .= ', '; @@ -192,13 +192,13 @@ class Lang foreach ($row as &$r) $r = implode(' ', $r); - switch ($fmt) + $separator = match ($fmt) { - case self::FMT_HTML: $separator = '
'; break; - case self::FMT_MARKUP: $separator = '[br]'; break; - case self::FMT_RAW: - default: $separator = "\n"; break; - } + self::FMT_HTML => '
', + self::FMT_MARKUP => '[br]', + self::FMT_RAW => "\n", + default => "\n" + }; return implode($separator, $row); } @@ -223,20 +223,20 @@ class Lang } // todo: expand - public static function getInfoBoxForFlags(int $flags) : array + public static function getInfoBoxForFlags(int $cuFlags) : array { $tmp = []; - if ($flags & CUSTOM_DISABLED) + if ($cuFlags & CUSTOM_DISABLED) $tmp[] = '[tooltip name=disabledHint]'.Util::jsEscape(self::main('disabledHint')).'[/tooltip][span class=tip tooltip=disabledHint]'.Util::jsEscape(self::main('disabled')).'[/span]'; - if ($flags & CUSTOM_SERVERSIDE) + if ($cuFlags & CUSTOM_SERVERSIDE) $tmp[] = '[tooltip name=serversideHint]'.Util::jsEscape(self::main('serversideHint')).'[/tooltip][span class=tip tooltip=serversideHint]'.Util::jsEscape(self::main('serverside')).'[/span]'; - if ($flags & CUSTOM_UNAVAILABLE) + if ($cuFlags & CUSTOM_UNAVAILABLE) $tmp[] = self::main('unavailable'); - if ($flags & CUSTOM_EXCLUDE_FOR_LISTVIEW && User::isInGroup(U_GROUP_STAFF)) + if ($cuFlags & CUSTOM_EXCLUDE_FOR_LISTVIEW && User::isInGroup(U_GROUP_STAFF)) $tmp[] = '[tooltip name=excludedHint]This entry is excluded from lists and is not searchable.[/tooltip][span tooltip=excludedHint class="tip q10"]Hidden[/span]'; return $tmp; @@ -246,7 +246,7 @@ class Lang { $locks = []; $ids = []; - $lock = DB::Aowow()->selectRow('SELECT * FROM ?_lock WHERE id = ?d', $lockId); + $lock = DB::Aowow()->selectRow('SELECT * FROM ?_lock WHERE `id` = ?d', $lockId); if (!$lock) return $locks; @@ -518,13 +518,13 @@ class Lang { $tmp = self::game('difficulty').self::main('colon'); - switch ($fmt) + $base = match ($fmt) { - case self::FMT_HTML: $base = '%2$s '; break; - case self::FMT_MARKUP: $base = '[color=r%1$d]%2$s[/color] '; break; - case self::FMT_RAW: - default: $base = '%2$s '; break; - } + self::FMT_HTML => '%2$s ', + self::FMT_MARKUP => '[color=r%1$d]%2$s[/color] ', + self::FMT_RAW => '%2$s ', + default => '%2$s ' + }; for ($i = 0; $i < 4; $i++) if (!empty($bp[$i])) @@ -594,7 +594,7 @@ class Lang return ''; } - private static function vspf(/* array|string */ $var, array $args = []) // : array|string + private static function vspf(null|array|string $var, array $args = []) : null|array|string { if (is_array($var)) { @@ -775,7 +775,7 @@ class Lang switch (strtolower($word[1])) { case 'h': - if (self::$locId != LOCALE_FR) + if (self::$locale != Locale::FR) return 'de ' . $word; case 'a': case 'e': @@ -810,7 +810,7 @@ class Lang { [$_, $num, $pad, $singular, $plural1, $plural2] = array_pad($m, 6, null); - if (self::$locId != LOCALE_RU || !$plural2) + if (self::$locale != Locale::RU || !$plural2) return $num . $pad . ($num == 1 ? $singular : $plural1); // singular - ends in 1, but not teen number diff --git a/pages/account.php b/pages/account.php index 6874792c..64a6872d 100644 --- a/pages/account.php +++ b/pages/account.php @@ -437,7 +437,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup $this->_post['email'], User::$ip, $this->_post['remember_me'] != 'yes', - User::$localeId, + Lang::getLocale()->value, U_GROUP_PENDING, ACC_STATUS_NEW, Cfg::get('ACC_CREATE_SAVE_DECAY'), diff --git a/pages/achievement.php b/pages/achievement.php index b2b854d3..5ac531b8 100644 --- a/pages/achievement.php +++ b/pages/achievement.php @@ -38,7 +38,7 @@ class AchievementPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $powerTpl = '$WowheadPower.registerAchievement(%d, %d, %s);'; @@ -48,7 +48,7 @@ class AchievementPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -233,7 +233,7 @@ class AchievementPage extends GenericPage // tab: see also $conditions = array( - ['name_loc'.User::$localeId, $this->subject->getField('name', true)], + ['name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)], ['id', $this->typeId, '!'] ); $saList = new AchievementList($conditions); @@ -551,12 +551,12 @@ class AchievementPage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = $this->subject->getField('name', true); - $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); + $power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true); + $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } private function createMail(&$reqCss = false) diff --git a/pages/compare.php b/pages/compare.php index 80780353..202bff1b 100644 --- a/pages/compare.php +++ b/pages/compare.php @@ -87,10 +87,10 @@ class ComparePage extends GenericPage $si['enchantment'] = implode(', ', $si['enchantment']); $this->cmpItems[$itemId] = [ - 'name_'.User::$localeString => $iList->getField('name', true), - 'quality' => $iList->getField('quality'), - 'icon' => $iList->getField('iconString'), - 'jsonequip' => $data[$itemId] + 'name_'.Lang::getLocale()->json() => $iList->getField('name', true), + 'quality' => $iList->getField('quality'), + 'icon' => $iList->getField('iconString'), + 'jsonequip' => $data[$itemId] ]; } } diff --git a/pages/currency.php b/pages/currency.php index c318001c..7c076d77 100644 --- a/pages/currency.php +++ b/pages/currency.php @@ -17,7 +17,7 @@ class CurrencyPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $powerTpl = '$WowheadPower.registerCurrency(%d, %d, %s);'; @@ -27,7 +27,7 @@ class CurrencyPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -231,12 +231,12 @@ class CurrencyPage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = $this->subject->getField('name', true); - $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); + $power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true); + $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } } diff --git a/pages/emote.php b/pages/emote.php index de72dfeb..6d330d68 100644 --- a/pages/emote.php +++ b/pages/emote.php @@ -89,7 +89,7 @@ class EmotePage extends GenericPage if ($this->subject->getField('cuFlags') & EMOTE_CU_MISSING_CMD) $text .= Lang::emote('noCommand').'[br][br]'; - else if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << User::$localeId)) + else if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << Lang::getLocale()->value)) { $text .= '[h3]'.Lang::emote('aliases').'[/h3][ul]'; foreach ($aliasses as $a) diff --git a/pages/event.php b/pages/event.php index bea2cfa5..50e85eb3 100644 --- a/pages/event.php +++ b/pages/event.php @@ -19,7 +19,7 @@ class EventPage extends GenericPage protected $tabId = 0; protected $mode = CACHE_TYPE_PAGE; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $powerTpl = '$WowheadPower.registerHoliday(%d, %d, %s);'; private $hId = 0; @@ -31,7 +31,7 @@ class EventPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -283,15 +283,15 @@ class EventPage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = $this->subject->getField('name', true); + $power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true); if ($this->subject->getField('iconString') != 'trade_engineering') $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } protected function postCache() @@ -309,7 +309,7 @@ class EventPage extends GenericPage else { if ($this->hId) - $this->wowheadLink = sprintf(WOWHEAD_LINK, Util::$subDomains[User::$localeId], 'event', $this->hId); + $this->wowheadLink = sprintf(WOWHEAD_LINK, Lang::getLocale()->domain(), 'event', $this->hId); /********************/ /* finalize infobox */ diff --git a/pages/genericPage.class.php b/pages/genericPage.class.php index 07f1a8c8..e73e5ece 100644 --- a/pages/genericPage.class.php +++ b/pages/genericPage.class.php @@ -30,7 +30,7 @@ trait TrDetailPage $staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE)); // mode, type, typeId, employee-flag, localeId, category, filter - $key = [$this->mode, $this->type, $this->typeId, $staff, User::$localeId, '-1', '-1']; + $key = [$this->mode, $this->type, $this->typeId, $staff, Lang::getLocale()->value, '-1', '-1']; // item special: can modify tooltips if (isset($this->enhancedTT)) @@ -70,7 +70,7 @@ trait TrListPage $staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE)); // mode, type, typeId, employee-flag, localeId, - $key = [$this->mode, $this->type, '-1', $staff, User::$localeId]; + $key = [$this->mode, $this->type, '-1', $staff, Lang::getLocale()->value]; //category $key[] = $this->category ? implode('.', $this->category) : '-1'; @@ -100,7 +100,7 @@ trait TrProfiler $staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE)); // mode, type, typeId, employee-flag, localeId, category, filter - $key = [$this->mode, $this->type, $this->subject->getField('id'), $staff, User::$localeId, '-1', '-1']; + $key = [$this->mode, $this->type, $this->subject->getField('id'), $staff, Lang::getLocale()->value, '-1', '-1']; return implode('_', $key); } @@ -141,7 +141,7 @@ trait TrProfiler } } - protected function initialSync() : void + protected function initialSync() : never { $this->prepareContent(); @@ -320,7 +320,7 @@ class GenericPage $this->gFavorites = User::getFavorites(); $this->pageTemplate['pageName'] = strtolower($pageCall); - $this->wowheadLink = sprintf(WOWHEAD_LINK, Util::$subDomains[User::$localeId], $pageCall, $pageParam); + $this->wowheadLink = sprintf(WOWHEAD_LINK,Lang::getLocale()->domain(), $pageCall, $pageParam); if (!$this->isValidPage()) $this->error(); @@ -495,15 +495,15 @@ class GenericPage // insert locale string if ($flags & SC_FLAG_LOCALIZED) - $str = sprintf($str, User::$localeString); + $str = sprintf($str, Lang::getLocale()->json()); if ($dynData) { - $app[] = 'locale='.User::$localeId; + $app[] = 'locale='.Lang::getLocale()->value; $app[] = 't='.$_SESSION['dataKey']; } - else if (($flags & SC_FLAG_APPEND_LOCALE) && User::$localeId) - $app[] = 'lang='.Util::$subDomains[User::$localeId]; + else if (($flags & SC_FLAG_APPEND_LOCALE) && Lang::getLocale() != Locale::EN) + $app[] = 'lang='.Lang::getLocale()->domain(); // append anti-cache timestamp if (!($flags & SC_FLAG_NO_TIMESTAMP) && !$dynData) @@ -549,10 +549,10 @@ class GenericPage Type::GUIDE, $this->typeId, $this->guideRevision); else if (!empty($this->articleUrl)) $article = DB::Aowow()->selectRow('SELECT `article`, `quickInfo`, `locale`, `editAccess` FROM ?_articles WHERE `url` = ? AND `locale` IN (?a) ORDER BY `locale` DESC, `rev` DESC LIMIT 1', - $this->articleUrl, [User::$localeId, LOCALE_EN]); + $this->articleUrl, [Lang::getLocale()->value, Locale::EN->value]); else if (!empty($this->type) && isset($this->typeId)) $article = DB::Aowow()->selectRow('SELECT `article`, `quickInfo`, `locale`, `editAccess` FROM ?_articles WHERE `type` = ?d AND `typeId` = ?d AND `locale` IN (?a) ORDER BY `locale` DESC, `rev` DESC LIMIT 1', - $this->type, $this->typeId, [User::$localeId, LOCALE_EN]); + $this->type, $this->typeId, [Lang::getLocale()->value, Locale::EN->value]); if ($article) { @@ -586,7 +586,7 @@ class GenericPage if (empty($this->infobox) && !empty($article['quickInfo'])) $this->infobox = $article['quickInfo']; - if ($article['locale'] != User::$localeId) + if ($article['locale'] != Lang::getLocale()->value) $this->article['params']['prepend'] = '
'.Lang::main('langOnly', [Lang::lang($article['locale'])]).'
'; if (method_exists($this, 'postArticle')) // e.g. update variables in article @@ -676,7 +676,7 @@ class GenericPage /*******************/ // unknown entry - public function notFound(string $title = '', string $msg = '') : void + public function notFound(string $title = '', string $msg = '') : never { if ($this->mode == CACHE_TYPE_TOOLTIP && method_exists($this, 'generateTooltip')) { @@ -713,7 +713,7 @@ class GenericPage } // unknown page - public function error() : void + public function error() : never { // $this->path = null; // $this->tabId = null; @@ -733,7 +733,7 @@ class GenericPage } // display brb gnomes - public function maintenance() : void + public function maintenance() : never { header('HTTP/1.0 503 Service Temporarily Unavailable', true, 503); header('Retry-After: '.(3 * HOUR)); @@ -748,7 +748,7 @@ class GenericPage /*******************/ // load given template string or GenericPage::$tpl - public function display(string $override = '') : void + public function display(string $override = '') : never { // Heisenbug: IE11 and FF32 will sometimes (under unknown circumstances) cache 302 redirects and stop // re-requesting them from the server but load them from local cache, thus breaking menu features. @@ -797,7 +797,7 @@ class GenericPage } // generate and cache - public function displayExtra(callable $generator, string $mime = MIME_TYPE_JSON) : void + public function displayExtra(callable $generator, string $mime = MIME_TYPE_JSON) : never { $outString = ''; if (!$this->loadCache($outString)) @@ -833,7 +833,7 @@ class GenericPage // localizes expected fields .. except for icons .. icons are special if (in_array($k, ['name', 'namefemale']) && $struct[0] != Type::getJSGlobalString(Type::ICON)) { - $data[$k.'_'.User::$localeString] = $v; + $data[$k.'_'.Lang::getLocale()->json()] = $v; unset($data[$k]); } } @@ -849,13 +849,13 @@ class GenericPage // spell if (!empty($x['tooltip'])) // spell + item - $buff .= "\n _[".$x['id'].'].tooltip_'.User::$localeString.' = '.Util::toJSON($x['tooltip']).";\n"; + $buff .= "\n _[".$x['id'].'].tooltip_'.Lang::getLocale()->json().' = '.Util::toJSON($x['tooltip']).";\n"; if (!empty($x['buff'])) // spell - $buff .= " _[".$x['id'].'].buff_'.User::$localeString.' = '.Util::toJSON($x['buff']).";\n"; + $buff .= " _[".$x['id'].'].buff_'.Lang::getLocale()->json().' = '.Util::toJSON($x['buff']).";\n"; if (!empty($x['spells'])) // spell + item - $buff .= " _[".$x['id'].'].spells_'.User::$localeString.' = '.Util::toJSON($x['spells']).";\n"; + $buff .= " _[".$x['id'].'].spells_'.Lang::getLocale()->json().' = '.Util::toJSON($x['spells']).";\n"; if (!empty($x['buffspells'])) // spell - $buff .= " _[".$x['id'].'].buffspells_'.User::$localeString.' = '.Util::toJSON($x['buffspells']).";\n"; + $buff .= " _[".$x['id'].'].buffspells_'.Lang::getLocale()->json().' = '.Util::toJSON($x['buffspells']).";\n"; $buff .= "\n"; } @@ -922,17 +922,17 @@ class GenericPage } // load brick with more text then vars - protected function localizedBrick(string $file, int $loc = LOCALE_EN) : void + protected function localizedBrick(string $file, Locale $loc = Locale::EN) : void { - if (!$this->isSaneInclude('template/localized/', $file.'_'.$loc)) + if (!$this->isSaneInclude('template/localized/', $file.'_'.$loc->value)) { - if ($loc == LOCALE_EN || !$this->isSaneInclude('template/localized/', $file.'_'.LOCALE_EN)) - trigger_error('Nonexistant template requested: template/localized/'.$file.'_'.$loc.'.tpl.php', E_USER_ERROR); + if ($loc == Locale::EN || !$this->isSaneInclude('template/localized/', $file.'_'.Locale::EN->value)) + trigger_error('Nonexistant template requested: template/localized/'.$file.'_'.$loc->value.'.tpl.php', E_USER_ERROR); else - include('template/localized/'.$file.'_'.LOCALE_EN.'.tpl.php'); + include('template/localized/'.$file.'_'.Locale::EN->value.'.tpl.php'); } else - include('template/localized/'.$file.'_'.$loc.'.tpl.php'); + include('template/localized/'.$file.'_'.$loc->value.'.tpl.php'); } diff --git a/pages/guide.php b/pages/guide.php index 070d9708..74f28d8e 100644 --- a/pages/guide.php +++ b/pages/guide.php @@ -180,7 +180,7 @@ class GuidePage extends GenericPage { // init required template vars $this->editorFields = array( - 'locale' => User::$localeId, + 'locale' => Lang::getLocale()->value, 'status' => GUIDE_STATUS_DRAFT ); } @@ -522,11 +522,11 @@ class GuidePage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = strip_tags($this->name); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); + $power->{'name_'.Lang::getLocale()->json()} = strip_tags($this->name); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); } - return sprintf($this->powerTpl, Util::toJSON($this->articleUrl ?: $this->typeId), User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, Util::toJSON($this->articleUrl ?: $this->typeId), Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } protected function generatePath() : void diff --git a/pages/guides.php b/pages/guides.php index 6372c916..1848cc99 100644 --- a/pages/guides.php +++ b/pages/guides.php @@ -52,7 +52,7 @@ class GuidesPage extends GenericPage else { $conditions = array( - ['locale', User::$localeId], + ['locale', Lang::getLocale()->value], ['status', GUIDE_STATUS_ARCHIVED, '!'], // never archived guides [ 'OR', diff --git a/pages/home.php b/pages/home.php index bd209893..36953157 100644 --- a/pages/home.php +++ b/pages/home.php @@ -41,7 +41,7 @@ class HomePage extends GenericPage $this->extendGlobalData($_); if (empty($this->featuredBox['boxBG'])) - $this->featuredBox['boxBG'] = Cfg::get('STATIC_URL').'/images/'.User::$localeString.'/mainpage-bg-news.jpg'; + $this->featuredBox['boxBG'] = Cfg::get('STATIC_URL').'/images/'.Lang::getLocale()->json().'/mainpage-bg-news.jpg'; // load overlay links $this->featuredBox['overlays'] = DB::Aowow()->select('SELECT * FROM ?_home_featuredbox_overlay WHERE featureId = ?d', $this->featuredBox['id']); @@ -54,7 +54,7 @@ class HomePage extends GenericPage protected function generateTitle() { - if ($_ = DB::Aowow()->selectCell('SELECT title FROM ?_home_titles WHERE active = 1 AND locale = ?d ORDER BY RAND() LIMIT 1', User::$localeId)) + if ($_ = DB::Aowow()->selectCell('SELECT title FROM ?_home_titles WHERE active = 1 AND locale = ?d ORDER BY RAND() LIMIT 1', Lang::getLocale()->value)) $this->homeTitle = Cfg::get('NAME').Lang::main('colon').$_; } diff --git a/pages/item.php b/pages/item.php index b5acacca..467bf2f5 100644 --- a/pages/item.php +++ b/pages/item.php @@ -29,7 +29,7 @@ class ItemPage extends genericPage ); protected $_get = array( - 'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain'], + 'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain'], 'rand' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], 'ench' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], 'gems' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkIntArray'], @@ -50,7 +50,7 @@ class ItemPage extends genericPage { // temp locale if ($this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); if ($this->_get['rand']) $this->enhancedTT['r'] = $this->_get['rand']; @@ -65,11 +65,11 @@ class ItemPage extends genericPage { // temp locale if ($this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); // allow lookup by name for xml if (!is_numeric($param)) - $conditions = [['name_loc'.User::$localeId, urldecode($param)]]; + $conditions = [['name_loc'.Lang::getLocale()->value, urldecode($param)]]; } $this->subject = new ItemList($conditions); @@ -672,7 +672,7 @@ class ItemPage extends genericPage ['id', $this->typeId, '!'], [ 'OR', - ['name_loc'.User::$localeId, $this->subject->getField('name', true)], + ['name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)], [ 'AND', ['class', $_class], @@ -1030,10 +1030,10 @@ class ItemPage extends genericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = Lang::unescapeUISequences($this->subject->getField('name', true, false, $this->enhancedTT), Lang::FMT_RAW); - $power->quality = $this->subject->getField('quality'); - $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(false, 0, $this->enhancedTT); + $power->{'name_'.Lang::getLocale()->json()} = Lang::unescapeUISequences($this->subject->getField('name', true, false, $this->enhancedTT), Lang::FMT_RAW); + $power->quality = $this->subject->getField('quality'); + $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(false, 0, $this->enhancedTT); } $itemString = $this->typeId; @@ -1044,7 +1044,7 @@ class ItemPage extends genericPage $itemString = "'".$itemString."'"; } - return sprintf($this->powerTpl, $itemString, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $itemString,Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } protected function generateXML() diff --git a/pages/itemset.php b/pages/itemset.php index 99aeab07..bb0a716e 100644 --- a/pages/itemset.php +++ b/pages/itemset.php @@ -25,7 +25,7 @@ class ItemsetPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $scripts = [[SC_JS_FILE, 'js/swfobject.js'], [SC_JS_FILE, 'js/Summary.js']]; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $powerTpl = '$WowheadPower.registerItemSet(%d, %d, %s);'; @@ -35,7 +35,7 @@ class ItemsetPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -149,7 +149,7 @@ class ItemsetPage extends GenericPage $compare[] = $itemId; $pieces[$itemId] = array( - 'name_'.User::$localeString => $iList->getField('name', true), + 'name_'.Lang::getLocale()->json() => $iList->getField('name', true), 'quality' => $iList->getField('quality'), 'icon' => $iList->getField('iconString'), 'jsonequip' => $data[$itemId] @@ -244,11 +244,11 @@ class ItemsetPage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = $this->subject->getField('name', true); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); + $power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } } diff --git a/pages/npc.php b/pages/npc.php index 4a61cde5..3b4918ec 100644 --- a/pages/npc.php +++ b/pages/npc.php @@ -24,7 +24,7 @@ class NpcPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $scripts = [[SC_JS_FILE, 'js/swfobject.js'], [SC_CSS_FILE, 'css/Profiler.css']]; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $soundIds = []; private $powerTpl = '$WowheadPower.registerNpc(%d, %d, %s);'; @@ -35,7 +35,7 @@ class NpcPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -902,12 +902,12 @@ class NpcPage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = $this->subject->getField('name', true); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); - $power->map = $this->subject->getSpawns(SPAWNINFO_SHORT); + $power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); + $power->map = $this->subject->getSpawns(SPAWNINFO_SHORT); } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } private function getRepForId(array $entries, array &$spillover) : array diff --git a/pages/object.php b/pages/object.php index b1cf479e..94e501d1 100644 --- a/pages/object.php +++ b/pages/object.php @@ -21,7 +21,7 @@ class ObjectPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $scripts = [[SC_JS_FILE, 'js/swfobject.js']]; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $powerTpl = '$WowheadPower.registerObject(%d, %d, %s);'; @@ -31,7 +31,7 @@ class ObjectPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -488,12 +488,12 @@ class ObjectPage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); + $power->{'name_'.Lang::getLocale()->json()} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); $power->map = $this->subject->getSpawns(SPAWNINFO_SHORT); } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } } diff --git a/pages/profile.php b/pages/profile.php index 7ca0d5aa..69f3a1af 100644 --- a/pages/profile.php +++ b/pages/profile.php @@ -30,7 +30,7 @@ class ProfilePage extends GenericPage ); protected $_get = array( - 'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain'], + 'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain'], 'new' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'] ); @@ -55,7 +55,7 @@ class ProfilePage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); if (count($params) == 1 && intval($params[0])) { @@ -170,7 +170,7 @@ class ProfilePage extends GenericPage // dummy title from dungeon encounter foreach (Lang::profiler('encounterNames') as $id => $name) - $this->extendGlobalData([Type::NPC => [$id => ['name_'.User::$localeString => $name]]]); + $this->extendGlobalData([Type::NPC => [$id => ['name_'.Lang::getLocale()->json() => $name]]]); } protected function generatePath() @@ -204,15 +204,15 @@ class ProfilePage extends GenericPage if ($title = (new TitleList(array(['id', $_])))->getField($g ? 'female' : 'male', true)) $n = sprintf($title, $n); - $power->{'name_'.User::$localeString} = $n; - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); - $power->icon = '$$WH.g_getProfileIcon('.$r.', '.$c.', '.$g.', '.$l.', \''.$this->subject->getIcon().'\')'; + $power->{'name_'.Lang::getLocale()->json()} = $n; + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); + $power->icon = '$$WH.g_getProfileIcon('.$r.', '.$c.', '.$g.', '.$l.', \''.$this->subject->getIcon().'\')'; } - return sprintf($this->powerTpl, $id, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $id, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } - public function display(string $override = ''): void + public function display(string $override = ''): never { if ($this->mode != CACHE_TYPE_TOOLTIP) parent::display($override); @@ -222,7 +222,7 @@ class ProfilePage extends GenericPage die($this->generateTooltip()); } - public function notFound(string $title = '', string $msg = '') : void + public function notFound(string $title = '', string $msg = '') : never { parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'profile')); } diff --git a/pages/quest.php b/pages/quest.php index bceaba9c..ae9b1e79 100644 --- a/pages/quest.php +++ b/pages/quest.php @@ -33,7 +33,7 @@ class QuestPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $scripts = [[SC_JS_FILE, 'js/ShowOnMap.js'], [SC_CSS_FILE, 'css/Book.css']]; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $powerTpl = '$WowheadPower.registerQuest(%d, %d, %s);'; @@ -43,7 +43,7 @@ class QuestPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -981,7 +981,7 @@ class QuestPage extends GenericPage /**************/ // tab: see also - $seeAlso = new QuestList(array(['name_loc'.User::$localeId, '%'.Util::htmlEscape($this->subject->getField('name', true)).'%'], ['id', $this->typeId, '!'])); + $seeAlso = new QuestList(array(['name_loc'.Lang::getLocale()->value, '%'.Util::htmlEscape($this->subject->getField('name', true)).'%'], ['id', $this->typeId, '!'])); if (!$seeAlso->error) { $this->extendGlobalData($seeAlso->getJSGlobals()); @@ -1045,13 +1045,13 @@ class QuestPage extends GenericPage $power = new StdClass(); if (!$this->subject->error) { - $power->{'name_'.User::$localeString} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW); - $power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(); + $power->{'name_'.Lang::getLocale()->json()} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW); + $power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(); if ($this->subject->isDaily()) $power->daily = 1; } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } private function createRewards($side) diff --git a/pages/search.php b/pages/search.php index 5bbdbe23..e036782b 100644 --- a/pages/search.php +++ b/pages/search.php @@ -138,14 +138,14 @@ class SearchPage extends GenericPage continue; else if ($clean[0] == '-') { - if (mb_strlen($clean) < 4 && !Util::isLogographic(User::$localeId)) + if (mb_strlen($clean) < 4 && !Util::isLogographic(Lang::getLocale()->value)) $this->invalid[] = mb_substr($raw, 1); else $this->excluded[] = mb_substr(str_replace('_', '\\_', $clean), 1); } else if ($clean !== '') { - if (mb_strlen($clean) < 3 && !Util::isLogographic(User::$localeId)) + if (mb_strlen($clean) < 3 && !Util::isLogographic(Lang::getLocale()->value)) $this->invalid[] = $raw; else $this->included[] = str_replace('_', '\\_', $clean); @@ -157,7 +157,7 @@ class SearchPage extends GenericPage { $staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE)); - $key = [$this->mode, $this->searchMask, md5($this->query), $staff, User::$localeId]; + $key = [$this->mode, $this->searchMask, md5($this->query), $staff, Lang::getLocale()->value]; return implode('_', $key); } @@ -212,7 +212,7 @@ class SearchPage extends GenericPage $this->performSearch(); } - public function notFound(string $title = '', string $msg = '') : void + public function notFound(string $title = '', string $msg = '') : never { if ($this->searchMask & SEARCH_TYPE_REGULAR) { @@ -237,7 +237,7 @@ class SearchPage extends GenericPage } } - public function display(string $override = '') : void + public function display(string $override = '') : never { if ($override || ($this->searchMask & SEARCH_TYPE_REGULAR)) parent::display($override); @@ -330,7 +330,7 @@ class SearchPage extends GenericPage { // default to name-field if (!$fields) - $fields[] = 'name_loc'.User::$localeId; + $fields[] = 'name_loc'.Lang::getLocale()->value; $qry = []; foreach ($fields as $f) @@ -429,7 +429,7 @@ class SearchPage extends GenericPage private function _searchTitle($cndBase) // 2 Titles: $searchMask & 0x00000004 { - $cnd = array_merge($cndBase, [$this->createLookup(['male_loc'.User::$localeId, 'female_loc'.User::$localeId])]); + $cnd = array_merge($cndBase, [$this->createLookup(['male_loc'.Lang::getLocale()->value, 'female_loc'.Lang::getLocale()->value])]); $titles = new TitleList($cnd, ['calcTotal' => true]); if ($data = $titles->getListviewData()) @@ -458,7 +458,7 @@ class SearchPage extends GenericPage $cnd = array_merge($cndBase, array( array( 'OR', - $this->createLookup(['h.name_loc'.User::$localeId]), + $this->createLookup(['h.name_loc'.Lang::getLocale()->value]), ['AND', $this->createLookup(['e.description']), ['e.holidayId', 0]] ) )); @@ -1321,7 +1321,7 @@ class SearchPage extends GenericPage private function _searchEmote($cndBase) // 25 Emotes $searchMask & 0x2000000 { - $cnd = array_merge($cndBase, [$this->createLookup(['cmd', 'meToExt_loc'.User::$localeId, 'meToNone_loc'.User::$localeId, 'extToMe_loc'.User::$localeId, 'extToExt_loc'.User::$localeId, 'extToNone_loc'.User::$localeId])]); + $cnd = array_merge($cndBase, [$this->createLookup(['cmd', 'meToExt_loc'.Lang::getLocale()->value, 'meToNone_loc'.Lang::getLocale()->value, 'extToMe_loc'.Lang::getLocale()->value, 'extToExt_loc'.Lang::getLocale()->value, 'extToNone_loc'.Lang::getLocale()->value])]); $emote = new EmoteList($cnd, ['calcTotal' => true]); if ($data = $emote->getListviewData()) @@ -1340,7 +1340,7 @@ class SearchPage extends GenericPage private function _searchEnchantment($cndBase) // 26 Enchantments $searchMask & 0x4000000 { - $cnd = array_merge($cndBase, [$this->createLookup(['name_loc'.User::$localeId])]); + $cnd = array_merge($cndBase, [$this->createLookup(['name_loc'.Lang::getLocale()->value])]); $enchantment = new EnchantmentList($cnd, ['calcTotal' => true]); if ($data = $enchantment->getListviewData()) diff --git a/pages/spell.php b/pages/spell.php index 2d7c8141..eca3c2b4 100644 --- a/pages/spell.php +++ b/pages/spell.php @@ -38,7 +38,7 @@ class SpellPage extends GenericPage protected $mode = CACHE_TYPE_PAGE; protected $scripts = [[SC_JS_FILE, 'js/swfobject.js']]; - protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']]; + protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']]; private $difficulties = []; private $firstRank = 0; @@ -56,7 +56,7 @@ class SpellPage extends GenericPage // temp locale if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain']) - Util::powerUseLocale($this->_get['domain']); + Lang::load($this->_get['domain']); $this->typeId = intVal($id); @@ -541,7 +541,7 @@ class SpellPage extends GenericPage ['s.effect2Id', $this->subject->getField('effect2Id')], ['s.effect3Id', $this->subject->getField('effect3Id')], ['s.id', $this->subject->id, '!'], - ['s.name_loc'.User::$localeId, $this->subject->getField('name', true)] + ['s.name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)] ); $saSpells = new SpellList($conditions); @@ -1283,15 +1283,15 @@ class SpellPage extends GenericPage [$tooltip, $ttSpells] = $this->subject->renderTooltip(); [$buff, $bfSpells] = $this->subject->renderBuff(); - $power->{'name_'.User::$localeString} = $this->subject->getField('name', true); + $power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true); $power->icon = rawurlencode($this->subject->getField('iconString', true, true)); - $power->{'tooltip_'.User::$localeString} = $tooltip; - $power->{'spells_'.User::$localeString} = $ttSpells; - $power->{'buff_'.User::$localeString} = $buff; - $power->{'buffspells_'.User::$localeString} = $bfSpells; + $power->{'tooltip_'.Lang::getLocale()->json()} = $tooltip; + $power->{'spells_'.Lang::getLocale()->json()} = $ttSpells; + $power->{'buff_'.Lang::getLocale()->json()} = $buff; + $power->{'buffspells_'.Lang::getLocale()->json()} = $bfSpells; } - return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER)); + return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER)); } private function buildPctStack(float $baseChance, int $maxStack) : string @@ -1907,7 +1907,7 @@ class SpellPage extends GenericPage JOIN ?_taxinodes tn1 ON tp.`startNodeId` = tn1.`id` JOIN ?_taxinodes tn2 ON tp.`endNodeId` = tn2.`id` WHERE tp.`id` = ?d', - User::$localeId, User::$localeId, User::$localeId, User::$localeId, $effMV + Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, $effMV ); if ($_) $_nameMV = $this->fmtStaffTip(''.Util::localizedString($_, 'start').''.Util::localizedString($_, 'end'), 'MiscValue: '.$effMV); diff --git a/pages/utility.php b/pages/utility.php index 6fc4455e..b54c25db 100644 --- a/pages/utility.php +++ b/pages/utility.php @@ -48,7 +48,7 @@ class UtilityPage extends GenericPage } } - public function display(string $override = '') : void + public function display(string $override = '') : never { if ($this->rss) // this should not be cached { @@ -275,7 +275,7 @@ class UtilityPage extends GenericPage $channel->addChild('title', Cfg::get('NAME_SHORT').' - '.$this->name); $channel->addChild('link', Cfg::get('HOST_URL').'/?'.$this->page . ($this->category ? '='.$this->category[0] : null)); $channel->addChild('description', Cfg::get('NAME')); - $channel->addChild('language', implode('-', str_split(User::$localeString, 2))); + $channel->addChild('language', implode('-', str_split(Lang::getLocale()->json(), 2))); $channel->addChild('ttl', Cfg::get('TTL_RSS')); $channel->addChild('lastBuildDate', date(DATE_RSS)); diff --git a/pages/zone.php b/pages/zone.php index 8b8eacd6..7ff8ad9a 100644 --- a/pages/zone.php +++ b/pages/zone.php @@ -195,9 +195,9 @@ class ZonePage extends GenericPage } // see if we can actually display a map - $hasMap = file_exists('static/images/wow/maps/'.Util::$localeStrings[User::$localeId].'/normal/'.$this->typeId.'.jpg'); + $hasMap = file_exists('static/images/wow/maps/'.Lang::getLocale()->json().'/normal/'.$this->typeId.'.jpg'); if (!$hasMap) // try multilayered - $hasMap = file_exists('static/images/wow/maps/'.Util::$localeStrings[User::$localeId].'/normal/'.$this->typeId.'-1.jpg'); + $hasMap = file_exists('static/images/wow/maps/'.Lang::getLocale()->json().'/normal/'.$this->typeId.'-1.jpg'); if (!$hasMap) // try english fallback $hasMap = file_exists('static/images/wow/maps/enus/normal/'.$this->typeId.'.jpg'); if (!$hasMap) // try english fallback, multilayered diff --git a/setup/tools/CLISetup.class.php b/setup/tools/CLISetup.class.php index 0f83cba9..54fc66e6 100644 --- a/setup/tools/CLISetup.class.php +++ b/setup/tools/CLISetup.class.php @@ -14,14 +14,6 @@ class CLISetup public static $srcDir = 'setup/mpqdata/'; 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, - 'frFR' => LOCALE_FR, - 'deDE' => LOCALE_DE, - 'zhCN' => LOCALE_CN, 'enCN' => LOCALE_CN, - 'esES' => LOCALE_ES, - 'ruRU' => LOCALE_RU - ); public const SQL_BATCH = 1000; // max. n items per sql insert @@ -175,21 +167,15 @@ class CLISetup // optional limit handled locales if (isset(self::$opts['locales'])) { - // engb and enus are identical for all intents and purposes - $from = ['engb', 'encn']; - $to = ['enus', 'zhcn']; - - self::$opts['locales'] = str_ireplace($from, $to, self::$opts['locales']); - - self::$locales = array_intersect(Util::$localeStrings, array_map('strtolower', self::$opts['locales'])); + $opt = array_map('strtolower', self::$opts['locales']); + foreach (Locale::cases() as $loc) + if ($loc->validate() && array_intersect(array_map('strtolower', $loc->gameDirs()), $opt)) + self::$locales[$loc->value] = $loc; } if (!self::$locales) - self::$locales = array_filter(Util::$localeStrings); - - // restrict actual locales - foreach (self::$locales as $idx => $_) - if (($l = Cfg::get('LOCALES')) && !($l & (1 << $idx))) - unset(self::$locales[$idx]); + foreach (Locale::cases() as $loc) + if ($loc->validate()) + self::$locales[$loc->value] = $loc; return !!self::$locales; } @@ -557,22 +543,19 @@ class CLISetup { $result = []; - foreach (self::$expectedPaths as $xp => $locId) + foreach (self::$locales as $locId => $loc) { - if (!in_array($locId, array_keys(self::$locales))) - continue; - - if (isset($result[$locId])) - continue; - - if ($xp) // if in subDir add trailing slash - $xp .= DIRECTORY_SEPARATOR; - - $path = sprintf($pathPattern, $xp); - if (self::fileExists($path)) + foreach ($loc->gameDirs() as $gDir) { - $result[$locId] = $path; - continue; + if ($gDir) // if in subDir add trailing slash + $gDir .= DIRECTORY_SEPARATOR; + + $path = sprintf($pathPattern, $gDir); + if (self::fileExists($path)) + { + $result[$locId] = $path; + break; + } } } @@ -590,17 +573,23 @@ class CLISetup CLI::write('loading required GlobalStrings', CLI::LOG_INFO); // try to load globalstrings for all selected locales - foreach (self::$expectedPaths as $xp => $lId) + foreach (self::$locales as $locId => $loc) { - if (isset(self::$gsFiles[$lId])) + if (isset(self::$gsFiles[$locId])) continue; - if ($xp) - $xp .= DIRECTORY_SEPARATOR; + foreach ($loc->gameDirs() as $gDir) + { + if ($gDir) + $gDir .= DIRECTORY_SEPARATOR; - $gsFile = sprintf(self::GLOBALSTRINGS_LUA, self::$srcDir, $xp); - if (self::fileExists($gsFile)) - self::$gsFiles[$lId] = file($gsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + $gsFile = sprintf(self::GLOBALSTRINGS_LUA, self::$srcDir, $gDir); + if (self::fileExists($gsFile)) + { + self::$gsFiles[$locId] = file($gsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + break; + } + } } if ($missing = array_diff_key(self::$locales, self::$gsFiles)) @@ -612,7 +601,7 @@ class CLISetup return true; } - public static function searchGlobalStrings(string $pattern) : generator + public static function searchGlobalStrings(string $pattern) : Generator { if (!self::$gsFiles) return; diff --git a/setup/tools/clisetup/account.us.php b/setup/tools/clisetup/account.us.php index ed1be498..10e5e3eb 100644 --- a/setup/tools/clisetup/account.us.php +++ b/setup/tools/clisetup/account.us.php @@ -38,8 +38,7 @@ CLISetup::registerUtility(new class extends UtilityScript // args: username, password, email, null // iiin public function run(&$args) : bool { - User::useLocale(LOCALE_EN); - Lang::load(LOCALE_EN); + Lang::load(Locale::EN); $name = $args[0] ?? ''; $passw = $args[1] ?? ''; @@ -67,21 +66,21 @@ CLISetup::registerUtility(new class extends UtilityScript { CLI::write(); - if (!$name && !User::isValidName($uiAccount['name'], $e)) + if (!$name && !User::isValidName($uiAccount['name'] ?? '', $e)) CLI::write(Lang::account($e == 1 ? 'errNameLength' : 'errNameChars'), CLI::LOG_ERROR); else if (!$name) $name = $uiAccount['name']; - if (!$passw && !User::isValidPass($uiAccount['pass1'], $e)) + if (!$passw && !User::isValidPass($uiAccount['pass1'] ?? '', $e)) CLI::write(Lang::account($e == 1 ? 'errPassLength' : 'errPassChars'), CLI::LOG_ERROR); else if (!$passw && $uiAccount['pass1'] != $uiAccount['pass2']) CLI::write(Lang::account('passMismatch'), CLI::LOG_ERROR); else if (!$passw) $passw = $uiAccount['pass1']; - if (!$email && Util::isValidEmail($uiAccount['email'])) + if (!$email && Util::isValidEmail($uiAccount['email'] ?? '')) $email = $uiAccount['email']; - else if (!$email && $uiAccount['email']) + else if (!$email && $uiAccount && $uiAccount['email']) CLI::write('[account] email invalid ... using default: ' . Cfg::get('CONTACT_EMAIL'), CLI::LOG_INFO); } else if ($this->fields) @@ -92,7 +91,7 @@ CLISetup::registerUtility(new class extends UtilityScript return true; } - if (DB::Aowow()->SelectCell('SELECT 1 FROM ?_account WHERE user = ? AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $name, ACC_STATUS_NEW, ACC_STATUS_NEW)) + if (DB::Aowow()->SelectCell('SELECT 1 FROM ?_account WHERE `user` = ? AND (`status` <> ?d OR (`status` = ?d AND `statusTimer` > UNIX_TIMESTAMP()))', $name, ACC_STATUS_NEW, ACC_STATUS_NEW)) { CLI::write('[account] ' . Lang::account('nameInUse'), CLI::LOG_ERROR); CLI::write(); @@ -102,10 +101,10 @@ CLISetup::registerUtility(new class extends UtilityScript if (!$name || !$passw) return false; - if (DB::Aowow()->query('REPLACE INTO ?_account (user, passHash, displayName, joindate, email, allowExpire, userGroups, userPerms) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, 0, ?d, 1)', + if (DB::Aowow()->query('REPLACE INTO ?_account (`user`, `passHash`, `displayName`, `joindate`, `email`, `allowExpire`, `userGroups`, `userPerms`) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, 0, ?d, 1)', $name, User::hashCrypt($passw), Util::ucFirst($name), $email ?: Cfg::get('CONTACT_EMAIL'), U_GROUP_ADMIN)) { - $newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $name); + $newId = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `user` = ?', $name); Util::gainSiteReputation($newId, SITEREP_ACTION_REGISTER); CLI::write("[account] admin ".$name." created successfully", CLI::LOG_OK); diff --git a/setup/tools/clisetup/dbconfig.us.php b/setup/tools/clisetup/dbconfig.us.php index c23fe650..449fd7a1 100644 --- a/setup/tools/clisetup/dbconfig.us.php +++ b/setup/tools/clisetup/dbconfig.us.php @@ -84,7 +84,7 @@ CLISetup::registerUtility(new class extends UtilityScript CLI::write(); if (!DB::isConnectable(DB_AUTH) || !$this->test()) CLI::write('[db] auth server not yet set up.', CLI::LOG_ERROR); - else if ($realms = DB::Auth()->select('SELECT id AS "0", name AS "1", icon AS "2", timezone AS "3", isRestricted AS "4" FROM realmlist')) + else if ($realms = DB::Auth()->select('SELECT `id` AS "0", `name` AS "1", `icon` AS "2", `timezone` AS "3", `allowedSecurityLevel` AS "4" FROM realmlist')) { $tbl = [['Realm Id', 'Name', 'Type', 'Region', 'GMLevel', 'Status']]; foreach ($realms as [$id, $name, $icon, $region, $level]) diff --git a/setup/tools/dbc.class.php b/setup/tools/dbc.class.php index c297215f..0f9f41b9 100644 --- a/setup/tools/dbc.class.php +++ b/setup/tools/dbc.class.php @@ -110,21 +110,27 @@ class DBC $this->isGameTable = array_values($this->format) == ['f'] && substr($file, 0, 2) == 'gt'; $foundMask = 0x0; - foreach (CLISetup::$expectedPaths as $locStr => $locId) + foreach (Locale::cases() as $loc) { - if (!in_array($locId, array_keys(CLISetup::$locales))) + if (!in_array($loc, CLISetup::$locales)) continue; - if ($foundMask & (1 << $locId)) + if ($foundMask & (1 << $loc->value)) continue; - $fullPath = CLI::nicePath($this->file.'.dbc', CLISetup::$srcDir, $locStr, 'DBFilesClient'); - if (!CLISetup::fileExists($fullPath)) - continue; + foreach ($loc->gameDirs() as $dir) + { + $fullPath = CLI::nicePath($this->file.'.dbc', CLISetup::$srcDir, $dir, 'DBFilesClient'); + if (!CLISetup::fileExists($fullPath)) + continue; - $this->curFile = $fullPath; - if ($this->validateFile($locId)) - $foundMask |= (1 << $locId); + $this->curFile = $fullPath; + if ($this->validateFile($loc)) + { + $foundMask |= (1 << $loc->value); + break; + } + } } if (!$this->fileRefs) @@ -138,7 +144,7 @@ class DBC $x = array_unique(array_column($headers, 'recordCount')); if (count($x) != 1) { - CLI::write('some DBCs have differenct record counts ('.implode(', ', $x).' respectively). cannot merge!', CLI::LOG_ERROR); + CLI::write('some DBCs have different record counts ('.implode(', ', $x).' respectively). cannot merge!', CLI::LOG_ERROR); return; } $x = array_unique(array_column($headers, 'fieldCount')); @@ -165,7 +171,7 @@ class DBC $this->createTable(); if ($this->localized) - CLI::write(' - DBC: reading and merging '.$this->file.'.dbc for locales '.Lang::concat(array_intersect_key(Util::$localeStrings, $this->fileRefs), true, 'CLI::bold')); + CLI::write(' - DBC: reading and merging '.$this->file.'.dbc for locales '.Lang::concat(array_keys($this->fileRefs), callback: fn($x) => CLI::bold(Locale::from($x)->name))); else CLI::write(' - DBC: reading '.$this->file.'.dbc'); @@ -212,25 +218,25 @@ class DBC $this->dataBuffer = null; } - private function readHeader(&$handle = null) + private function readHeader(&$handle = null) : array { if (!is_resource($handle)) $handle = fopen($this->curFile, 'rb'); if (!$handle) - return false; + return []; if (fread($handle, 4) != 'WDBC') { CLI::write('file '.$this->curFile.' has incorrect magic bytes', CLI::LOG_ERROR); fclose($handle); - return false; + return []; } return unpack('VrecordCount/VfieldCount/VrecordSize/VstringSize', fread($handle, 16)); } - private function validateFile($locId) + private function validateFile(Locale $loc) : bool { $filesize = filesize($this->curFile); if ($filesize < 20) @@ -266,7 +272,7 @@ class DBC return false; } - $this->fileRefs[$locId] = [$handle, $this->curFile, $header]; + $this->fileRefs[$loc->value] = [$handle, $this->curFile, $header]; return true; } diff --git a/setup/tools/filegen/enchants.ss.php b/setup/tools/filegen/enchants.ss.php index 4a383198..991a1ec8 100644 --- a/setup/tools/filegen/enchants.ss.php +++ b/setup/tools/filegen/enchants.ss.php @@ -66,16 +66,16 @@ CLISetup::registerSetup("build", new class extends SetupScript $castItems = []; $enchantSpells = DB::Aowow()->select( - 'SELECT s.id AS ARRAY_KEY, - effect1MiscValue, - equippedItemClass, equippedItemInventoryTypeMask, equippedItemSubClassMask, - skillLine1, - IFNULL(i.name, ?) AS iconString, - name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8 + 'SELECT s.`id` AS ARRAY_KEY, + `effect1MiscValue`, + `equippedItemClass`, `equippedItemInventoryTypeMask`, `equippedItemSubClassMask`, + `skillLine1`, + IFNULL(i.`name`, ?) AS "iconString", + `name_loc0`, `name_loc2`, `name_loc3`, `name_loc4`, `name_loc6`, `name_loc8` FROM ?_spell s - LEFT JOIN ?_icons i ON i.id = s.iconId - WHERE effect1Id = ?d AND - name_loc0 NOT LIKE "QA%"', + LEFT JOIN ?_icons i ON i.`id` = s.`iconId` + WHERE `effect1Id` = ?d AND + `name_loc0` NOT LIKE "QA%"', DEFAULT_ICON, SPELL_EFFECT_ENCHANT_ITEM ); @@ -97,10 +97,9 @@ CLISetup::registerSetup("build", new class extends SetupScript return false; } - foreach (CLISetup::$locales as $lId => $jsonStr) + foreach (CLISetup::$locales as $loc) { - User::useLocale($lId); - Lang::load($lId); + Lang::load($loc); $enchantsOut = []; foreach ($enchantSpells as $esId => $es) @@ -121,7 +120,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if ($invType = $es['equippedItemInventoryTypeMask']) $slot = $invType >> 1; else /* if (equippedItemSubClassMask == 64) */ // shields have it their own way <_< - $slot = (1 << (14 - 1)); + $slot = (1 << (INVTYPE_SHIELD - 1)); } else if ($es['equippedItemClass'] == ITEM_CLASS_WEAPON) { @@ -133,7 +132,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if ((1 << $i) & $es['equippedItemSubClassMask']) { if ($sp == 13) // also mainHand & offHand *siiigh* - $slot |= ((1 << (21 - 1)) | (1 << (22 - 1))); + $slot |= ((1 << (INVTYPE_WEAPONMAINHAND - 1)) | (1 << (INVTYPE_WEAPONOFFHAND - 1))); $slot |= (1 << ($sp - 1)); } @@ -185,7 +184,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if ($cI->getField('spellId1') != $esId) continue; - $isScroll = substr($cI->getField('name_loc0'), 0, 17) == 'Scroll of Enchant'; + $isScroll = $cI->getField('class') == ITEM_CLASS_CONSUMABLE && $cI->getField('subClass') == ITEM_SUBCLASS_ITEM_ENHANCEMENT && $cI->getField('pickUpSoundId') == 1192; if ($s = Util::getEnchantmentScore($cI->getField('itemLevel'), $isScroll ? -1 : $cI->getField('quality'), !!$enchantments->getField('skillLevel'), $eId)) if ($s > $ench['gearscore']) @@ -254,7 +253,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $ench[$k] = $v[0]; $toFile = "var g_enchants = ".Util::toJSON($enchantsOut).";"; - $file = 'datasets/'.$jsonStr.'/enchants'; + $file = 'datasets/'.$loc->json().'/enchants'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; diff --git a/setup/tools/filegen/gems.ss.php b/setup/tools/filegen/gems.ss.php index fc36fa5b..662d9e0e 100644 --- a/setup/tools/filegen/gems.ss.php +++ b/setup/tools/filegen/gems.ss.php @@ -35,19 +35,19 @@ CLISetup::registerSetup("build", new class extends SetupScript // sketchy, but should work // id < 36'000 || ilevel < 70 ? BC : WOTLK $gems = DB::Aowow()->select( - 'SELECT i.id AS itemId, - i.name_loc0, i.name_loc2, i.name_loc3, i.name_loc4, i.name_loc6, i.name_loc8, - IF (i.id < 36000 OR i.itemLevel < 70, ?d, ?d) AS expansion, - i.quality, - ic.name AS icon, - i.gemEnchantmentId AS enchId, - i.gemColorMask AS colors, - i.requiredSkill, - i.itemLevel + 'SELECT i.`id` AS "itemId", + i.`name_loc0`, i.`name_loc2`, i.`name_loc3`, i.`name_loc4`, i.`name_loc6`, i.`name_loc8`, + IF (i.`id` < 36000 OR i.`itemLevel` < 70, ?d, ?d) AS "expansion", + i.`quality`, + ic.`name` AS "icon", + i.`gemEnchantmentId` AS "enchId", + i.`gemColorMask` AS "colors", + i.`requiredSkill`, + i.`itemLevel` FROM ?_items i - JOIN ?_icons ic ON ic.id = i.iconId - WHERE i.gemEnchantmentId <> 0 - ORDER BY i.id DESC', + JOIN ?_icons ic ON ic.`id` = i.`iconId` + WHERE i.`gemEnchantmentId` <> 0 + ORDER BY i.`id` DESC', EXP_BC, EXP_WOTLK ); @@ -59,12 +59,11 @@ CLISetup::registerSetup("build", new class extends SetupScript return false; } - foreach (CLISetup::$locales as $lId => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(5); - User::useLocale($lId); - Lang::load($lId); + Lang::load($loc); $gemsOut = []; foreach ($gems as $g) @@ -88,7 +87,7 @@ CLISetup::registerSetup("build", new class extends SetupScript } $toFile = "var g_gems = ".Util::toJSON($gemsOut).";"; - $file = 'datasets/'.$jsonStr.'/gems'; + $file = 'datasets/'.$loc->json().'/gems'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; diff --git a/setup/tools/filegen/glyphs.ss.php b/setup/tools/filegen/glyphs.ss.php index b73c43c8..666d4fce 100644 --- a/setup/tools/filegen/glyphs.ss.php +++ b/setup/tools/filegen/glyphs.ss.php @@ -32,32 +32,31 @@ CLISetup::registerSetup("build", new class extends SetupScript public function generate() : bool { $glyphList = DB::Aowow()->Select( - 'SELECT i.id AS itemId, + 'SELECT i.`id` AS "itemId", i.*, - IF (g.typeFlags & 0x1, 2, 1) AS type, - i.subclass AS classs, - i.requiredLevel AS level, - s1.id AS glyphSpell, - ic.name AS icon, - s1.skillLine1 AS skillId, - s2.id AS glyphEffect, - s2.id AS ARRAY_KEY + IF (g.`typeFlags` & 0x1, 2, 1) AS "type", + i.`subclass` AS "classs", + i.`requiredLevel` AS "level", + s1.`id` AS "glyphSpell", + ic.`name` AS "icon", + s1.`skillLine1` AS "skillId", + s2.`id` AS "glyphEffect", + s2.`id` AS ARRAY_KEY FROM ?_items i - JOIN ?_spell s1 ON s1.id = i.spellid1 - JOIN ?_glyphproperties g ON g.id = s1.effect1MiscValue - JOIN ?_spell s2 ON s2.id = g.spellId - JOIN ?_icons ic ON ic.id = s1.iconIdAlt + JOIN ?_spell s1 ON s1.`id` = i.`spellid1` + JOIN ?_glyphproperties g ON g.`id` = s1.`effect1MiscValue` + JOIN ?_spell s2 ON s2.`id` = g.`spellId` + JOIN ?_icons ic ON ic.`id` = s1.`iconIdAlt` WHERE i.classBak = ?d', ITEM_CLASS_GLYPH); $glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], Cfg::get('SQL_LIMIT_NONE'))); - foreach (CLISetup::$locales as $lId => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(30); - User::useLocale($lId); - Lang::load($lId); + Lang::load($loc); $glyphsOut = []; foreach ($glyphSpells->iterate() as $__) @@ -67,7 +66,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if (!$pop['glyphEffect']) continue; - if ($glyphSpells->getField('effect1Id') != 6 && $glyphSpells->getField('effect2Id') != 6 && $glyphSpells->getField('effect3Id') != 6) + if ($glyphSpells->getField('effect1Id') != SPELL_EFFECT_APPLY_AURA && $glyphSpells->getField('effect2Id') != SPELL_EFFECT_APPLY_AURA && $glyphSpells->getField('effect3Id') != SPELL_EFFECT_APPLY_AURA) continue; $glyphsOut[$pop['itemId']] = array( @@ -82,7 +81,7 @@ CLISetup::registerSetup("build", new class extends SetupScript } $toFile = "var g_glyphs = ".Util::toJSON($glyphsOut).";"; - $file = 'datasets/'.$jsonStr.'/glyphs'; + $file = 'datasets/'.$loc->json().'/glyphs'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; diff --git a/setup/tools/filegen/img-artwork.ss.php b/setup/tools/filegen/img-artwork.ss.php index 0786ef7f..e01911cd 100644 --- a/setup/tools/filegen/img-artwork.ss.php +++ b/setup/tools/filegen/img-artwork.ss.php @@ -42,7 +42,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $this->imgPath = CLISetup::$srcDir.$this->imgPath; $this->maxExecTime = ini_get('max_execution_time'); - foreach ($this->genSteps[0][self::$GEN_IDX_DEST_INFO] as $dir) + foreach ($this->genSteps[0][self::GEN_IDX_DEST_INFO] as $dir) $this->requiredDirs[] = $dir[0]; } diff --git a/setup/tools/filegen/img-maps.ss.php b/setup/tools/filegen/img-maps.ss.php index 0185780d..4ccb8384 100644 --- a/setup/tools/filegen/img-maps.ss.php +++ b/setup/tools/filegen/img-maps.ss.php @@ -84,8 +84,8 @@ CLISetup::registerSetup("build", new class extends SetupScript if (strpos($dir[0], '%s') === false) $this->requiredDirs[] = $dir[0]; else - foreach (CLISetup::$locales as $l => $locJsonStr) - $this->requiredDirs[] = sprintf($dir[0], $locJsonStr.'/'); + foreach (CLISetup::$locales as $loc) + $this->requiredDirs[] = sprintf($dir[0], $loc->json().DIRECTORY_SEPARATOR); } } } @@ -145,7 +145,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $sumAreas = count($this->wmAreas); $sumMaps = count(CLISetup::$locales) * ($sumAreas + $sumFloors); - CLI::write('Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(array_intersect_key(Util::$localeStrings, CLISetup::$locales))); + CLI::write('[img-maps] Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(CLISetup::$locales, callback: fn($x) => $x->name)); /* todo: retrain brain and generate maps by given files and GlobalStrings. Then assign dbc data to them not the other way round like it is now. foreach ($this->mapFiles as $name => [$floors, $isMultilevel]) @@ -188,7 +188,7 @@ CLISetup::registerSetup("build", new class extends SetupScript // create spawn-maps if wanted if ($resOverlay && $this->modeMask & self::M_SPAWNS) { - $outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png'; + $outFile = $this->genSteps[self::M_SPAWNS][self::GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png'; if (!$this->buildSpawnMap($resOverlay, $outFile)) $this->success = false; } @@ -237,7 +237,7 @@ CLISetup::registerSetup("build", new class extends SetupScript */ $progressLoc = -1; - foreach (CLISetup::$locales as $l => $locJsonStr) + foreach (CLISetup::$locales as $l => $loc) { $progressLoc++; @@ -279,11 +279,11 @@ CLISetup::registerSetup("build", new class extends SetupScript str_pad('Dungeon Maps: '.($nFloors + ((($flags ?? 0) & self::AREA_FLAG_DEFAULT_FLOOR_TERRAIN) ? 1 : 0)), 18) ); - $srcPath = $mapSrcDir.'/'.$textureStr; + $srcPath = $mapSrcDir.DIRECTORY_SEPARATOR.$textureStr; if (!CLISetup::fileExists($srcPath)) { $this->success = false; - CLI::write('worldmap file '.$srcPath.' missing for selected locale '.$locJsonStr, CLI::LOG_ERROR); + CLI::write('worldmap file '.$srcPath.' missing for selected locale '.$loc->name, CLI::LOG_ERROR); continue; } @@ -316,7 +316,7 @@ CLISetup::registerSetup("build", new class extends SetupScript { ini_set('max_execution_time', $this->maxExecTime); - $file = $srcPath.'/'.$textureStr; + $file = $srcPath.DIRECTORY_SEPARATOR.$textureStr; // todo: Dalaran [4395] has no level 0 but is not skipped here if (!$floorIdx && !($flags & self::AREA_FLAG_DEFAULT_FLOOR_TERRAIN) && !in_array($mapId, self::CONTINENTS)) @@ -333,7 +333,7 @@ CLISetup::registerSetup("build", new class extends SetupScript foreach (self::DEST_DIRS as $sizeIdx => [$path, $width, $height]) { - $outFile[$sizeIdx] = sprintf($path, $locJsonStr.'/') . $zoneId; + $outFile[$sizeIdx] = sprintf($path, $loc->json().DIRECTORY_SEPARATOR) . $zoneId; /* dataset 'zones' requires that ... * 3959 - Black Temple: starts with empty floor suffix @@ -386,7 +386,7 @@ CLISetup::registerSetup("build", new class extends SetupScript // also create subzone-maps if ($resMap && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES) - $this->buildSubZones($resMap, $wmaId, $l); + $this->buildSubZones($resMap, $wmaId, $loc); if ($resMap) imagedestroy($resMap); @@ -508,9 +508,9 @@ CLISetup::registerSetup("build", new class extends SetupScript $sumAreas = count($this->wmAreas); $sumMaps = count(CLISetup::$locales) * ($sumAreas + $sumFloors); - CLI::write('[img-maps] Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(array_intersect_key(Util::$localeStrings, CLISetup::$locales))); + CLI::write('[img-maps] Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(CLISetup::$locales, callback: fn($x) => CLI::bold($x->name))); - foreach (CLISetup::$locales as $l => $locJsonStr) + foreach (CLISetup::$locales as $l => $loc) { // source for mapFiles $mapSrcDir = ''; @@ -522,7 +522,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $mapSrcDir = $this->genSteps[self::M_MAPS][1][$l] ?? ''; if (!$mapSrcDir) { - CLI::write('[img-maps] - No suitable localized map files found for locale ['.$l.': '.$locJsonStr.'].', CLI::LOG_ERROR); + CLI::write('[img-maps] - No suitable localized map files found for locale '.CLI::bold($loc->name).'.', CLI::LOG_ERROR); $this->success = false; continue; } @@ -551,28 +551,28 @@ CLISetup::registerSetup("build", new class extends SetupScript // .. which is not set in dbc 0 => 1, 1 => 2, etc. if ($flags & self::AREA_FLAG_NO_DEFAULT_FLOOR) - $dmFloors = array_combine($dmFloors, array_map(function ($x) { return ++$x; }, $dmFloors)); + $dmFloors = array_combine($dmFloors, array_map(fn($x) => ++$x, $dmFloors)); } else if ($dmFloors != [0]) // 1 => 1, 2 => 2, etc. $dmFloors = array_combine($dmFloors, $dmFloors); CLI::write( - '['.$locJsonStr.'] ' . + '['.$loc->json().'] ' . str_pad('['.$areaEntry['areaId'].']', 7) . str_pad($areaEntry['nameINT'], 22) . str_pad('Overlays: '.count($this->wmOverlays[$areaEntry['id']] ?? []), 14) . str_pad('Dungeon Maps: '.$nFloors, 18) ); - $srcPath = $mapSrcDir.'/'.$textureStr; + $srcPath = $mapSrcDir.DIRECTORY_SEPARATOR.$textureStr; if (!CLISetup::fileExists($srcPath)) { - CLI::write('[img-maps] - WorldMap file path '.$srcPath.' missing for selected locale '.$locJsonStr, CLI::LOG_ERROR); + CLI::write('[img-maps] - WorldMap file path '.$srcPath.' missing for selected locale '.CLI::bold($loc->name), CLI::LOG_ERROR); $this->success = false; continue; } - $srcPath .= '/'; + $srcPath .= DIRECTORY_SEPARATOR; // zone has overlays (is in open world; is not multilevel) if (isset($this->wmOverlays[$wmaId]) && ($this->modeMask & (self::M_MAPS | self::M_SPAWNS | self::M_SUBZONES))) @@ -619,7 +619,7 @@ CLISetup::registerSetup("build", new class extends SetupScript foreach (self::DEST_DIRS as $sizeIdx => [$path, $width, $height]) { - $outPaths[$sizeIdx] = sprintf($path, strtolower($locJsonStr).'/') . $outFile . '.jpg'; + $outPaths[$sizeIdx] = sprintf($path, strtolower($loc->json()).DIRECTORY_SEPARATOR) . $outFile . '.jpg'; if (!CLISetup::getOpt('force') && file_exists($outPaths[$sizeIdx])) { @@ -662,7 +662,7 @@ CLISetup::registerSetup("build", new class extends SetupScript // also create subzone-maps if ($resMap && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES) - $this->buildSubZones($resMap, $wmaId, $l); + $this->buildSubZones($resMap, $wmaId, $loc); if ($resMap) imagedestroy($resMap); @@ -677,7 +677,7 @@ CLISetup::registerSetup("build", new class extends SetupScript { $areaNames = array_combine( array_column($this->wmAreas, 'areaId'), - array_map(function ($x) { return strtoupper($x); }, array_column($this->wmAreas, 'nameINT')) + array_map(fn($x) => strtoupper($x), array_column($this->wmAreas, 'nameINT')) ); if ($this->multiLevelZones) @@ -708,7 +708,7 @@ CLISetup::registerSetup("build", new class extends SetupScript foreach (CLISetup::$locales as $lId => $loc) { - Lang::load($lId); + Lang::load($loc); // "custom" - show second level of Ahn'Kahet not shown but present in-game if (isset($zoneAreas[$lId][4494])) @@ -722,7 +722,7 @@ CLISetup::registerSetup("build", new class extends SetupScript continue; // todo: just note for now, try to compensate later? - CLI::write('[img-maps] ['.$loc.'] '.str_pad('['.$zoneId.']', 7).'floor count mismatch between GlobalStrings: '.$nStrings.' and image files: '.$nFloors, CLI::LOG_WARN); + CLI::write('[img-maps] ['.$loc->json().'] '.str_pad('['.$zoneId.']', 7).'floor count mismatch between GlobalStrings: '.$nStrings.' and image files: '.$nFloors, CLI::LOG_WARN); } ksort($zoneAreas[$lId]); @@ -732,24 +732,16 @@ CLISetup::registerSetup("build", new class extends SetupScript // don't convert numbers to int in json $toFile = "Mapper.multiLevelZones = ".Util::toJSON($this->multiLevelZones, 0x0).";\n\n"; $toFile .= "var g_zone_areas = ".Util::toJSON($zoneAreas[$lId]).";"; - $file = 'datasets/'.$loc.'/zones'; + $file = 'datasets/'.$loc->json().'/zones'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; } } - private function buildSpawnMap(/*GdImage*/ $resOverlay, int $zoneId) : void + private function buildSpawnMap(GdImage $resOverlay, int $zoneId) : void { - // GdImage: < 8.0 resource; >= 8.0 object - if (gettype($resOverlay) != 'resource' && gettype($resOverlay) != 'object') - { - CLI::write('[img-maps] - no GdImage passed to buildSpawnMap', CLI::LOG_ERROR); - $this->success = false; - return; - } - - $outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png'; + $outFile = $this->genSteps[self::M_SPAWNS][self::GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png'; if (!CLISetup::getOpt('force') && file_exists($outFile)) { @@ -777,16 +769,8 @@ CLISetup::registerSetup("build", new class extends SetupScript $this->success = false; } - private function buildSubZones(/*GdImage*/ $resMap, int $wmaId, int $locId) : void + private function buildSubZones(GdImage $resMap, int $wmaId, Locale $loc) : void { - // GdImage: < 8.0 resource; >= 8.0 object - if (gettype($resMap) != 'resource' && gettype($resMap) != 'object') - { - CLI::write('[img-maps] - no GdImage passed to buildSubZones()', CLI::LOG_ERROR); - $this->success = false; - return; - } - foreach ($this->wmOverlays[$wmaId] as &$row) { $doSkip = 0x0; @@ -794,7 +778,7 @@ CLISetup::registerSetup("build", new class extends SetupScript foreach (self::DEST_DIRS as $sizeIdx => [$path, , ]) { - $outFile[$sizeIdx] = sprintf($path, strtolower(Util::$localeStrings[$locId]).'/') . $row['areaTableId'].'.jpg'; + $outFile[$sizeIdx] = sprintf($path, $loc->json() . DIRECTORY_SEPARATOR) . $row['areaTableId'].'.jpg'; if (!CLISetup::getOpt('force') && file_exists($outFile[$sizeIdx])) { CLI::write($this->status.' - file '.$outFile[$sizeIdx].' was already processed', CLI::LOG_BLANK, true, true); @@ -822,7 +806,7 @@ CLISetup::registerSetup("build", new class extends SetupScript } } - private function generateOverlay(int $wmaId, string $basePath) // : ?GdImage + private function generateOverlay(int $wmaId, string $basePath) : ?GdImage { if (!isset($this->wmOverlays[$wmaId])) return null; diff --git a/setup/tools/filegen/itemsets.ss.php b/setup/tools/filegen/itemsets.ss.php index ea8e75c6..b00eb619 100644 --- a/setup/tools/filegen/itemsets.ss.php +++ b/setup/tools/filegen/itemsets.ss.php @@ -41,13 +41,12 @@ CLISetup::registerSetup("build", new class extends SetupScript public function generate() : bool { - $setList = DB::Aowow()->Select('SELECT * FROM ?_itemset ORDER BY refSetId DESC'); + $setList = DB::Aowow()->Select('SELECT * FROM ?_itemset ORDER BY `refSetId` DESC'); $jsonBonus = []; - foreach (CLISetup::$locales as $lId => $jsonStr) + foreach (CLISetup::$locales as $loc) { - User::useLocale($lId); - Lang::load($lId); + Lang::load($loc); $itemsetOut = []; foreach ($setList as $set) @@ -120,7 +119,7 @@ CLISetup::registerSetup("build", new class extends SetupScript } $toFile = "var g_itemsets = ".Util::toJSON($itemsetOut).";"; - $file = 'datasets/'.$jsonStr.'/itemsets'; + $file = 'datasets/'.$loc->json().'/itemsets'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; diff --git a/setup/tools/filegen/locales.ss.php b/setup/tools/filegen/locales.ss.php index 057101b1..dfd78c68 100644 --- a/setup/tools/filegen/locales.ss.php +++ b/setup/tools/filegen/locales.ss.php @@ -8,7 +8,45 @@ if (!CLI) // Create 'locale.js'-file in static/js -// available locales have to be set in aowow.aowow_config + +/* + 0: { // English + id: LOCALE_ENUS, + name: 'enus', + domain: 'en', + description: 'English' + }, + 2: { // French + id: LOCALE_FRFR, + name: 'frfr', + domain: 'fr', + description: 'Fran' + String.fromCharCode(231) + 'ais' + }, + 3: { // German + id: LOCALE_DEDE, + name: 'dede', + domain: 'de', + description: 'Deutsch' + }, + 4:{ // Chinese + id: LOCALE_ZHCN, + name: 'zhcn', + domain: 'cn', + description: String.fromCharCode(31616, 20307, 20013, 25991) + }, + 6: { // Spanish + id: LOCALE_ESES, + name: 'eses', + domain: 'es', + description: 'Espa' + String.fromCharCode(241) + 'ol' + }, + 8: { // Russian + id: LOCALE_RURU, + name: 'ruru', + domain: 'ru', + description: String.fromCharCode(1056, 1091, 1089, 1089, 1082, 1080, 1081) + } +*/ CLISetup::registerSetup("build", new class extends SetupScript { @@ -23,51 +61,17 @@ CLISetup::registerSetup("build", new class extends SetupScript private function locales() : string { - $available = array( - LOCALE_EN => " 0: { // English\r\n" . - " id: LOCALE_ENUS,\r\n" . - " name: 'enus',\r\n" . - " domain: 'en',\r\n" . - " description: 'English'\r\n" . - " }", - LOCALE_FR => " 2: { // French\r\n" . - " id: LOCALE_FRFR,\r\n" . - " name: 'frfr',\r\n" . - " domain: 'fr',\r\n" . - " description: 'Fran' + String.fromCharCode(231) + 'ais'\r\n" . - " }", - LOCALE_DE => " 3: { // German\r\n" . - " id: LOCALE_DEDE,\r\n" . - " name: 'dede',\r\n" . - " domain: 'de',\r\n" . - " description: 'Deutsch'\r\n" . - " }", - LOCALE_CN => " 4:{ // Chinese\r\n" . - " id: LOCALE_ZHCN,\r\n" . - " name: 'zhcn',\r\n" . - " domain: 'cn',\r\n" . - " description: String.fromCharCode(31616, 20307, 20013, 25991)\r\n" . - " }", - LOCALE_ES => " 6: { // Spanish\r\n" . - " id: LOCALE_ESES,\r\n" . - " name: 'eses',\r\n" . - " domain: 'es',\r\n" . - " description: 'Espa' + String.fromCharCode(241) + 'ol'\r\n" . - " }", - LOCALE_RU => " 8: { // Russian\r\n" . - " id: LOCALE_RURU,\r\n" . - " name: 'ruru',\r\n" . - " domain: 'ru',\r\n" . - " description: String.fromCharCode(1056, 1091, 1089, 1089, 1082, 1080, 1081)\r\n" . - " }", - ); - $result = []; - foreach (CLISetup::$locales as $l => $_) - if (isset($available[$l])) - $result[] = $available[$l]; - return implode(",\r\n", $result); + foreach (CLISetup::$locales as $loc) + $result[$loc->value] = array( + 'id' => '$LOCALE_' . strtoupper($loc->json()), + 'name' => $loc->json(), + 'domain' => $loc->domain(), + 'description' => $loc->title() + ); + + return Util::toJSON($result); } }); diff --git a/setup/tools/filegen/pets.ss.php b/setup/tools/filegen/pets.ss.php index 553d7b66..0b32f220 100644 --- a/setup/tools/filegen/pets.ss.php +++ b/setup/tools/filegen/pets.ss.php @@ -39,28 +39,29 @@ CLISetup::registerSetup("build", new class extends SetupScript public function generate() : bool { $petList = DB::Aowow()->Select( - 'SELECT cr.id, - cr.name_loc0, cr.name_loc2, cr.name_loc3, cr.name_loc4, cr.name_loc6, cr.name_loc8, - cr.minLevel, cr.maxLevel, - ft.A, ft.H, - cr.rank AS classification, - cr.family, - cr.displayId1 AS displayId, - cr.textureString AS skin, - LOWER(SUBSTRING_INDEX(cf.iconString, "\\\\", -1)) AS icon, - cf.petTalentType AS type - FROM ?_creature cr - JOIN ?_factiontemplate ft ON ft.id = cr.faction - JOIN dbc_creaturefamily cf ON cf.id = cr.family - WHERE cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0 - ORDER BY cr.id ASC'); + 'SELECT cr.`id`, + cr.`name_loc0`, cr.`name_loc2`, cr.`name_loc3`, cr.`name_loc4`, cr.`name_loc6`, cr.`name_loc8`, + cr.`minLevel`, cr.`maxLevel`, + ft.`A`, ft.`H`, + cr.`rank` AS "classification", + cr.`family`, + cr.`displayId1` AS "displayId", + cr.`textureString` AS "skin", + LOWER(SUBSTRING_INDEX(cf.`iconString`, "\\\\", -1)) AS "icon", + cf.`petTalentType` AS "type" + FROM ?_creature cr + JOIN ?_factiontemplate ft ON ft.`id` = cr.`faction` + JOIN dbc_creaturefamily cf ON cf.`id` = cr.`family` + WHERE cr.`typeFlags` & 0x1 AND (cr.`cuFlags` & ?d) = 0 + ORDER BY cr.`id` ASC', + NPC_CU_DIFFICULTY_DUMMY + ); $locations = DB::Aowow()->selectCol('SELECT `typeId` AS ARRAY_KEY, `areaId` AS ARRAY_KEY2, `areaId` FROM ?_spawns WHERE `type` = ?d AND `typeId` IN (?a) GROUP BY `typeId`, `areaId`', Type::NPC, array_column($petList, 'id')); - foreach (CLISetup::$locales as $lId => $jsonStr) + foreach (CLISetup::$locales as $loc) { - User::useLocale($lId); - Lang::load($lId); + Lang::load($loc); $petsOut = []; foreach ($petList as $pet) @@ -82,7 +83,7 @@ CLISetup::registerSetup("build", new class extends SetupScript } $toFile = "var g_pets = ".Util::toJSON($petsOut).";"; - $file = 'datasets/'.$jsonStr.'/pets'; + $file = 'datasets/'.$loc->json().'/pets'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; diff --git a/setup/tools/filegen/profiler.ss.php b/setup/tools/filegen/profiler.ss.php index 7079c0d3..fab85d9d 100644 --- a/setup/tools/filegen/profiler.ss.php +++ b/setup/tools/filegen/profiler.ss.php @@ -90,12 +90,11 @@ CLISetup::registerSetup("build", new class extends SetupScript $relCurr = new CurrencyList(array(['id', $_])); - foreach (CLISetup::$locales as $l => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(20); - User::useLocale($l); - Lang::load($l); + Lang::load($loc); if (!$relCurr->error) { @@ -108,7 +107,7 @@ CLISetup::registerSetup("build", new class extends SetupScript foreach ($questz->getListviewData() as $id => $data) $buff .= '_['.$id.'] = '.Util::toJSON($data).";\n"; - if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-quests-'.$cat2, $buff)) + if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-quests-'.$cat2, $buff)) $this->success = false; } } @@ -132,15 +131,14 @@ CLISetup::registerSetup("build", new class extends SetupScript // get titles for exclusion foreach ($titlez->iterate() as $id => $__) - if (empty($titlez->sources[$id][4]) && empty($titlez->sources[$id][12])) + if (empty($titlez->sources[$id][SRC_QUEST]) && empty($titlez->sources[$id][SRC_ACHIEVEMENT])) $this->addExclusion(Type::TITLE, $id, PR_EXCLUDE_GROUP_UNAVAILABLE); - foreach (CLISetup::$locales as $l => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(5); - User::useLocale($l); - Lang::load($l); + Lang::load($loc); foreach ([GENDER_MALE, GENDER_FEMALE] as $g) { @@ -152,7 +150,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $buff .= '_['.$id.'] = '.Util::toJSON($data).";\n"; } - if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-titles-'.$g, $buff)) + if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-titles-'.$g, $buff)) $this->success = false; } } @@ -168,7 +166,7 @@ CLISetup::registerSetup("build", new class extends SetupScript ); $mountz = new SpellList($condition); - $conditionSet = DB::World()->selectCol('SELECT SourceEntry AS ARRAY_KEY, ConditionValue1 FROM conditions WHERE SourceTypeOrReferenceId = ?d AND ConditionTypeOrReference = ?d AND SourceEntry IN (?a)', Conditions::SRC_SPELL, Conditions::SKILL, $mountz->getFoundIDs()); + $conditionSet = DB::World()->selectCol('SELECT `SourceEntry` AS ARRAY_KEY, `ConditionValue1` FROM conditions WHERE `SourceTypeOrReferenceId` = ?d AND `ConditionTypeOrReference` = ?d AND `SourceEntry` IN (?a)', Conditions::SRC_SPELL, Conditions::SKILL, $mountz->getFoundIDs()); // get mounts for exclusion foreach ($conditionSet as $mount => $skill) @@ -179,12 +177,11 @@ CLISetup::registerSetup("build", new class extends SetupScript if (!$mountz->getSources()) $this->addExclusion(Type::SPELL, $id, PR_EXCLUDE_GROUP_UNAVAILABLE); - foreach (CLISetup::$locales as $l => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(5); - User::useLocale($l); - Lang::load($l); + Lang::load($loc); $buff = "var _ = g_spells;\n"; foreach ($mountz->getListviewData(ITEMINFO_MODEL) as $id => $data) @@ -203,7 +200,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $buff .= '_['.$id.'] = '.Util::toJSON($data).";\n"; } - if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-mounts', $buff)) + if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-mounts', $buff)) $this->success = false; } } @@ -222,12 +219,11 @@ CLISetup::registerSetup("build", new class extends SetupScript if (!$companionz->getSources()) $this->addExclusion(Type::SPELL, $id, PR_EXCLUDE_GROUP_UNAVAILABLE); - foreach (CLISetup::$locales as $l => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(5); - User::useLocale($l); - Lang::load($l); + Lang::load($loc); $buff = "var _ = g_spells;\n"; foreach ($companionz->getListviewData(ITEMINFO_MODEL) as $id => $data) @@ -241,7 +237,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $buff .= '_['.$id.'] = '.Util::toJSON($data).";\n"; } - if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-companions', $buff)) + if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-companions', $buff)) $this->success = false; } } @@ -254,12 +250,11 @@ CLISetup::registerSetup("build", new class extends SetupScript ); $factionz = new FactionList($condition); - foreach (CLISetup::$locales as $l => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(5); - User::useLocale($l); - Lang::load($l); + Lang::load($loc); $buff = "var _ = g_factions;\n"; foreach ($factionz->getListviewData() as $id => $data) @@ -267,7 +262,7 @@ CLISetup::registerSetup("build", new class extends SetupScript $buff .= "\ng_faction_order = [0, 469, 891, 1037, 1118, 67, 1052, 892, 936, 1117, 169, 980, 1097];\n"; - if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-factions', $buff)) + if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-factions', $buff)) $this->success = false; } } @@ -284,8 +279,10 @@ CLISetup::registerSetup("build", new class extends SetupScript $baseCnd = array( Cfg::get('SQL_LIMIT_NONE'), [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0], - ['effect1Id', [6, 45, 57, 127, 33, 158, 99, 28, 95], '!'], // aura, tradeSkill, Tracking, Prospecting, Decipher, Milling, Disenchant, Summon (Engineering), Skinning - ['effect2Id', [118, 60], '!'], // not the skill itself + // Inscryption Engineering + ['effect1Id', [SPELL_EFFECT_APPLY_AURA, SPELL_EFFECT_TRADE_SKILL, SPELL_EFFECT_PROSPECTING, SPELL_EFFECT_OPEN_LOCK, SPELL_EFFECT_MILLING, SPELL_EFFECT_DISENCHANT, SPELL_EFFECT_SUMMON, SPELL_EFFECT_SKINNING], '!'], + // not the skill itself + ['effect2Id', [SPELL_EFFECT_SKILL, SPELL_EFFECT_PROFICIENCY], '!'], ['OR', ['typeCat', 9], ['typeCat', 11]] ); @@ -307,12 +304,11 @@ CLISetup::registerSetup("build", new class extends SetupScript } } - foreach (CLISetup::$locales as $l => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(10); - User::useLocale($l); - Lang::load($l); + Lang::load($loc); $buff = ''; foreach ($recipez->getListviewData() as $id => $data) @@ -324,7 +320,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if (!$buff) { // this behaviour is intended, do not create an error - CLI::write('[profiler] - file datasets/'.$jsonStr.'/p-recipes-'.$file.' has no content => skipping', CLI::LOG_INFO); + CLI::write('[profiler] - file datasets/'.$loc->json().'/p-recipes-'.$file.' has no content => skipping', CLI::LOG_INFO); continue; } @@ -333,7 +329,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if (is_array($s)) $buff .= "\ng_skill_order = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356];\n"; - if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-recipes-'.$file, $buff)) + if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-recipes-'.$file, $buff)) $this->success = false; } } @@ -348,12 +344,11 @@ CLISetup::registerSetup("build", new class extends SetupScript ); $achievez = new AchievementList($condition); - foreach (CLISetup::$locales as $l => $jsonStr) + foreach (CLISetup::$locales as $loc) { set_time_limit(5); - User::useLocale($l); - Lang::load($l); + Lang::load($loc); $sumPoints = 0; $buff = "var _ = g_achievements;\n"; @@ -368,7 +363,7 @@ CLISetup::registerSetup("build", new class extends SetupScript // sum points $buff .= "\ng_achievement_points = [".$sumPoints."];\n"; - if (!CLISetup::writeFile('datasets/'.$jsonStr.'/achievements', $buff)) + if (!CLISetup::writeFile('datasets/'.$loc->json().'/achievements', $buff)) $this->success = false; } } @@ -378,7 +373,7 @@ CLISetup::registerSetup("build", new class extends SetupScript set_time_limit(2); CLI::write('[profiler] applying '.count($this->exclusions).' baseline exclusions'); - DB::Aowow()->query('DELETE FROM ?_profiler_excludes WHERE comment = ""'); + DB::Aowow()->query('DELETE FROM ?_profiler_excludes WHERE `comment` = ""'); foreach ($this->exclusions as $ex) DB::Aowow()->query('REPLACE INTO ?_profiler_excludes (?#) VALUES (?a)', array_keys($ex), array_values($ex)); @@ -389,10 +384,10 @@ CLISetup::registerSetup("build", new class extends SetupScript $exData = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, `typeId` AS ARRAY_KEY2, `groups` FROM ?_profiler_excludes'); for ($i = 0; (1 << $i) < PR_EXCLUDE_GROUP_ANY; $i++) foreach ($exData as $type => $data) - if ($ids = array_keys(array_filter($data, function ($x) use ($i) { return $x & (1 << $i); } ))) + if ($ids = array_keys(array_filter($data, fn($x) => $x & (1 << $i)))) $excludes[$type][$i + 1] = $ids; - $buff = "g_excludes = ".Util::toJSON($excludes ?: (new Stdclass)).";\n"; + $buff = "g_excludes = ".Util::toJSON($excludes ?: (new StdClass)).";\n"; if (!CLISetup::writeFile('datasets/quick-excludes', $buff)) $this->success = false; @@ -400,13 +395,13 @@ CLISetup::registerSetup("build", new class extends SetupScript private function getExcludeForSkill(int $skillId) : int { - switch ($skillId) + return match ($skillId) { - case SKILL_FISHING: return PR_EXCLUDE_GROUP_REQ_FISHING; - case SKILL_ENGINEERING: return PR_EXCLUDE_GROUP_REQ_ENGINEERING; - case SKILL_TAILORING: return PR_EXCLUDE_GROUP_REQ_TAILORING; - default: return 0; - } + SKILL_FISHING => PR_EXCLUDE_GROUP_REQ_FISHING, + SKILL_ENGINEERING => PR_EXCLUDE_GROUP_REQ_ENGINEERING, + SKILL_TAILORING => PR_EXCLUDE_GROUP_REQ_TAILORING, + default => 0 + }; } private function addExclusion(int $type, int $typeId, int $groups, string $comment = '') : void @@ -423,7 +418,7 @@ CLISetup::registerSetup("build", new class extends SetupScript } } - private function sumTotal (array &$sumArr, int $raceMask = -1, int $classMask= -1) : void + private function sumTotal(array &$sumArr, int $raceMask = -1, int $classMask= -1) : void { for ($i = 0; $i < RACE_MASK_ALL; $i++) { diff --git a/setup/tools/filegen/realmmenu.ss.php b/setup/tools/filegen/realmmenu.ss.php index 61c6c8ce..08180f9d 100644 --- a/setup/tools/filegen/realmmenu.ss.php +++ b/setup/tools/filegen/realmmenu.ss.php @@ -74,8 +74,7 @@ CLISetup::registerSetup("build", new class extends SetupScript CLI::write('[realmmenu] no viable realms found .. realm menu will be empty', CLI::LOG_WARN); // why is this file not localized!? - User::useLocale(LOCALE_EN); - Lang::load(LOCALE_EN); + Lang::load(Locale::EN); foreach (Util::$regions as $idx => $n) if ($set & (1 << $idx)) diff --git a/setup/tools/filegen/simpleimg.ss.php b/setup/tools/filegen/simpleimg.ss.php index 2eace248..81d811d5 100644 --- a/setup/tools/filegen/simpleimg.ss.php +++ b/setup/tools/filegen/simpleimg.ss.php @@ -118,18 +118,18 @@ CLISetup::registerSetup("build", new class extends SetupScript $this->maxExecTime = ini_get('max_execution_time'); // init directories to be checked when registered - foreach (array_column($this->genSteps, self::$GEN_IDX_DEST_INFO) as $subDirs) + foreach (array_column($this->genSteps, self::GEN_IDX_DEST_INFO) as $subDirs) foreach ($subDirs as $sd) $this->requiredDirs[] = $sd[0]; // fix genSteps 2 [icons] - no tiny inventory backgrounds - $this->genSteps[2][self::$GEN_IDX_DEST_INFO] = array_slice($this->genSteps[2][self::$GEN_IDX_DEST_INFO], 0, 3); + $this->genSteps[2][self::GEN_IDX_DEST_INFO] = array_slice($this->genSteps[2][self::GEN_IDX_DEST_INFO], 0, 3); // fix genSteps 12 [pvp money icons] - smaller border offset for pvp currency icons - array_walk($this->genSteps[12][self::$GEN_IDX_DEST_INFO], function(&$x) { $x[4] = 2; }); + array_walk($this->genSteps[12][self::GEN_IDX_DEST_INFO], function(&$x) { $x[4] = 2; }); // fix genSteps 10 [holoday icons] - img src size is 90px - array_walk($this->genSteps[10][self::$GEN_IDX_DEST_INFO], function(&$x) { $x[2] = 90; }); + array_walk($this->genSteps[10][self::GEN_IDX_DEST_INFO], function(&$x) { $x[2] = 90; }); } public function generate() : bool @@ -154,7 +154,7 @@ CLISetup::registerSetup("build", new class extends SetupScript if (!in_array($idx, $groups)) unset($this->genSteps[$idx]); else - $this->genSteps[$idx][self::$GEN_IDX_SRC_REAL] = null; + $this->genSteps[$idx][self::GEN_IDX_SRC_REAL] = null; } if (!$this->checkSourceDirs()) @@ -340,24 +340,24 @@ CLISetup::registerSetup("build", new class extends SetupScript { if ($siRows = DB::Aowow()->selectCol('SELECT `iconPath` FROM dbc_spellicon WHERE `iconPath` NOT LIKE "%glyph-rune%"')) foreach ($siRows as $icon) - if (stristr($icon, $this->genSteps[0][self::$GEN_IDX_SRC_PATH])) // Icons/ - $dbcEntries[] = strtolower($this->genSteps[0][self::$GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1)); + if (stristr($icon, $this->genSteps[0][self::GEN_IDX_SRC_PATH])) // Icons/ + $dbcEntries[] = strtolower($this->genSteps[0][self::GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1)); if ($itemIcons = DB::Aowow()->selectCol('SELECT `inventoryIcon1` FROM dbc_itemdisplayinfo WHERE `inventoryIcon1` <> ""')) foreach ($itemIcons as $icon) - $dbcEntries[] = strtolower($this->genSteps[0][self::$GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon); + $dbcEntries[] = strtolower($this->genSteps[0][self::GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon); } if (in_array(1, $gens)) // generates glyphs if ($siRows = DB::Aowow()->selectCol('SELECT `iconPath` FROM dbc_spellicon WHERE `iconPath` LIKE "%glyph-rune%"')) foreach ($siRows as $icon) - if (stristr($icon, $this->genSteps[1][self::$GEN_IDX_SRC_PATH])) // Spellbook/ - $dbcEntries[] = strtolower($this->genSteps[1][self::$GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1)); + if (stristr($icon, $this->genSteps[1][self::GEN_IDX_SRC_PATH])) // Spellbook/ + $dbcEntries[] = strtolower($this->genSteps[1][self::GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1)); if (in_array(10, $gens)) // generates holiday icons if ($eventIcons = DB::Aowow()->selectCol('SELECT `textureString` FROM dbc_holidays WHERE `textureString` <> ""')) foreach ($eventIcons as $icon) - $dbcEntries[] = strtolower($this->genSteps[10][self::$GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon.'start'); + $dbcEntries[] = strtolower($this->genSteps[10][self::GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon.'start'); // case-insensitive array_unique *vomits silently into a corner* $dbcEntries = array_intersect_key($dbcEntries, array_unique($dbcEntries)); diff --git a/setup/tools/filegen/soundfiles.ss.php b/setup/tools/filegen/soundfiles.ss.php index 9716e24d..620be989 100644 --- a/setup/tools/filegen/soundfiles.ss.php +++ b/setup/tools/filegen/soundfiles.ss.php @@ -19,7 +19,7 @@ CLISetup::registerSetup("build", new class extends SetupScript public function generate() : bool { // ALL files - $files = DB::Aowow()->selectCol('SELECT ABS(id) AS ARRAY_KEY, CONCAT(path, "/", `file`) FROM ?_sounds_files'); + $files = DB::Aowow()->selectCol('SELECT ABS(`id`) AS ARRAY_KEY, CONCAT(`path`, "/", `file`) FROM ?_sounds_files'); $nFiles = count($files); $qtLen = strlen($nFiles); $sum = 0; @@ -37,31 +37,31 @@ CLISetup::registerSetup("build", new class extends SetupScript // expect converted files as file.wav_ or file.mp3_ $filePath .= '_'; - // just use the first locale available .. there is no support for multiple audio files anyway - foreach (CLISetup::$expectedPaths as $locStr => $__) + // just use the first locale available .. there is no support for multiple audio files for now + foreach (CLISetup::$locales as $loc) { - // get your paths straight! - $p = CLI::nicePath($filePath, CLISetup::$srcDir, $locStr); - - if (CLISetup::fileExists($p)) + foreach ($loc->gameDirs() as $dir) { - // copy over to static/wowsounds/ - if (!copy($p, 'static/wowsounds/'.$fileId)) - { - $this->success = false; - CLI::write('[soundfiles] - could not copy '.CLI::bold($p).' into '.CLI::bold('static/wowsounds/'.$fileId), CLI::LOG_ERROR); - $time->reset(); - break 2; - } + // get your paths straight! + $p = CLI::nicePath($filePath, CLISetup::$srcDir, $dir); - continue 2; + if (!CLISetup::fileExists($p)) + continue; + + // copy over to static/wowsounds/ + if (copy($p, 'static/wowsounds/'.$fileId)) + continue 3; + + $this->success = false; + CLI::write('[soundfiles] - could not copy '.CLI::bold($p).' into '.CLI::bold('static/wowsounds/'.$fileId), CLI::LOG_ERROR); + $time->reset(); } } - CLI::write('[soundfiles] - did not find file: '.CLI::bold(CLI::nicePath($filePath, CLISetup::$srcDir, '['.implode(',', CLISetup::$locales).']')), CLI::LOG_WARN); + CLI::write('[soundfiles] - did not find file: '.CLI::bold(CLI::nicePath($filePath, CLISetup::$srcDir, '['.implode(',', array_map(fn($x) => $x->json(), CLISetup::$locales)).']')), CLI::LOG_WARN); $time->reset(); // flag as unusable in DB - DB::Aowow()->query('UPDATE ?_sounds_files SET id = ?d WHERE ABS(id) = ?d', -$fileId, $fileId); + DB::Aowow()->query('UPDATE ?_sounds_files SET `id` = ?d WHERE ABS(`id`) = ?d', -$fileId, $fileId); } return $this->success; diff --git a/setup/tools/filegen/talentcalc.ss.php b/setup/tools/filegen/talentcalc.ss.php index db0ae0c1..671a3555 100644 --- a/setup/tools/filegen/talentcalc.ss.php +++ b/setup/tools/filegen/talentcalc.ss.php @@ -49,15 +49,14 @@ CLISetup::registerSetup("build", new class extends SetupScript $this->petFamIcons = ['Ability_Druid_KingoftheJungle', 'Ability_Druid_DemoralizingRoar', 'Ability_EyeOfTheOwl']; // .. i've no idea where to fetch these from $this->spellMods = (new SpellList(array(['typeCat', -2], Cfg::get('SQL_LIMIT_NONE'))))->getProfilerMods(); - $petIcons = Util::toJSON(DB::Aowow()->SelectCol('SELECT id AS ARRAY_KEY, LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)) AS iconString FROM dbc_creaturefamily WHERE petTalentType IN (0, 1, 2)')); + $petIcons = Util::toJSON(DB::Aowow()->SelectCol('SELECT `id` AS ARRAY_KEY, LOWER(SUBSTRING_INDEX(`iconString`, "\\\\", -1)) AS "iconString" FROM dbc_creaturefamily WHERE `petTalentType` IN (0, 1, 2)')); - $tSpellIds = DB::Aowow()->selectCol('SELECT rank1 FROM dbc_talent UNION SELECT rank2 FROM dbc_talent UNION SELECT rank3 FROM dbc_talent UNION SELECT rank4 FROM dbc_talent UNION SELECT rank5 FROM dbc_talent'); + $tSpellIds = DB::Aowow()->selectCol('SELECT `rank1` FROM dbc_talent UNION SELECT `rank2` FROM dbc_talent UNION SELECT `rank3` FROM dbc_talent UNION SELECT `rank4` FROM dbc_talent UNION SELECT `rank5` FROM dbc_talent'); $this->tSpells = new SpellList(array(['s.id', $tSpellIds], Cfg::get('SQL_LIMIT_NONE'))); - foreach (CLISetup::$locales as $lId => $jsonStr) + foreach (CLISetup::$locales as $loc) { - User::useLocale($lId); - Lang::load($lId); + Lang::load($loc); // TalentCalc for ($i = 1; (1 << ($i - 1)) < CLASS_MASK_ALL; $i++ ) @@ -67,7 +66,7 @@ CLISetup::registerSetup("build", new class extends SetupScript set_time_limit(20); - $file = 'datasets/'.$jsonStr.'/talents-'.$i; + $file = 'datasets/'.$loc->json().'/talents-'.$i; $toFile = '$WowheadTalentCalculator.registerClass('.$i.', '.Util::toJSON($this->buildTree(1 << ($i - 1))).')'; if (!CLISetup::writeFile($file, $toFile)) @@ -77,7 +76,7 @@ CLISetup::registerSetup("build", new class extends SetupScript // PetCalc $toFile = "var g_pet_icons = ".$petIcons.";\n\n"; $toFile .= 'var g_pet_talents = '.Util::toJSON($this->buildTree(0)).';'; - $file = 'datasets/'.$jsonStr.'/pet-talents'; + $file = 'datasets/'.$loc->json().'/pet-talents'; if (!CLISetup::writeFile($file, $toFile)) $this->success = false; @@ -91,12 +90,21 @@ CLISetup::registerSetup("build", new class extends SetupScript $petCategories = []; // All "tabs" of a given class talent - $tabs = DB::Aowow()->select('SELECT * FROM dbc_talenttab WHERE classMask = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $classMask); + $tabs = DB::Aowow()->select('SELECT * FROM dbc_talenttab WHERE `classMask` = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $classMask); $result = []; for ($tabIdx = 0; $tabIdx < count($tabs); $tabIdx++) { - $talents = DB::Aowow()->select('SELECT t.id AS tId, t.*, IF(t.rank5, 5, IF(t.rank4, 4, IF(t.rank3, 3, IF(t.rank2, 2, 1)))) AS maxRank, s.name_loc0, s.name_loc2, s.name_loc3, s.name_loc4, s.name_loc6, s.name_loc8, LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AS iconString FROM dbc_talent t, dbc_spell s, dbc_spellicon si WHERE si.`id` = s.`iconId` AND t.`tabId`= ?d AND s.`id` = t.`rank1` ORDER by t.`row`, t.`column`', $tabs[$tabIdx]['id']); + $talents = DB::Aowow()->select( + 'SELECT t.id AS "tId", t.*, IF(t.rank5, 5, IF(t.rank4, 4, IF(t.rank3, 3, IF(t.rank2, 2, 1)))) AS "maxRank", + s.`name_loc0`, s.`name_loc2`, s.`name_loc3`, s.`name_loc4`, s.`name_loc6`, s.`name_loc8`, + LOWER(SUBSTRING_INDEX(si.`iconPath`, "\\\\", -1)) AS "iconString" + FROM dbc_talent t, dbc_spell s, dbc_spellicon si + WHERE si.`id` = s.`iconId` AND t.`tabId`= ?d AND s.`id` = t.`rank1` + ORDER BY t.`row`, t.`column`', + $tabs[$tabIdx]['id'] + ); + $result[$tabIdx] = array( 'n' => Util::localizedString($tabs[$tabIdx], 'name'), 't' => [] @@ -106,7 +114,7 @@ CLISetup::registerSetup("build", new class extends SetupScript { $petFamId = log($tabs[$tabIdx]['creatureFamilyMask'], 2); $result[$tabIdx]['icon'] = $this->petFamIcons[$petFamId]; - $petCategories = DB::Aowow()->SelectCol('SELECT id AS ARRAY_KEY, categoryEnumID FROM dbc_creaturefamily WHERE petTalentType = ?d', $petFamId); + $petCategories = DB::Aowow()->SelectCol('SELECT `id` AS ARRAY_KEY, `categoryEnumID` FROM dbc_creaturefamily WHERE `petTalentType` = ?d', $petFamId); $result[$tabIdx]['f'] = array_keys($petCategories); } diff --git a/setup/tools/filegen/templates/locale.js.in b/setup/tools/filegen/templates/locale.js.in index 6786ca94..9b712aeb 100644 --- a/setup/tools/filegen/templates/locale.js.in +++ b/setup/tools/filegen/templates/locale.js.in @@ -14,9 +14,7 @@ var Locale = { current: {}, // All - locales: { -/*setup:locales*/ - }, + locales: /*setup:locales*/, getAll: function() { var result = []; diff --git a/setup/tools/setupScript.class.php b/setup/tools/setupScript.class.php index a58dd71a..a6f9896d 100644 --- a/setup/tools/setupScript.class.php +++ b/setup/tools/setupScript.class.php @@ -136,17 +136,17 @@ trait TrTemplateFile trait TrImageProcessor { - private $imgPath = '%sInterface/'; - private $status = ''; - private $maxExecTime = 30; + private $imgPath = '%sInterface/'; + private $status = ''; + private $maxExecTime = 30; - private static $GEN_IDX_SRC_PATH = 0; // php v8.0 make static > const - private static $GEN_IDX_SRC_REAL = 1; - private static $GEN_IDX_LOCALE = 2; - private static $GEN_IDX_SRC_INFO = 3; - private static $GEN_IDX_DEST_INFO = 4; + private const GEN_IDX_SRC_PATH = 0; + private const GEN_IDX_SRC_REAL = 1; + private const GEN_IDX_LOCALE = 2; + private const GEN_IDX_SRC_INFO = 3; + private const GEN_IDX_DEST_INFO = 4; - private static $JPEG_QUALITY = 85; // 0: worst - 100: best + private const JPEG_QUALITY = 85; // 0: worst - 100: best private function checkSourceDirs() : bool { @@ -161,7 +161,7 @@ trait TrImageProcessor // multiple genSteps can require the same resource if (isset($foundCache[$subDir])) { - $this->genSteps[$i][self::$GEN_IDX_SRC_REAL] = $foundCache[$subDir]; + $this->genSteps[$i][self::GEN_IDX_SRC_REAL] = $foundCache[$subDir]; continue; } @@ -171,16 +171,20 @@ trait TrImageProcessor if ($p = CLISetup::filesInPathLocalized($path, $this->success, $localized)) { $foundCache[$subDir] = $p; - $this->genSteps[$i][self::$GEN_IDX_SRC_REAL] = $p; // php v8.2+ - make GEN_IDX_SRC_REAL a const + $this->genSteps[$i][self::GEN_IDX_SRC_REAL] = $p; } else $this->success = false; } $locList = []; - foreach (CLISetup::$expectedPaths as $xp => $locId) - if (in_array($locId, array_keys(CLISetup::$locales))) - $locList[] = $xp; + foreach (Locale::cases() as $loc) + { + if (!$loc->validate() || !in_array($loc, CLISetup::$locales)) + continue; + + $locList = array_merge($locList, $loc->gameDirs()); + } CLI::write('[img-proc] required resources overview:', CLI::LOG_INFO); @@ -194,29 +198,29 @@ trait TrImageProcessor $foundCache[$subDir] = true; if (!$realPaths) { - CLI::write(CLI::red('MISSING').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/,', $locList).'/]').$subDir); + CLI::write(CLI::red('MISSING').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/ ', $locList).'/]').$subDir); $this->success = false; } else if ($localized) { $foundLoc = []; - foreach (CLISetup::$expectedPaths as $xp => $lId) - if (in_array($lId, array_keys(CLISetup::$locales))) + foreach (CLISetup::$locales as $lId => $loc) + foreach ($loc->gameDirs() as $xp) if (isset($realPaths[$lId]) && ($n = stripos($realPaths[$lId], DIRECTORY_SEPARATOR.$xp.DIRECTORY_SEPARATOR))) $foundLoc[$lId] = substr($realPaths[$lId], $n + 1, 4); if ($diff = array_diff_key(CLISetup::$locales, $foundLoc)) { $buff = []; - foreach ($diff as $d => $_) - $buff[] = CLI::red(Util::$localeStrings[$d]); + foreach ($diff as $loc) + $buff[] = CLI::red($loc->json()); foreach ($foundLoc as $str) $buff[] = CLI::green($str); - CLI::write(CLI::yellow('PARTIAL').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/,', $buff).'/]').$subDir); + CLI::write(CLI::yellow('PARTIAL').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/ ', $buff).'/]').$subDir); } else - CLI::write(CLI::green('FOUND ').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/,', $foundLoc).'/]').$subDir); + CLI::write(CLI::green('FOUND ').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/ ', $foundLoc).'/]').$subDir); } else CLI::write(CLI::green('FOUND ').' - '.str_pad($subDir, $outTblLen).' @ '.reset($realPaths)); @@ -227,7 +231,7 @@ trait TrImageProcessor // if not localized directly return result foreach ($this->genSteps as $i => [$subDir, $realPaths, $localized, , ]) if (!$localized && $realPaths) - $this->genSteps[$i][self::$GEN_IDX_SRC_REAL] = reset($realPaths); + $this->genSteps[$i][self::GEN_IDX_SRC_REAL] = reset($realPaths); return $this->success; } @@ -235,7 +239,7 @@ trait TrImageProcessor // prefer manually converted PNG files (as the imagecreatefromblp-script has issues with some formats) // alpha channel issues observed with locale deDE Hilsbrad and Elwynn - maps // see: https://github.com/Kanma/BLPConverter - private function loadImageFile(string $path, ?bool &$noSrc = false) // : ?GdImage + private function loadImageFile(string $path, ?bool &$noSrc = false) : ?GdImage { $result = null; $noSrc = false; @@ -260,7 +264,7 @@ trait TrImageProcessor return $result; } - private function writeImageFile(/* GdImage */ $src, string $outFile, array $srcDims, array $destDims) : bool + private function writeImageFile(GdImage $src, string $outFile, array $srcDims, array $destDims) : bool { $success = false; $outRes = imagecreatetruecolor($destDims['w'], $destDims['h']); @@ -279,7 +283,7 @@ trait TrImageProcessor switch ($ext) { case 'jpg': - $success = imagejpeg($outRes, $outFile, self::$JPEG_QUALITY); + $success = imagejpeg($outRes, $outFile, self::JPEG_QUALITY); break; case 'gif': $success = imagegif($outRes, $outFile); @@ -309,7 +313,7 @@ trait TrComplexImage { use TrImageProcessor { TrImageProcessor::writeImageFile as _writeImageFile; } - private function writeImageFile(/* GdImage */ $src, string $outFile, int $w, int $h) : bool + private function writeImageFile(GdImage $src, string $outFile, int $w, int $h) : bool { $srcDims = array( 'x' => 0, @@ -327,7 +331,7 @@ trait TrComplexImage return $this->_writeImageFile($src, $outFile, $srcDims, $destDims); } - private function createAlphaImage(int $w, int $h) //: ?GdImage + private function createAlphaImage(int $w, int $h) : ?GdImage { $img = imagecreatetruecolor($w, $h); if (!$img) @@ -347,7 +351,7 @@ trait TrComplexImage return $img; } - private function assembleImage(string $baseName, array $tileData, int $destW, int $destH) //: ?GdImage + private function assembleImage(string $baseName, array $tileData, int $destW, int $destH) : ?GdImage { $dest = imagecreatetruecolor($destW, $destH); if (!$dest) @@ -464,8 +468,8 @@ abstract class SetupScript if (!$this->localized) $dirs[] = $dir; else - foreach (CLISetup::$locales as $str) - $dirs[] = $dir . $str . DIRECTORY_SEPARATOR; + foreach (CLISetup::$locales as $loc) + $dirs[] = $dir . $loc->json() . DIRECTORY_SEPARATOR; foreach ($dirs as $d) { diff --git a/setup/tools/sqlgen/achievement.ss.php b/setup/tools/sqlgen/achievement.ss.php index 79187456..3baee0b9 100644 --- a/setup/tools/sqlgen/achievement.ss.php +++ b/setup/tools/sqlgen/achievement.ss.php @@ -74,14 +74,14 @@ CLISetup::registerSetup('sql', new class extends SetupScript CLI::write('[achievement] - serverside achievement data'); - $serverAchievements = DB::World()->select('SELECT ID AS "id", IF(requiredFaction = -1, 3, IF(requiredFaction = 0, 2, 1)) AS "faction", mapID AS "map", points, flags, count AS "reqCriteriaCount", refAchievement FROM achievement_dbc{ WHERE id IN (?a)}', + $serverAchievements = DB::World()->select('SELECT `ID` AS "id", IF(`requiredFaction` = -1, 3, IF(`requiredFaction` = 0, 2, 1)) AS "faction", `mapID` AS "map", `points`, `flags`, `count` AS "reqCriteriaCount", `refAchievement` FROM achievement_dbc{ WHERE `id` IN (?a)}', $ids ?: DBSIMPLE_SKIP ); foreach ($serverAchievements as &$sa) { $sa['cuFlags'] = CUSTOM_SERVERSIDE; - foreach (Util::$localeStrings as $i => $_) + foreach (CLISetup::$locales as $i => $_) if ($_) $sa['name_loc'.$i] = 'Serverside - #'.$sa['id']; } @@ -98,11 +98,11 @@ CLISetup::registerSetup('sql', new class extends SetupScript CLI::write('[achievement] - linking achievements to chain'); - $parents = DB::Aowow()->selectCol('SELECT a.id FROM dbc_achievement a JOIN dbc_achievement b ON b.previous = a.id WHERE a.previous = 0'); + $parents = DB::Aowow()->selectCol('SELECT a.`id` FROM dbc_achievement a JOIN dbc_achievement b ON b.`previous` = a.`id` WHERE a.`previous` = 0'); foreach ($parents as $chainId => $next) { $tree = [null, $next]; - while ($next = DB::Aowow()->selectCell('SELECT id FROM dbc_achievement WHERE previous = ?d', $next)) + while ($next = DB::Aowow()->selectCell('SELECT `id` FROM dbc_achievement WHERE `previous` = ?d', $next)) $tree[] = $next; foreach ($tree as $idx => $aId) @@ -110,7 +110,7 @@ CLISetup::registerSetup('sql', new class extends SetupScript if (!$aId) continue; - DB::Aowow()->query('UPDATE ?_achievement SET cuFlags = cuFlags | ?d, chainId = ?d, chainPos = ?d WHERE id = ?d', + DB::Aowow()->query('UPDATE ?_achievement SET `cuFlags` = `cuFlags` | ?d, `chainId` = ?d, `chainPos` = ?d WHERE `id` = ?d', $idx == 1 ? ACHIEVEMENT_CU_FIRST_SERIES : (count($tree) == $idx + 1 ? ACHIEVEMENT_CU_LAST_SERIES : 0), $chainId + 1, $idx, @@ -126,8 +126,8 @@ CLISetup::registerSetup('sql', new class extends SetupScript CLI::write('[achievement] - disabling disabled achievements from table disables'); - if ($criteria = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 4')) - DB::Aowow()->query('UPDATE ?_achievement a JOIN ?_achievementcriteria ac ON a.id = ac.refAchievementId SET a.cuFlags = ?d WHERE ac.id IN (?a)', CUSTOM_DISABLED, $criteria); + if ($criteria = DB::World()->selectCol('SELECT `entry` FROM disables WHERE `sourceType` = 4')) + DB::Aowow()->query('UPDATE ?_achievement a JOIN ?_achievementcriteria ac ON a.`id` = ac.`refAchievementId` SET a.`cuFlags` = ?d WHERE ac.`id` IN (?a)', CUSTOM_DISABLED, $criteria); $this->reapplyCCFlags('achievement', Type::ACHIEVEMENT); diff --git a/setup/tools/sqlgen/emotes.ss.php b/setup/tools/sqlgen/emotes.ss.php index 632f8a09..af7d1fe6 100644 --- a/setup/tools/sqlgen/emotes.ss.php +++ b/setup/tools/sqlgen/emotes.ss.php @@ -26,8 +26,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript if ($x = array_diff_key(CLISetup::$locales, $locPath)) { - $locs = array_intersect_key(CLISetup::$locales, array_flip($x)); - CLI::write('[emotes] '.sprintf($globStrPath, CLI::bold('['.implode('/,', $locs).'/]')) . ' not found!', CLI::LOG_WARN); + $locs = array_intersect_key(CLISetup::$locales, $x); + CLI::write('[emotes] '.sprintf($globStrPath, '[' . Lang::concat($locs, callback: fn($x) => CLI::bold(implode('/, ', $x->gameDirs()) . '/')) . ']') . ' not found!', CLI::LOG_WARN); CLI::write(' Emote aliasses can not be generated for affected locales!', CLI::LOG_WARN); } @@ -51,9 +51,9 @@ CLISetup::registerSetup("sql", new class extends SetupScript 12 female others no 4 - */ - $this->textData = DB::Aowow()->select('SELECT id AS ARRAY_KEY, text_loc0 AS "0", text_loc2 AS "2", text_loc3 AS "3", text_loc4 AS "4", text_loc6 AS "6", text_loc8 AS "8" FROM dbc_emotestextdata'); + $this->textData = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, `text_loc0` AS "0", `text_loc2` AS "2", `text_loc3` AS "3", `text_loc4` AS "4", `text_loc6` AS "6", `text_loc8` AS "8" FROM dbc_emotestextdata'); - $texts = DB::Aowow()->select('SELECT et.id AS ARRAY_KEY, LOWER(command) AS `cmd`, IF(e.animationId, 1, 0) AS `anim`, -emoteId AS "parent", e.soundId, etd0, etd1, etd2, etd4, etd6, etd8, etd9, etd12 FROM dbc_emotestext et LEFT JOIN dbc_emotes e ON e.id = et.emoteId'); + $texts = DB::Aowow()->select('SELECT et.`id` AS ARRAY_KEY, LOWER(`command`) AS "cmd", IF(e.`animationId`, 1, 0) AS "anim", -`emoteId` AS "parent", e.`soundId`, `etd0`, `etd1`, `etd2`, `etd4`, `etd6`, `etd8`, `etd9`, `etd12` FROM dbc_emotestext et LEFT JOIN dbc_emotes e ON e.`id` = et.`emoteId`'); foreach ($texts AS $id => $t) { DB::Aowow()->query( @@ -68,12 +68,12 @@ CLISetup::registerSetup("sql", new class extends SetupScript VALUES (?d, ?, ?d, ?d, ?d, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', $id, $t['cmd'], $t['anim'], $t['parent'], $t['soundId'], - $this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_EN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_EN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_EN), $this->textData[$t['etd2']][LOCALE_EN] ?? '', $this->textData[$t['etd6']][LOCALE_EN] ?? '', - $this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_FR), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_FR), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_FR), $this->textData[$t['etd2']][LOCALE_FR] ?? '', $this->textData[$t['etd6']][LOCALE_FR] ?? '', - $this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_DE), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_DE), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_DE), $this->textData[$t['etd2']][LOCALE_DE] ?? '', $this->textData[$t['etd6']][LOCALE_DE] ?? '', - $this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_CN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_CN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_CN), $this->textData[$t['etd2']][LOCALE_CN] ?? '', $this->textData[$t['etd6']][LOCALE_CN] ?? '', - $this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_ES), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_ES), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_ES), $this->textData[$t['etd2']][LOCALE_ES] ?? '', $this->textData[$t['etd6']][LOCALE_ES] ?? '', - $this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_RU), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_RU), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_RU), $this->textData[$t['etd2']][LOCALE_RU] ?? '', $this->textData[$t['etd6']][LOCALE_RU] ?? '' + $this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::EN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::EN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::EN), $this->textData[$t['etd2']][Locale::EN->value] ?? '', $this->textData[$t['etd6']][Locale::EN->value] ?? '', + $this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::FR), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::FR), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::FR), $this->textData[$t['etd2']][Locale::FR->value] ?? '', $this->textData[$t['etd6']][Locale::FR->value] ?? '', + $this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::DE), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::DE), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::DE), $this->textData[$t['etd2']][Locale::DE->value] ?? '', $this->textData[$t['etd6']][Locale::DE->value] ?? '', + $this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::CN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::CN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::CN), $this->textData[$t['etd2']][Locale::CN->value] ?? '', $this->textData[$t['etd6']][Locale::CN->value] ?? '', + $this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::ES), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::ES), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::ES), $this->textData[$t['etd2']][Locale::ES->value] ?? '', $this->textData[$t['etd6']][Locale::ES->value] ?? '', + $this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::RU), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::RU), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::RU), $this->textData[$t['etd2']][Locale::RU->value] ?? '', $this->textData[$t['etd6']][Locale::RU->value] ?? '' ); } @@ -114,10 +114,10 @@ CLISetup::registerSetup("sql", new class extends SetupScript return $allOK; } - private function mergeGenderedStrings(int $maleTextId, int $femaleTextId, int $locale) : string + private function mergeGenderedStrings(int $maleTextId, int $femaleTextId, Locale $loc) : string { - $maleText = $this->textData[$maleTextId][$locale] ?? ''; - $femaleText = $this->textData[$femaleTextId][$locale] ?? ''; + $maleText = $this->textData[$maleTextId][$loc->value] ?? ''; + $femaleText = $this->textData[$femaleTextId][$loc->value] ?? ''; if (!$maleText && !$femaleText) return ''; diff --git a/setup/tools/sqlgen/itemset.ss.php b/setup/tools/sqlgen/itemset.ss.php index d79ad36d..99eb8a42 100644 --- a/setup/tools/sqlgen/itemset.ss.php +++ b/setup/tools/sqlgen/itemset.ss.php @@ -79,16 +79,17 @@ CLISetup::registerSetup("sql", new class extends SetupScript 29 => [901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883] ); - // well .. fuck - private $tagsByNamePart = array( - 17 => ['gladiator'], // "Arena Season 1 Set", - 19 => ['merciless'], // "Arena Season 2 Set", - 20 => ['vengeful'], // "Arena Season 3 Set", - 22 => ['brutal'], // "Arena Season 4 Set", - 24 => ['deadly', 'hateful', 'savage'], // "Arena Season 5 Set", - 26 => ['furious'], // "Arena Season 6 Set", - 28 => ['relentless'], // "Arena Season 7 Set", - 30 => ['wrathful'] // "Arena Season 8 Set", + // in pvp we hope nobody fucked with the item level + private $tagsByItemlevel = array( + 123 => 17, // "Arena Season 1 Set" + 136 => 19, // "Arena Season 2 Set" + 146 => 20, // "Arena Season 3 Set" + 159 => 22, // "Arena Season 4 Set" + 200 => 24, // "Arena Season 5 Set" + 213 => 24, // + 232 => 26, // "Arena Season 6 Set" + 251 => 28, // "Arena Season 7 Set" + 270 => 30 // "Arena Season 8 Set" ); private function getSetType(array $items) : int @@ -113,11 +114,11 @@ CLISetup::registerSetup("sql", new class extends SetupScript { switch ($item['subclass']) { - case 0: $type = 8; break; // 1H-Axe - case 4: $type = 9; break; // 1H-Mace - case 7: $type = 10; break; // 1H-Sword - case 13: $type = 7; break; // Fist Weapon - case 15: $type = 5; break; // Dagger + case ITEM_SUBCLASS_1H_AXE: $type = 8; break; + case ITEM_SUBCLASS_1H_MACE: $type = 9; break; + case ITEM_SUBCLASS_1H_SWORD: $type = 10; break; + case ITEM_SUBCLASS_FIST_WEAPON: $type = 7; break; + case ITEM_SUBCLASS_DAGGER: $type = 5; break; } } else if ($item['class'] == ITEM_CLASS_ARMOR) @@ -150,11 +151,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript return $tag; // try arena set - if ($item['ItemLevel'] >= 120 && $item['AllowableClass'] && ($item['AllowableClass'] & CLASS_MASK_ALL) != CLASS_MASK_ALL) - foreach ($this->tagsByNamePart as $tag => $strings) - foreach ($strings as $str) - if (stripos($item['name'], $str) === 0) - return $tag; + if ($item['AllowableClass'] && ($item['AllowableClass'] & CLASS_MASK_ALL) != CLASS_MASK_ALL) + return $this->tagsByItemlevel[$item['ItemLevel']] ?? 0; return 0; } @@ -188,14 +186,14 @@ CLISetup::registerSetup("sql", new class extends SetupScript public function generate(array $ids = []) : bool { // find events associated with holidayIds - if ($pairs = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($this->setToHoliday))) + if ($pairs = DB::World()->selectCol('SELECT `holiday` AS ARRAY_KEY, `eventEntry` FROM game_event WHERE `holiday` IN (?a)', array_values($this->setToHoliday))) foreach ($this->setToHoliday as &$hId) $hId = !empty($pairs[$hId]) ? $pairs[$hId] : 0; DB::Aowow()->query('TRUNCATE TABLE ?_itemset'); $virtualId = 0; - $sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset'); + $sets = DB::Aowow()->select('SELECT *, `id` AS ARRAY_KEY FROM dbc_itemset'); foreach ($sets as $setId => $setData) { @@ -237,22 +235,22 @@ CLISetup::registerSetup("sql", new class extends SetupScript $descText = []; - foreach (Util::mask2bits(Cfg::get('LOCALES')) as $loc) + foreach (CLISetup::$locales as $locId => $loc) { - User::useLocale($loc); + Lang::load($loc); - $row['name_loc'.$loc] = Util::localizedString($setData, 'name'); + $row['name_loc'.$locId] = Util::localizedString($setData, 'name'); foreach ($bonusSpells->iterate() as $__) { - if (!isset($descText[$loc])) - $descText[$loc] = ''; + if (!isset($descText[$locId])) + $descText[$locId] = ''; - $descText[$loc] .= $bonusSpells->parseText()[0]."\n"; + $descText[$locId] .= $bonusSpells->parseText()[0]."\n"; } // strip rating blocks - e.g. 14 (0.30% @ L80) - $row['bonusText_loc'.$loc] = preg_replace('/(\d+) .*?<\/small>/i', '\1', $descText[$loc]); + $row['bonusText_loc'.$locId] = preg_replace('/(\d+) .*?<\/small>/i', '\1', $descText[$locId]); } @@ -260,7 +258,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript /* determine type and reuse from pieces */ /****************************************/ - $pieces = DB::World()->select('SELECT entry, name, class, subclass, Quality, AllowableClass, ItemLevel, RequiredLevel, itemset, IF (Flags & ?d, 1, 0) AS heroic, IF(InventoryType = 15, 26, IF(InventoryType = 5, 20, InventoryType)) AS slot, entry AS ARRAY_KEY FROM item_template WHERE itemset = ?d', ITEM_FLAG_HEROIC, $setId); + $pieces = DB::World()->select('SELECT `entry`, `name`, `class`, `subclass`, `Quality`, `AllowableClass`, `ItemLevel`, `RequiredLevel`, `itemset`, IF (`Flags` & ?d, 1, 0) AS "heroic", IF(`InventoryType` = 15, 26, IF(`InventoryType` = 5, 20, `InventoryType`)) AS "slot", `entry` AS ARRAY_KEY FROM item_template WHERE `itemset` = ?d', ITEM_FLAG_HEROIC, $setId); /* possible cases: @@ -294,7 +292,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript else if (in_array($data['slot'], [INVTYPE_WEAPON, INVTYPE_FINGER, INVTYPE_TRINKET])) $sorted[$k][-$data['slot']] = $data; // slot confict. If item is being sold, replace old item (imperfect solution :/) - else if (DB::World()->selectCell('SELECT SUM(n) FROM (SELECT COUNT(1) AS n FROM npc_vendor WHERE item = ?d UNION SELECT COUNT(1) AS n FROM game_event_npc_vendor WHERE item = ?d) x', $data['entry'], $data['entry'])) + else if (DB::World()->selectCell('SELECT SUM(`n`) FROM (SELECT COUNT(1) AS "n" FROM npc_vendor WHERE `item` = ?d UNION SELECT COUNT(1) AS "n" FROM game_event_npc_vendor WHERE `item` = ?d) x', $data['entry'], $data['entry'])) $sorted[$k][$data['slot']] = $data; } diff --git a/template/bricks/contribute.tpl.php b/template/bricks/contribute.tpl.php index 87f61733..8e602a46 100644 --- a/template/bricks/contribute.tpl.php +++ b/template/bricks/contribute.tpl.php @@ -9,7 +9,7 @@ if (!empty($this->contribute)):
localizedBrick('contrib', User::$localeId); + $this->localizedBrick('contrib', Lang::getLocale()); ?>
diff --git a/template/bricks/pageTemplate.tpl.php b/template/bricks/pageTemplate.tpl.php index 45fee1b2..da06b8e6 100644 --- a/template/bricks/pageTemplate.tpl.php +++ b/template/bricks/pageTemplate.tpl.php @@ -21,8 +21,8 @@ if (!empty($this->gPageInfo)): endif; if (!empty($this->pageTemplate)): - if (User::$localeId && $this->pageTemplate['pageName'] != 'home'): - echo " Locale.set(".User::$localeId.");\n"; + if (Lang::getLocale()->value && $this->pageTemplate['pageName'] != 'home'): + echo " Locale.set(".Lang::getLocale()->value.");\n"; endif; echo " PageTemplate.set(".Util::toJSON($this->pageTemplate).");\n"; @@ -35,4 +35,3 @@ if (!empty($fi)): endif; ?> //]]> - diff --git a/template/pages/home.tpl.php b/template/pages/home.tpl.php index c64eef7f..e1a92471 100644 --- a/template/pages/home.tpl.php +++ b/template/pages/home.tpl.php @@ -66,8 +66,8 @@ endif; ?>