From 3a982018372e1f9adac6ddb75b4aa3e49a0e4c23 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Tue, 8 Mar 2022 18:52:01 +0100 Subject: [PATCH 001/698] Zones/Locations * fixed Quick Info defaulting expansion maps to have [0, 0, 0] as parent * corrected looking for custom excluded flag when collecting instances for area --- pages/zone.php | 2 +- setup/tools/sqlgen/zones.func.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/zone.php b/pages/zone.php index 9158663f..45c3ac20 100644 --- a/pages/zone.php +++ b/pages/zone.php @@ -109,7 +109,7 @@ class ZonePage extends GenericPage } // Instances - if ($_ = DB::Aowow()->selectCol('SELECT id FROM ?_zones WHERE parentAreaId = ?d AND (flags & ?d) = 0', $this->typeId, CUSTOM_EXCLUDE_FOR_LISTVIEW)) + if ($_ = DB::Aowow()->selectCol('SELECT `id` FROM ?_zones WHERE `parentAreaId` = ?d AND (`cuFlags` & ?d) = 0', $this->typeId, CUSTOM_EXCLUDE_FOR_LISTVIEW)) { $this->extendGlobalIds(TYPE_ZONE, ...$_); $infobox[] = Lang::maps('Instances').Lang::main('colon')."\n[zone=".implode("], \n[zone=", $_).']'; diff --git a/setup/tools/sqlgen/zones.func.php b/setup/tools/sqlgen/zones.func.php index d2c45337..bfb54299 100644 --- a/setup/tools/sqlgen/zones.func.php +++ b/setup/tools/sqlgen/zones.func.php @@ -115,7 +115,7 @@ SqlGen::register(new class extends SetupScript foreach ($baseData as &$bd) { - if (!in_array($bd['parentMapId'], [0, 1, 530, 571])) + if (in_array($bd['mapBak'], [0, 1, 530, 571])) continue; if ($gPos = Game::worldPosToZonePos($bd['parentMapId'], $bd['parentY'], $bd['parentX'])) From 65bfd9376156f5681b1f09ada82e5cf242ba3410 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sun, 6 Feb 2022 19:05:55 +0100 Subject: [PATCH 002/698] Profiler * truncate local profile if sync with game server fails (entry deleted) * do not use chars/guilds/arena teams with empty names --- includes/profiler.class.php | 20 +++++++++++++++++++- includes/types/arenateam.class.php | 10 +++++++++- includes/types/guild.class.php | 10 +++++++++- includes/types/profile.class.php | 10 +++++++++- prQueue | 9 +++++---- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/includes/profiler.class.php b/includes/profiler.class.php index 76db217b..55fd44f3 100644 --- a/includes/profiler.class.php +++ b/includes/profiler.class.php @@ -300,6 +300,12 @@ class Profiler if (!$char) return false; + if (!$char['name']) + { + trigger_error('char #'.$charGuid.' on realm #'.$realmId.' has empty name. skipping...', E_USER_WARNING); + return false; + } + // reminder: this query should not fail: a placeholder entry is created as soon as a char listview is created or profile detail page is called $profile = DB::Aowow()->selectRow('SELECT id, lastupdated FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $realmId, $char['guid']); if (!$profile) @@ -431,7 +437,7 @@ class Profiler // char is flagged for rename if ($char['at_login'] & 0x1) { - $ri = DB::Aowow()->selectCell('SELECT MAX(renameItr) FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d AND name = ?', $realmId, $charGuid, $char['name']); + $ri = DB::Aowow()->selectCell('SELECT MAX(renameItr) FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID IS NOT NULL AND name = ?', $realmId, $char['name']); $data['renameItr'] = $ri ? ++$ri : 1; } @@ -773,6 +779,12 @@ class Profiler if (!$guild) return false; + if (!$guild['name']) + { + trigger_error('guild #'.$guildGuid.' on realm #'.$realmId.' has empty name. skipping...', E_USER_WARNING); + return false; + } + // reminder: this query should not fail: a placeholder entry is created as soon as a team listview is created or team detail page is called $guildId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $realmId, $guild['guildId']); @@ -834,6 +846,12 @@ class Profiler if (!$team) return false; + if (!$team['name']) + { + trigger_error('arena team #'.$teamGuid.' on realm #'.$realmId.' has empty name. skipping...', E_USER_WARNING); + return false; + } + // reminder: this query should not fail: a placeholder entry is created as soon as a team listview is created or team detail page is called $teamId = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $realmId, $team['arenaTeamId']); diff --git a/includes/types/arenateam.class.php b/includes/types/arenateam.class.php index a2e8bcc2..8007107d 100644 --- a/includes/types/arenateam.class.php +++ b/includes/types/arenateam.class.php @@ -167,7 +167,15 @@ class RemoteArenaTeamList extends ArenaTeamList } else { - trigger_error('arena team "'.$curTpl['name'].'" belongs to nonexistant realm #'.$r, E_USER_WARNING); + trigger_error('arena team #'.$guid.' belongs to nonexistant realm #'.$r, E_USER_WARNING); + unset($this->templates[$guid]); + continue; + } + + // empty name + if (!$curTpl['name']) + { + trigger_error('arena team #'.$guid.' on realm #'.$r.' has empty name.', E_USER_WARNING); unset($this->templates[$guid]); continue; } diff --git a/includes/types/guild.class.php b/includes/types/guild.class.php index c219e360..981cc3bf 100644 --- a/includes/types/guild.class.php +++ b/includes/types/guild.class.php @@ -196,7 +196,15 @@ class RemoteGuildList extends GuildList } else { - trigger_error('character "'.$curTpl['name'].'" belongs to nonexistant realm #'.$r, E_USER_WARNING); + trigger_error('guild #'.$guid.' belongs to nonexistant realm #'.$r, E_USER_WARNING); + unset($this->templates[$guid]); + continue; + } + + // empty name + if (!$curTpl['name']) + { + trigger_error('guild #'.$guid.' on realm #'.$r.' has empty name.', E_USER_WARNING); unset($this->templates[$guid]); continue; } diff --git a/includes/types/profile.class.php b/includes/types/profile.class.php index 77cd62c3..b760d90b 100644 --- a/includes/types/profile.class.php +++ b/includes/types/profile.class.php @@ -573,7 +573,15 @@ class RemoteProfileList extends ProfileList } else { - trigger_error('character "'.$curTpl['name'].'" belongs to nonexistant realm #'.$r, E_USER_WARNING); + trigger_error('char #'.$guid.' belongs to nonexistant realm #'.$r, E_USER_WARNING); + unset($this->templates[$guid]); + continue; + } + + // empty name + if (!$curTpl['name']) + { + trigger_error('char #'.$guid.' on realm #'.$r.' has empty name.', E_USER_WARNING); unset($this->templates[$guid]); continue; } diff --git a/prQueue b/prQueue index 0ed859a2..716a6e8a 100755 --- a/prQueue +++ b/prQueue @@ -33,11 +33,10 @@ $error = function ($type, $realmGUID, $realmId) if ($type == TYPE_GUILD) $what = 'guild'; if ($type == TYPE_ARENA_TEAM) - $what = 'arena team'; + $what = 'arena team'; DB::Aowow()->query('UPDATE ?_profiler_sync SET status = ?d, errorCode = ?d WHERE realm = ?d AND realmGUID = ?d AND type = ?d', PR_QUEUE_STATUS_ERROR, PR_QUEUE_ERROR_CHAR, $realmId, $realmGUID, $type); - trigger_error('prQueue - unknown '.$what.' guid #'.$realmGUID.' on realm #'.$realmId.' to sync into profiler.', E_USER_WARNING); - CLI::write('unknown '.$what.' guid #'.$realmGUID.' on realm #'.$realmId.' to sync into profiler.', CLI::LOG_WARN); + trigger_error('prQueue - '.$what.' #'.$realmGUID.' on realm #'.$realmId.' not found. Truncating local placeholder.', E_USER_WARNING); }; @@ -78,6 +77,7 @@ while (DB::Aowow()->selectCell('SELECT value FROM ?_config WHERE `key` = "profil if (!Profiler::getCharFromRealm($row['realm'], $row['realmGUID'])) { $error(TYPE_PROFILE, $row['realmGUID'], $row['realm']); + DB::Aowow()->query('DELETE FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $row['realm'], $row['realmGUID']); continue 2; } @@ -86,6 +86,7 @@ while (DB::Aowow()->selectCell('SELECT value FROM ?_config WHERE `key` = "profil if (!Profiler::getGuildFromRealm($row['realm'], $row['realmGUID'])) { $error(TYPE_GUILD, $row['realmGUID'], $row['realm']); + DB::Aowow()->query('DELETE FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $row['realm'], $row['realmGUID']); continue 2; } @@ -94,6 +95,7 @@ while (DB::Aowow()->selectCell('SELECT value FROM ?_config WHERE `key` = "profil if (!Profiler::getArenaTeamFromRealm($row['realm'], $row['realmGUID'])) { $error(TYPE_ARENA_TEAM, $row['realmGUID'], $row['realm']); + DB::Aowow()->query('DELETE FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $row['realm'], $row['realmGUID']); continue 2; } @@ -101,7 +103,6 @@ while (DB::Aowow()->selectCell('SELECT value FROM ?_config WHERE `key` = "profil default: DB::Aowow()->query('DELETE FROM ?_profiler_sync WHERE realm = ?d AND type = ?d AND typeId = ?d', $row['realm'], $row['type'], $row['typeId']); trigger_error('prQueue - unknown type #'.$row['type'].' to sync into profiler. Removing from queue...', E_USER_ERROR); - CLI::write('unknown type #'.$row['type'].' to sync into profiler. Removing from queue...', CLI::LOG_ERROR); } $tCycle = microtime(true); From 7caabc0fa8f7baf5a7fb8a27fcf1f27d0e909afa Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Tue, 22 Mar 2022 16:25:36 +0100 Subject: [PATCH 003/698] Misc/Fixup * obligatory after-the-fact fixups --- includes/utilities.php | 2 +- pages/admin.php | 8 ++++---- pages/guides.php | 2 +- pages/talent.php | 2 +- setup/db_structure.sql | 2 +- static/js/locale_dede.js | 13 +------------ static/js/locale_enus.js | 13 +------------ static/js/locale_eses.js | 13 +------------ static/js/locale_frfr.js | 13 +------------ static/js/locale_ruru.js | 13 +------------ static/js/locale_zhcn.js | 13 +------------ 11 files changed, 14 insertions(+), 80 deletions(-) diff --git a/includes/utilities.php b/includes/utilities.php index 50d72d92..98d25b6d 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -1844,7 +1844,7 @@ abstract class Type $x = []; foreach (self::$data as $k => [$o, , , $f]) if ($o && (!$flags || $flags & $f)) - if (!$attr || self::checkClassAttrib($attr, $attrVal)) + if (!$attr || self::checkClassAttrib($k, $attr, $attrVal)) $x[$k] = $o; return $x; diff --git a/pages/admin.php b/pages/admin.php index 6ea4d02b..70b3b0c3 100644 --- a/pages/admin.php +++ b/pages/admin.php @@ -16,7 +16,7 @@ class AdminPage extends GenericPage 'all' => ['filter' => FILTER_UNSAFE_RAW], 'type' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], 'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], - 'user' => ['filter' => FILTER_CALLBACK, 'options' => 'urldecode'], + 'user' => ['filter' => FILTER_CALLBACK, 'options' => 'urldecode'] ); private $generator = ''; @@ -88,7 +88,7 @@ class AdminPage extends GenericPage [CSS_STRING, '.grid a.tip:hover { opacity:1; }'], [CSS_STRING, '.grid tr { height:30px; }'], [CSS_STRING, '.grid .disabled { opacity:0.4 !important; }'], - [CSS_STRING, '.grid .status { position:absolute; right:5px; }'], + [CSS_STRING, '.grid .status { position:absolute; right:5px; }'] ); $head = ''; @@ -198,7 +198,7 @@ class AdminPage extends GenericPage $this->addScript( [JS_FILE, 'screenshot.js'], [CSS_STRING, '.layout {margin: 0px 25px; max-width: inherit; min-width: 1200px; }'], - [CSS_STRING, '#highlightedRow { background-color: #322C1C; }'], + [CSS_STRING, '#highlightedRow { background-color: #322C1C; }'] ); $ssGetAll = $this->_get['all']; @@ -235,7 +235,7 @@ class AdminPage extends GenericPage { $this->addScript( [JS_FILE, 'filters.js'], - [CSS_STRING, '.wt-edit {display:inline-block; vertical-align:top; width:350px;}'], + [CSS_STRING, '.wt-edit {display:inline-block; vertical-align:top; width:350px;}'] ); $head = $body = ''; diff --git a/pages/guides.php b/pages/guides.php index 0e039c14..44451737 100644 --- a/pages/guides.php +++ b/pages/guides.php @@ -10,7 +10,7 @@ class GuidesPage extends GenericPage { use TrListPage; - protected $type = Type::Guide; + protected $type = Type::GUIDE; protected $tpl = 'list-page-generic'; protected $path = [6]; protected $tabId = 6; diff --git a/pages/talent.php b/pages/talent.php index 79df675a..8ebe3b9f 100644 --- a/pages/talent.php +++ b/pages/talent.php @@ -33,7 +33,7 @@ class TalentPage extends GenericPage // add conditional js & css $this->addScript( [JS_FILE, ($this->isPetCalc ? '?data=pet-talents.pets' : '?data=glyphs').'&locale='.User::$localeId.'&t='.$_SESSION['dataKey']], - [JS_FILE, $this->isPetCalc ? 'petcalc.js' : 'talent.js'], + [JS_FILE, $this->isPetCalc ? 'petcalc.js' : 'talent.js'] ); if ($this->isPetCalc) diff --git a/setup/db_structure.sql b/setup/db_structure.sql index 26b984fb..daaa37f2 100644 --- a/setup/db_structure.sql +++ b/setup/db_structure.sql @@ -3184,7 +3184,7 @@ UNLOCK TABLES; LOCK TABLES `aowow_dbversion` WRITE; /*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */; -INSERT INTO `aowow_dbversion` VALUES (1645476215,0,NULL,NULL); +INSERT INTO `aowow_dbversion` VALUES (1647956310,0,NULL,NULL); /*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */; UNLOCK TABLES; diff --git a/static/js/locale_dede.js b/static/js/locale_dede.js index 71a7d4c2..5280c9cc 100644 --- a/static/js/locale_dede.js +++ b/static/js/locale_dede.js @@ -960,18 +960,7 @@ var mn_guides = [ [1, "Klassen", '?guides=1'], [4, "Neue Spieler & Stufenfortschritt", '?guides=4'], [5, "Schlachtzüge & Bosskämpfe", '?guides=5'], - [3, "Weltereignisse", '?guides=3', [ - [, "Aowow Leitfäden"], - ["lunar-festival","Mondfest","?guide=lunar-festival"], - ["love-is-in-the-air","Liebe liegt in der Luft","?guide=love-is-in-the-air"], - ["noblegarden","Nobelgartenfest","?guide=noblegarden"], - ["childrens-week","Kinderwoche","?guide=childrens-week"], - ["midsummer-fire-festival","Sonnenwendfest","?guide=midsummer-fire-festival"], - ["brewfest","Braufest","?guide=brewfest"], - ["hallows-end","Schlotternächte","?guide=hallows-end"], - ["pilgrims-bounty","Pilgerfreudenfest","?guide=pilgrims-bounty"], - ["winter-veil","Winterhauchfest","?guide=winter-veil"] - ]], + [3, "Weltereignisse", '?guides=3'], [6, "Wirtschaft & Währung", '?guides=6'], [9, "Anderes", '?guides=9'] ]; diff --git a/static/js/locale_enus.js b/static/js/locale_enus.js index aa320f56..7927e634 100644 --- a/static/js/locale_enus.js +++ b/static/js/locale_enus.js @@ -1007,18 +1007,7 @@ var mn_guides = [ [2, "Professions", '?guides=2'], [5, "Raid & Boss Fights", '?guides=5'], [8, "Vanity Items, Pets & Mounts", '?guides=8'], - [3, "World Events", '?guides=3', [ - [,"Aowow Guides"], - ["lunar-festival","Lunar Festival","?guide=lunar-festival"], - ["love-is-in-the-air","Love is in the Air","?guide=love-is-in-the-air"], - ["noblegarden","Noblegarden","?guide=noblegarden"], - ["childrens-week","Childrens Week","?guide=childrens-week"], - ["midsummer-fire-festival","Midsummer Fire Festival","?guide=midsummer-fire-festival"], - ["brewfest","Brewfest","?guide=brewfest"], - ["hallows-end","Hallow's End","?guide=hallows-end"], - ["pilgrims-bounty","Pilgrim's Bounty","?guide=pilgrims-bounty"], - ["winter-veil","Feast of Winter Veil","?guide=winter-veil"] - ]], + [3, "World Events", '?guides=3'], [9, "Other", '?guides=9'] ]; diff --git a/static/js/locale_eses.js b/static/js/locale_eses.js index b1dc0ec6..0cb9de05 100644 --- a/static/js/locale_eses.js +++ b/static/js/locale_eses.js @@ -957,18 +957,7 @@ var mn_guides = [ [1, "Clases", '?guides=1'], [5, "Combates de Bandas y Jefes", '?guides=5'], [6, "Economía y Dinero", '?guides=6'], - [3, "Eventos del mundo", '?guides=3', [ - [,"Aowow Guías"], - ["lunar-festival","Festival Lunar","?guide=lunar-festival"], - ["love-is-in-the-air","Amor en el aire","?guide=love-is-in-the-air"], - ["noblegarden","Jardín Noble","?guide=noblegarden"], - ["childrens-week","Los Niños","?guide=childrens-week"], - ["midsummer-fire-festival","Festival de Fuego del Solsticio de Verano","?guide=midsummer-fire-festival"], - ["brewfest","El festín del Festival de Invierno","?guide=brewfest"], - ["hallows-end","Halloween","?guide=hallows-end"], - ["pilgrims-bounty","Generosidad","?guide=pilgrims-bounty"], - ["winter-veil","Festival de Invierno","?guide=winter-veil"] - ]], + [3, "Eventos del mundo", '?guides=3'], [7, "Logros", '?guides=7'], [4, "Nuevos Jugadores y Leveling", '?guides=4'], [8, "Objetos de vanidad, Mascotas y Monturas", '?guides=8'], diff --git a/static/js/locale_frfr.js b/static/js/locale_frfr.js index c72ff2de..607fcfcd 100644 --- a/static/js/locale_frfr.js +++ b/static/js/locale_frfr.js @@ -956,18 +956,7 @@ var mn_database = [ var mn_guides = [ [1, "Classes", '?guides=1'], [6, "Economie et Argent", '?guides=6'], - [3, "Évènements mondiaux", '?guides=3', [ - [,"Aowow Guides"], - ["lunar-festival","Fête lunaire","?guide=lunar-festival"], - ["love-is-in-the-air","De l'amour dans l'air","?guide=love-is-in-the-air"], - ["noblegarden","Jardin des nobles","?guide=noblegarden"], - ["childrens-week","Semaine des enfants","?guide=childrens-week"], - ["midsummer-fire-festival","Fête du Feu du solstice d'été","?guide=midsummer-fire-festival"], - ["brewfest","Voile d'hiver","?guide=brewfest"], - ["hallows-end","Sanssaint","?guide=hallows-end"], - ["pilgrims-bounty","Bienfaits du pèlerin","?guide=pilgrims-bounty"], - ["winter-veil","Voile d'hiver","?guide=winter-veil"] - ]], + [3, "Évènements mondiaux", '?guides=3'], [7, "Hauts faits", '?guides=7'], [4, "Nouveaux Joueurs & Montée en niveau", '?guides=4'], [2, "Métiers", '?guides=2'], diff --git a/static/js/locale_ruru.js b/static/js/locale_ruru.js index 720a29fd..6d9b3d77 100644 --- a/static/js/locale_ruru.js +++ b/static/js/locale_ruru.js @@ -961,18 +961,7 @@ var mn_guides = [ [2, "Профессии", '?guides=2'], [5, "Подземелья и рейды", '?guides=5'], [8, "Забавные предметы", '?guides=8'], - [3, "Игровые события", '?guides=3', [ - [,"Aowow Гайды"], - ["lunar-festival","Лунный фестиваль","?guide=lunar-festival"], - ["love-is-in-the-air","Любовная лихорадка","?guide=love-is-in-the-air"], - ["noblegarden","Сад чудес","?guide=noblegarden"], - ["childrens-week","Детская неделя","?guide=childrens-week"], - ["winter-veil","Зимний Покров","?guide=winter-veil"], - ["hallows-end","Тыквовин","?guide=hallows-end"], - ["midsummer-fire-festival","Огненный солнцеворот","?guide=midsummer-fire-festival"], - ["winter-veil","Зимний Покров","?guide=winter-veil"], - ["pilgrims-bounty","Пиршество странников","?guide=pilgrims-bounty"] - ]], + [3, "Игровые события", '?guides=3'], [9, "Разное", '?guides=9'] ]; diff --git a/static/js/locale_zhcn.js b/static/js/locale_zhcn.js index fb8a67c7..a0b02959 100644 --- a/static/js/locale_zhcn.js +++ b/static/js/locale_zhcn.js @@ -1007,18 +1007,7 @@ var mn_guides = [ [2, "专业", '?guides=2'], [5, "地下城与团队副本", '?guides=5'], [8, "华丽收藏", '?guides=8'], - [3, "世界事件", '?guides=3', [ - [,"Aowow 指南"], - ["lunar-festival","春节","?guide=lunar-festival"], - ["love-is-in-the-air","情人节","?guide=love-is-in-the-air"], - ["noblegarden","复活节","?guide=noblegarden"], - ["childrens-week","儿童周","?guide=childrens-week"], - ["midsummer-fire-festival","仲夏火焰节","?guide=midsummer-fire-festival"], - ["brewfest","美酒节","?guide=brewfest"], - ["hallows-end","万圣节","?guide=hallows-end"], - ["pilgrims-bounty","感恩节","?guide=pilgrims-bounty"], - ["winter-veil","冬幕节","?guide=winter-veil"] - ]], + [3, "世界事件", '?guides=3'], [9, "杂项", '?guides=9'] ]; From 1dc8d5028919862410c94f874302545a8460f829 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Tue, 22 Mar 2022 21:59:49 +0100 Subject: [PATCH 004/698] Misc/Fixup * move guide localization, so Lang::typeName can pick it up * rename forgotten TYPE_* definitions --- includes/types/item.class.php | 2 +- localization/locale_dede.php | 100 +++++++++++++++++----------------- localization/locale_enus.php | 98 +++++++++++++++++---------------- localization/locale_eses.php | 98 +++++++++++++++++---------------- localization/locale_frfr.php | 98 +++++++++++++++++---------------- localization/locale_ruru.php | 98 +++++++++++++++++---------------- localization/locale_zhcn.php | 97 +++++++++++++++++---------------- pages/guide.php | 12 ++-- pages/guides.php | 4 +- prQueue | 18 +++--- 10 files changed, 318 insertions(+), 307 deletions(-) diff --git a/includes/types/item.class.php b/includes/types/item.class.php index d0927833..2354f50a 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -889,7 +889,7 @@ class ItemList extends BaseType { foreach ($jsg as $js) if (empty($this->jsGlobals[Type::CHR_RACE][$js])) - $this->jsGlobals[Type::CHR_ACE][$js] = $js; + $this->jsGlobals[Type::CHR_RACE][$js] = $js; $x .= Lang::game('races').Lang::main('colon').$races.'
'; } diff --git a/localization/locale_dede.php b/localization/locale_dede.php index e767f205..d857e1b2 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -159,8 +159,6 @@ $lang = array( ) ), 'guide' => array( - 'guide' => "Leitfaden", - 'guides' => "Leitfäden", 'myGuides' => "Meine Leitfäden", 'editTitle' => "Eigenen Leitfaden bearbeiten", 'newTitle' => "Leitfaden erstellen", @@ -275,70 +273,74 @@ $lang = array( ) ), 'game' => array( - 'achievement' => "Erfolg", + // type strings + 'npc' => "NPC", // 1 + 'npcs' => "NPCs", + 'object' => "Objekt", // 2 + 'objects' => "Objekte", + 'item' => "Gegenstand", // 3 + 'items' => "Gegenstände", + 'itemset' => "Ausrüstungsset", // 4 + 'itemsets' => "Ausrüstungssets", + 'quest' => "Quest", // 5 + 'quests' => "Quests", + 'spell' => "Zauber", // 6 + 'spells' => "Zauber", + 'zone' => "Zone", // 7 + 'zones' => "Gebiete", + 'faction' => "Fraktion", // 8 + 'factions' => "Fraktionen", + 'pet' => "Begleiter", // 9 + 'pets' => "Begleiter", + 'achievement' => "Erfolg", // 10 'achievements' => "Erfolge", - 'areatrigger' => "Areatrigger", - 'areatriggers' => "Areatrigger", - 'class' => "Klasse", + 'title' => "Titel", // 11 + 'titles' => "Titel", + 'event' => "Weltereigniss", // 12 + 'events' => "Weltereignisse", + 'class' => "Klasse", // 13 'classes' => "Klassen", - 'currency' => "Währung", + 'race' => "Volk", // 14 + 'races' => "Völker", + 'skill' => "Fertigkeit", // 15 + 'skills' => "Fertigkeiten", + 'currency' => "Währung", // 17 'currencies' => "Währungen", + 'sound' => "Klang", // 19 + 'sounds' => "Klänge", + 'icon' => "Icon", // 29 + 'icons' => "Icons", + 'profile' => "Profil", // 100 + 'profiles' => "Profile", + 'guide' => "Leitfaden", // 300 + 'guides' => "Leitfäden", + 'emote' => "Emote", // 501 + 'emotes' => "Emotes", + 'enchantment' => "Verzauberung", // 502 + 'enchantments' => "Verzauberungen", + 'areatrigger' => "Areatrigger", // 503 + 'areatriggers' => "Areatrigger", + 'mail' => "Brief", // 504 + 'mails' => "Briefe", + + 'cooldown' => "%s Abklingzeit", 'difficulty' => "Modus", 'dispelType' => "Bannart", 'duration' => "Dauer", - 'emote' => "Emote", - 'emotes' => "Emotes", - 'enchantment' => "Verzauberung", - 'enchantments' => "Verzauberungen", - 'flags' => "Flags", - 'object' => "Objekt", - 'objects' => "Objekte", - 'glyphType' => "Glyphenart", - 'race' => "Volk", - 'races' => "Völker", - 'title' => "Titel", - 'titles' => "Titel", 'eventShort' => "Ereignis", - 'event' => "Weltereigniss", - 'events' => "Weltereignisse", - 'faction' => "Fraktion", - 'factions' => "Fraktionen", - 'cooldown' => "%s Abklingzeit", - 'icon' => "Icon", - 'icons' => "Icons", - 'item' => "Gegenstand", - 'items' => "Gegenstände", - 'itemset' => "Ausrüstungsset", - 'itemsets' => "Ausrüstungssets", - 'mail' => "Brief", - 'mails' => "Briefe", + 'flags' => "Flags", + 'glyphType' => "Glyphenart", + 'level' => "Stufe", 'mechanic' => "Auswirkung", 'mechAbbr' => "Ausw.", 'meetingStone' => "Versammlungsstein", - 'npc' => "NPC", - 'npcs' => "NPCs", - 'pet' => "Begleiter", - 'pets' => "Begleiter", - 'profile' => "Profil", - 'profiles' => "Profile", - 'quest' => "Quest", - 'quests' => "Quests", 'requires' => "Benötigt %s", 'requires2' => "Benötigt", 'reqLevel' => "Benötigt Stufe %s", 'reqSkillLevel' => "Benötigte Fertigkeitsstufe", - 'level' => "Stufe", 'school' => "Magieart", - 'skill' => "Fertigkeit", - 'skills' => "Fertigkeiten", - 'sound' => "Klang", - 'sounds' => "Klänge", - 'spell' => "Zauber", - 'spells' => "Zauber", 'type' => "Art", 'valueDelim' => " - ", // " bis " - 'zone' => "Zone", - 'zones' => "Gebiete", 'pvp' => "PvP", 'honorPoints' => "Ehrenpunkte", diff --git a/localization/locale_enus.php b/localization/locale_enus.php index 2f3bc2b1..f3d908c4 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -159,8 +159,6 @@ $lang = array( ) ), 'guide' => array( - 'guide' => "Guide", - 'guides' => "Guides", 'myGuides' => "My Guides", 'editTitle' => "Edit your Guide", 'newTitle' => "Create New Guide", @@ -275,70 +273,74 @@ $lang = array( ) ), 'game' => array( - 'achievement' => "achievement", - 'achievements' => "Achievements", - 'areatrigger' => "areatrigger", - 'areatriggers' => "Areatrigger", - 'class' => "class", - 'classes' => "Classes", - 'currency' => "currency", - 'currencies' => "Currencies", - 'difficulty' => "Difficulty", - 'dispelType' => "Dispel type", - 'duration' => "Duration", - 'emote' => "emote", - 'emotes' => "Emotes", - 'enchantment' => "enchantment", - 'enchantments' => "Enchantments", - 'flags' => "Flags", + // type strings + 'npc' => "NPC", + 'npcs' => "NPCs", 'object' => "object", 'objects' => "Objects", - 'glyphType' => "Glyph type", - 'race' => "race", - 'races' => "Races", - 'title' => "title", - 'titles' => "Titles", - 'eventShort' => "Event", - 'event' => "World Event", - 'events' => "World Events", - 'faction' => "faction", - 'factions' => "Factions", - 'cooldown' => "%s cooldown", - 'icon' => "icon", - 'icons' => "icons", 'item' => "item", 'items' => "Items", 'itemset' => "item Set", 'itemsets' => "Item Sets", + 'quest' => "quest", + 'quests' => "Quests", + 'spell' => "spell", + 'spells' => "Spells", + 'zone' => "zone", + 'zones' => "Zones", + 'faction' => "faction", + 'factions' => "Factions", + 'pet' => "Pet", + 'pets' => "Hunter Pets", + 'achievement' => "achievement", + 'achievements' => "Achievements", + 'title' => "title", + 'titles' => "Titles", + 'event' => "World Event", + 'events' => "World Events", + 'class' => "class", + 'classes' => "Classes", + 'race' => "race", + 'races' => "Races", + 'skill' => "skill", + 'skills' => "Skills", + 'currency' => "currency", + 'currencies' => "Currencies", + 'sound' => "sound", + 'sounds' => "Sounds", + 'icon' => "icon", + 'icons' => "icons", + 'profile' => "profile", + 'profiles' => "Profiles", + 'guide' => "Guide", + 'guides' => "Guides", + 'emote' => "emote", + 'emotes' => "Emotes", + 'enchantment' => "enchantment", + 'enchantments' => "Enchantments", + 'areatrigger' => "areatrigger", + 'areatriggers' => "Areatrigger", 'mail' => "mail", 'mails' => "Mails", + + 'cooldown' => "%s cooldown", + 'difficulty' => "Difficulty", + 'dispelType' => "Dispel type", + 'duration' => "Duration", + 'eventShort' => "Event", + 'flags' => "Flags", + 'glyphType' => "Glyph type", + 'level' => "Level", 'mechanic' => "Mechanic", 'mechAbbr' => "Mech.", 'meetingStone' => "Meeting Stone", - 'npc' => "NPC", - 'npcs' => "NPCs", - 'pet' => "Pet", - 'pets' => "Hunter Pets", - 'profile' => "profile", - 'profiles' => "Profiles", - 'quest' => "quest", - 'quests' => "Quests", 'requires' => "Requires %s", 'requires2' => "Requires", 'reqLevel' => "Requires Level %s", 'reqSkillLevel' => "Required skill level", - 'level' => "Level", 'school' => "School", - 'skill' => "skill", - 'skills' => "Skills", - 'sound' => "sound", - 'sounds' => "Sounds", - 'spell' => "spell", - 'spells' => "Spells", 'type' => "Type", 'valueDelim' => " to ", - 'zone' => "zone", - 'zones' => "Zones", 'pvp' => "PvP", // PVP 'honorPoints' => "Honor Points", // HONOR_POINTS diff --git a/localization/locale_eses.php b/localization/locale_eses.php index 765a78f7..b80f7902 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -159,8 +159,6 @@ $lang = array( ) ), 'guide' => array( - 'guide' => "Guía", - 'guides' => "Guías", 'myGuides' => "Mis Guías", 'editTitle' => "Editar tu Guía", 'newTitle' => "Crear Nueva Guía", @@ -275,70 +273,74 @@ $lang = array( ) ), 'game' => array( - 'achievement' => "logro", - 'achievements' => "Logros", - 'areatrigger' => "areatrigger", - 'areatriggers' => "Areatrigger", - 'class' => "clase", - 'classes' => "Clases", - 'currency' => "monedas", - 'currencies' => "Monedas", - 'difficulty' => "Dificultad", - 'dispelType' => "Tipo de disipación", - 'duration' => "Duración", - 'emote' => "emoción", - 'emotes' => "Emociones", - 'enchantment' => "encantamiento", - 'enchantments' => "Encantamientos", - 'flags' => "Banderas", + // type strings + 'npc' => "PNJ", + 'npcs' => "PNJs", 'object' => "entidad", 'objects' => "Entidades", - 'glyphType' => "Tipo de glifo", - 'race' => "raza", - 'races' => "Razas", - 'title' => "título", - 'titles' => "Títulos", - 'eventShort' => "Evento", - 'event' => "Suceso mundial ", - 'events' => "Eventos del mundo", - 'faction' => "facción", - 'factions' => "Facciones", - 'cooldown' => "%s de reutilización", - 'icon' => "icono", - 'icons' => "Iconos", 'item' => "objeto", 'items' => "Objetos", 'itemset' => "conjunto de objetos", 'itemsets' => "Conjuntos de objetos", + 'quest' => "misión", + 'quests' => "Misiones", + 'spell' => "hechizo", + 'spells' => "Hechizos", + 'zone' => "zona", + 'zones' => "Zonas", + 'faction' => "facción", + 'factions' => "Facciones", + 'pet' => "Mascota", + 'pets' => "Mascotas de cazador", + 'achievement' => "logro", + 'achievements' => "Logros", + 'title' => "título", + 'titles' => "Títulos", + 'event' => "Suceso mundial ", + 'events' => "Eventos del mundo", + 'class' => "clase", + 'classes' => "Clases", + 'race' => "raza", + 'races' => "Razas", + 'skill' => "habilidad", + 'skills' => "Habilidades", + 'currency' => "monedas", + 'currencies' => "Monedas", + 'sound' => "sonido", + 'sounds' => "Sonidos", + 'icon' => "icono", + 'icons' => "Iconos", + 'profile' => "Perfile", + 'profiles' => "Perfiles", + 'guide' => "Guía", + 'guides' => "Guías", + 'emote' => "emoción", + 'emotes' => "Emociones", + 'enchantment' => "encantamiento", + 'enchantments' => "Encantamientos", + 'areatrigger' => "areatrigger", + 'areatriggers' => "Areatrigger", 'mail' => "mail", 'mails' => "Mails", + + 'cooldown' => "%s de reutilización", + 'difficulty' => "Dificultad", + 'dispelType' => "Tipo de disipación", + 'duration' => "Duración", + 'eventShort' => "Evento", + 'flags' => "Banderas", + 'glyphType' => "Tipo de glifo", + 'level' => "Nivel", 'mechanic' => "Mecanica", 'mechAbbr' => "Mec.", 'meetingStone' => "Roca de encuentro", - 'npc' => "PNJ", - 'npcs' => "PNJs", - 'pet' => "Mascota", - 'pets' => "Mascotas de cazador", - 'profile' => "", - 'profiles' => "Perfiles", - 'quest' => "misión", - 'quests' => "Misiones", 'requires' => "Requiere %s", 'requires2' => "Requiere", 'reqLevel' => "Necesitas ser de nivel %s", 'reqSkillLevel' => "Requiere nivel de habilidad", - 'level' => "Nivel", 'school' => "Escuela", - 'skill' => "habilidad", - 'skills' => "Habilidades", - 'sound' => "sonido", - 'sounds' => "Sonidos", - 'spell' => "hechizo", - 'spells' => "Hechizos", 'type' => "Tipo", 'valueDelim' => " - ", - 'zone' => "zona", - 'zones' => "Zonas", 'pvp' => "JcJ", 'honorPoints' => "Puntos de Honor", diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index c1e0999d..2ed96a91 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -159,8 +159,6 @@ $lang = array( ) ), 'guide' => array( - 'guide' => "Guide", - 'guides' => "Guides", 'myGuides' => "Mes guides", 'editTitle' => "Editez votre Guide", 'newTitle' => "Créer un nouveau Guide", @@ -275,70 +273,74 @@ $lang = array( ) ), 'game' => array( - 'achievement' => "haut fait", - 'achievements' => "Hauts faits", - 'areatrigger' => "areatrigger", - 'areatriggers' => "Areatrigger", - 'class' => "classe", - 'classes' => "Classes", - 'currency' => "monnaies", - 'currencies' => "Monnaies", - 'difficulty' => "Difficulté", - 'dispelType' => "Type de dissipation", - 'duration' => "Durée", - 'emote' => "emote", - 'emotes' => "Emotes", - 'enchantment' => "enchantement", - 'enchantments' => "Enchantements", - 'flags' => "Marqueurs", + // type strings + 'npc' => "PNJ", + 'npcs' => "PNJs", 'object' => "entité", 'objects' => "Entités", - 'glyphType' => "Type de glyphe", - 'race' => "race", - 'races' => "Races", - 'title' => "titre", - 'titles' => "Titres", - 'eventShort' => "Évènement", - 'event' => "Évènement mondial", - 'events' => "Évènements mondiaux", - 'faction' => "faction", - 'factions' => "Factions", - 'cooldown' => "%s de recharge", - 'icon' => "icône", - 'icons' => "Icônes", 'item' => "objet", 'items' => "Objets", 'itemset' => "ensemble d'objets", 'itemsets' => "Ensembles d'objets", + 'quest' => "quête", + 'quests' => "Quêtes", + 'spell' => "sort", + 'spells' => "Sorts", + 'zone' => "zone", + 'zones' => "Zones", + 'faction' => "faction", + 'factions' => "Factions", + 'pet' => "Familier", + 'pets' => "Familiers de chasseur", + 'achievement' => "haut fait", + 'achievements' => "Hauts faits", + 'title' => "titre", + 'titles' => "Titres", + 'event' => "Évènement mondial", + 'events' => "Évènements mondiaux", + 'class' => "classe", + 'classes' => "Classes", + 'race' => "race", + 'races' => "Races", + 'skill' => "compétence", + 'skills' => "Compétences", + 'currency' => "monnaies", + 'currencies' => "Monnaies", + 'sound' => "son", + 'sounds' => "Sons", + 'icon' => "icône", + 'icons' => "Icônes", + 'profile' => "Profil", + 'profiles' => "Profils", + 'guide' => "Guide", + 'guides' => "Guides", + 'emote' => "emote", + 'emotes' => "Emotes", + 'enchantment' => "enchantement", + 'enchantments' => "Enchantements", + 'areatrigger' => "areatrigger", + 'areatriggers' => "Areatrigger", 'mail' => "mail", 'mails' => "Mails", + + 'cooldown' => "%s de recharge", + 'difficulty' => "Difficulté", + 'dispelType' => "Type de dissipation", + 'duration' => "Durée", + 'eventShort' => "Évènement", + 'flags' => "Marqueurs", + 'glyphType' => "Type de glyphe", + 'level' => "Niveau", 'mechanic' => "Mécanique", 'mechAbbr' => "Mécan.", 'meetingStone' => "Pierre de rencontre", - 'npc' => "PNJ", - 'npcs' => "PNJs", - 'pet' => "Familier", - 'pets' => "Familiers de chasseur", - 'profile' => "", - 'profiles' => "Profils", - 'quest' => "quête", - 'quests' => "Quêtes", 'requires' => "%s requis", 'requires2' => "Requiert", 'reqLevel' => "Niveau %s requis", 'reqSkillLevel' => "Niveau de compétence requis", - 'level' => "Niveau", 'school' => "École", - 'skill' => "compétence", - 'skills' => "Compétences", - 'sound' => "son", - 'sounds' => "Sons", - 'spell' => "sort", - 'spells' => "Sorts", 'type' => "Type", 'valueDelim' => " - ", - 'zone' => "zone", - 'zones' => "Zones", 'pvp' => "JcJ", 'honorPoints' => "Points d'honneur", diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index 83883829..a929147e 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -159,8 +159,6 @@ $lang = array( ) ), 'guide' => array( - 'guide' => "Руководство", - 'guides' => "Руководство", 'myGuides' => "Мои руководства", 'editTitle' => "Редактировать руководство", 'newTitle' => "Написать новое руководство", @@ -275,70 +273,74 @@ $lang = array( ) ), 'game' => array( - 'achievement' => "достижение", - 'achievements' => "Достижения", - 'areatrigger' => "areatrigger", - 'areatriggers' => "Areatrigger", - 'class' => "класс", - 'classes' => "Классы", - 'currency' => "валюта", - 'currencies' => "Валюта", - 'difficulty' => "Сложность", - 'dispelType' => "Тип рассеивания", - 'duration' => "Длительность", - 'emote' => "Эмоция", - 'emotes' => "Эмоции", - 'enchantment' => "улучшение", - 'enchantments' => "Улучшения", - 'flags' => "Метки", + // type strings + 'npc' => "НИП", + 'npcs' => "НИП", 'object' => "объект", 'objects' => "Объекты", - 'glyphType' => "Тип символа", - 'race' => "раса", - 'races' => "Расы", - 'title' => "звание", - 'titles' => "Звания", - 'eventShort' => "Игровое событие", - 'event' => "Событие", - 'events' => "Игровые события", - 'faction' => "фракция", - 'factions' => "Фракции", - 'cooldown' => "Восстановление: %s", - 'icon' => "иконка", - 'icons' => "Иконки", 'item' => "предмет", 'items' => "Предметы", 'itemset' => "комплект", 'itemsets' => "Комплекты", + 'quest' => "задание", + 'quests' => "Задания", + 'spell' => "заклинание", + 'spells' => "Заклинания", + 'zone' => "игровая зона", + 'zones' => "Местности", + 'faction' => "фракция", + 'factions' => "Фракции", + 'pet' => "Питомец", + 'pets' => "Питомцы охотников", + 'achievement' => "достижение", + 'achievements' => "Достижения", + 'title' => "звание", + 'titles' => "Звания", + 'event' => "Событие", + 'events' => "Игровые события", + 'class' => "класс", + 'classes' => "Классы", + 'race' => "раса", + 'races' => "Расы", + 'skill' => "Уровень навыка", + 'skills' => "Умения", + 'currency' => "валюта", + 'currencies' => "Валюта", + 'sound' => "Звук", + 'sounds' => "Звуки", + 'icon' => "иконка", + 'icons' => "Иконки", + 'profile' => "Профиль", + 'profiles' => "Профили", + 'guide' => "Руководство", + 'guides' => "Руководство", + 'emote' => "Эмоция", + 'emotes' => "Эмоции", + 'enchantment' => "улучшение", + 'enchantments' => "Улучшения", + 'areatrigger' => "areatrigger", + 'areatriggers' => "Areatrigger", 'mail' => "mail", 'mails' => "Mails", + + 'cooldown' => "Восстановление: %s", + 'difficulty' => "Сложность", + 'dispelType' => "Тип рассеивания", + 'duration' => "Длительность", + 'eventShort' => "Игровое событие", + 'flags' => "Метки", + 'glyphType' => "Тип символа", + 'level' => "Уровень", 'mechanic' => "Механика", 'mechAbbr' => "Механика", 'meetingStone' => "Камень встреч", - 'npc' => "НИП", - 'npcs' => "НИП", - 'pet' => "Питомец", - 'pets' => "Питомцы охотников", - 'profile' => "", - 'profiles' => "Профили", - 'quest' => "задание", - 'quests' => "Задания", 'requires' => "Требует %s", 'requires2' => "Требуется:", 'reqLevel' => "Требуется уровень: %s", 'reqSkillLevel' => "Требуется уровень навыка", - 'level' => "Уровень", 'school' => "Школа", - 'skill' => "Уровень навыка", - 'skills' => "Умения", - 'sound' => "Звук", - 'sounds' => "Звуки", - 'spell' => "заклинание", - 'spells' => "Заклинания", 'type' => "Тип", 'valueDelim' => " - ", - 'zone' => "игровая зона", - 'zones' => "Местности", 'pvp' => "PvP", 'honorPoints' => "Очки Чести", diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php index 42864801..fc3b6d8a 100644 --- a/localization/locale_zhcn.php +++ b/localization/locale_zhcn.php @@ -159,8 +159,6 @@ $lang = array( ) ), 'guide' => array( - 'guide' => "指南", - 'guides' => "指南", 'myGuides' => "我的指南", 'editTitle' => "编辑你的指南", 'newTitle' => "创建新指南", @@ -275,70 +273,73 @@ $lang = array( ) ), 'game' => array( - 'achievement' => "成就", - 'achievements' => "成就", - 'areatrigger' => "areatrigger", - 'areatriggers' => "Areatrigger", - 'class' => "职业", - 'classes' => "职业", - 'currency' => "货币", - 'currencies' => "货币", - 'difficulty' => "难度", - 'dispelType' => "驱散类型", - 'duration' => "持续时间", - 'emote' => "表情", - 'emotes' => "表情", - 'enchantment' => "附魔", - 'enchantments' => "附魔", - 'flags' => "标记", + 'npc' => "NPC", + 'npcs' => "NPC", 'object' => "对象", 'objects' => "对象", - 'glyphType' => "雕文类型", - 'race' => "种族", - 'races' => "种族", - 'title' => "头衔", - 'titles' => "头衔", - 'eventShort' => "事件", - 'event' => "世界事件", - 'events' => "世界事件", - 'faction' => "阵营", - 'factions' => "阵营", - 'cooldown' => "%s冷却时间", - 'icon' => "图标", - 'icons' => "图标", 'item' => "物品", 'items' => "物品", 'itemset' => "套装", 'itemsets' => "套装", + 'quest' => "任务", + 'quests' => "任务", + 'spell' => "法术", + 'spells' => "法术", + 'zone' => "区域", + 'zones' => "区域", + 'faction' => "阵营", + 'factions' => "阵营", + 'pet' => "猎人宠物", + 'pets' => "猎人宠物", + 'achievement' => "成就", + 'achievements' => "成就", + 'title' => "头衔", + 'titles' => "头衔", + 'event' => "世界事件", + 'events' => "世界事件", + 'class' => "职业", + 'classes' => "职业", + 'race' => "种族", + 'races' => "种族", + 'skill' => "技能", + 'skills' => "技能", + 'currency' => "货币", + 'currencies' => "货币", + 'sound' => "声音", + 'sounds' => "声音", + 'icon' => "图标", + 'icons' => "图标", + 'profile' => "简介", + 'profiles' => "简介", + 'guide' => "指南", + 'guides' => "指南", + 'emote' => "表情", + 'emotes' => "表情", + 'enchantment' => "附魔", + 'enchantments' => "附魔", + 'areatrigger' => "areatrigger", + 'areatriggers' => "Areatrigger", 'mail' => "mail", 'mails' => "Mails", + + 'cooldown' => "%s冷却时间", + 'difficulty' => "难度", + 'dispelType' => "驱散类型", + 'duration' => "持续时间", + 'eventShort' => "事件", + 'flags' => "标记", + 'glyphType' => "雕文类型", + 'level' => "等级", 'mechanic' => "机制", 'mechAbbr' => "机制", 'meetingStone' => "集合石", - 'npc' => "NPC", - 'npcs' => "NPC", - 'pet' => "猎人宠物", - 'pets' => "猎人宠物", - 'profile' => "简介", - 'profiles' => "简介", - 'quest' => "任务", - 'quests' => "任务", 'requires' => "需要%s", 'requires2' => "需要", 'reqLevel' => "需要等级%s", 'reqSkillLevel' => "需要技能等级", - 'level' => "等级", 'school' => "类型", - 'skill' => "技能", - 'skills' => "技能", - 'sound' => "声音", - 'sounds' => "声音", - 'spell' => "法术", - 'spells' => "法术", 'type' => "类型", 'valueDelim' => "到", - 'zone' => "区域", - 'zones' => "区域", 'pvp' => "PvP", 'honorPoints' => "荣誉点数", diff --git a/pages/guide.php b/pages/guide.php index f9d1d7ae..923ff653 100644 --- a/pages/guide.php +++ b/pages/guide.php @@ -106,7 +106,7 @@ class GuidePage extends GenericPage if (User::canWriteGuide()) { if (!$this->initEdit()) - $this->notFound(Lang::guide('guide'), Lang::guide('notFound')); + $this->notFound(Lang::game('guide'), Lang::guide('notFound')); $this->show = self::SHOW_EDITOR; } @@ -128,7 +128,7 @@ class GuidePage extends GenericPage $this->subject = new GuideList(array(['id', $this->typeId])); if ($this->subject->error) - $this->notFound(Lang::guide('guide'), Lang::guide('notFound')); + $this->notFound(Lang::game('guide'), Lang::guide('notFound')); if (!$this->subject->canBeViewed() && !$this->subject->userCanView()) header('Location: ?guides='.$this->subject->getField('category'), true, 302); @@ -188,7 +188,7 @@ class GuidePage extends GenericPage { // can't check in init as subject is unknown if ($this->subject->getField('status') == GUIDE_STATUS_ARCHIVED) - $this->notFound(Lang::guide('guide'), Lang::guide('notFound')); + $this->notFound(Lang::game('guide'), Lang::guide('notFound')); $status = GUIDE_STATUS_NONE; $rev = DB::Aowow()->selectCell('SELECT `rev` FROM ?_articles WHERE `type` = ?d AND `typeId` = ?d ORDER BY `rev` DESC LIMIT 1', Type::GUIDE, $this->typeId); @@ -537,11 +537,11 @@ class GuidePage extends GenericPage protected function generateTitle() : void { if ($this->show == self::SHOW_EDITOR) - array_unshift($this->title, Lang::guide('editTitle').Lang::main('colon').$this->subject->getField('title'), Lang::guide('guides')); + array_unshift($this->title, Lang::guide('editTitle').Lang::main('colon').$this->subject->getField('title'), Lang::game('guides')); if ($this->show == self::SHOW_NEW) - array_unshift($this->title, Lang::guide('newTitle'), Lang::guide('guides')); + array_unshift($this->title, Lang::guide('newTitle'), Lang::game('guides')); else - array_unshift($this->title, $this->subject->getField('title'), Lang::guide('guides')); + array_unshift($this->title, $this->subject->getField('title'), Lang::game('guides')); } protected function postCache() : void diff --git a/pages/guides.php b/pages/guides.php index 44451737..6372c916 100644 --- a/pages/guides.php +++ b/pages/guides.php @@ -34,7 +34,7 @@ class GuidesPage extends GenericPage $this->myGuides = true; } else - $this->name = Util::ucFirst(Lang::guide('guides')); + $this->name = Util::ucFirst(Lang::game('guides')); } protected function generateContent() @@ -71,7 +71,7 @@ class GuidesPage extends GenericPage $tabData = array( 'data' => $data, - 'name' => Util::ucFirst(Lang::guide('guides')), + 'name' => Util::ucFirst(Lang::game('guides')), 'hiddenCols' => $hCols, 'visibleCols' => $vCols, 'extraCols' => $xCols diff --git a/prQueue b/prQueue index 716a6e8a..1d4fa298 100755 --- a/prQueue +++ b/prQueue @@ -28,11 +28,11 @@ $tCycle = microtime(true); $error = function ($type, $realmGUID, $realmId) { $what = ''; - if ($type == TYPE_PROFILE) + if ($type == Type::PROFILE) $what = 'char'; - if ($type == TYPE_GUILD) + if ($type == Type::GUILD) $what = 'guild'; - if ($type == TYPE_ARENA_TEAM) + if ($type == Type::ARENA_TEAM) $what = 'arena team'; DB::Aowow()->query('UPDATE ?_profiler_sync SET status = ?d, errorCode = ?d WHERE realm = ?d AND realmGUID = ?d AND type = ?d', PR_QUEUE_STATUS_ERROR, PR_QUEUE_ERROR_CHAR, $realmId, $realmGUID, $type); @@ -73,28 +73,28 @@ while (DB::Aowow()->selectCell('SELECT value FROM ?_config WHERE `key` = "profil switch ($row['type']) { - case TYPE_PROFILE: + case Type::PROFILE: if (!Profiler::getCharFromRealm($row['realm'], $row['realmGUID'])) { - $error(TYPE_PROFILE, $row['realmGUID'], $row['realm']); + $error(Type::PROFILE, $row['realmGUID'], $row['realm']); DB::Aowow()->query('DELETE FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $row['realm'], $row['realmGUID']); continue 2; } break; - case TYPE_GUILD: + case Type::GUILD: if (!Profiler::getGuildFromRealm($row['realm'], $row['realmGUID'])) { - $error(TYPE_GUILD, $row['realmGUID'], $row['realm']); + $error(Type::GUILD, $row['realmGUID'], $row['realm']); DB::Aowow()->query('DELETE FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $row['realm'], $row['realmGUID']); continue 2; } break; - case TYPE_ARENA_TEAM: + case Type::ARENA_TEAM: if (!Profiler::getArenaTeamFromRealm($row['realm'], $row['realmGUID'])) { - $error(TYPE_ARENA_TEAM, $row['realmGUID'], $row['realm']); + $error(Type::ARENA_TEAM, $row['realmGUID'], $row['realm']); DB::Aowow()->query('DELETE FROM ?_profiler_arena_team WHERE realm = ?d AND realmGUID = ?d', $row['realm'], $row['realmGUID']); continue 2; } From e572967c08f352beaed2b90bb6e51b254b79f480 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Wed, 23 Mar 2022 11:19:00 +0100 Subject: [PATCH 005/698] Misc/Fixup * lost changes to timestamps from a8edf6c9123d0f45ead885bfee1388eb86296b0d * dates on comment, screenshot, video previews are now formatted correctly --- pages/utility.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pages/utility.php b/pages/utility.php index fd9f1ca7..a571ccde 100644 --- a/pages/utility.php +++ b/pages/utility.php @@ -93,7 +93,10 @@ class UtilityPage extends GenericPage } } else + { + array_walk($data, fn(&$d) => $d['date'] = date(Util::$dateFormatInternal, $d['date'])); $this->lvTabs[] = ['commentpreview', ['data' => array_values($data)]]; + } break; case 'latest-screenshots': // rss @@ -121,7 +124,10 @@ class UtilityPage extends GenericPage } } else + { + array_walk($data, fn(&$d) => $d['date'] = date(Util::$dateFormatInternal, $d['date'])); $this->lvTabs[] = ['screenshot', ['data' => array_values($data)]]; + } break; case 'latest-videos': // rss @@ -149,7 +155,10 @@ class UtilityPage extends GenericPage } } else + { + array_walk($data, fn(&$d) => $d['date'] = date(Util::$dateFormatInternal, $d['date'])); $this->lvTabs[] = ['video', ['data' => array_values($data)]]; + } break; case 'unrated-comments': From 05f6d68070f1cbc0e6d17f4f805de2389b4ec5f0 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Wed, 23 Mar 2022 19:28:40 +0100 Subject: [PATCH 006/698] Utility * implemented page: unrated-comment --- includes/community.class.php | 2 ++ pages/utility.php | 5 +---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/includes/community.class.php b/includes/community.class.php index f4359a08..c12e180e 100644 --- a/includes/community.class.php +++ b/includes/community.class.php @@ -95,6 +95,7 @@ class CommunityContent {c.userId = ?d AND} {c.replyTo <> ?d AND} {c.replyTo = ?d AND} + {ur.entry IS ?n AND} ((c.flags & ?d) = 0 OR c.userId = ?d OR ?d) GROUP BY c.id @@ -141,6 +142,7 @@ class CommunityContent empty($params['user']) ? DBSIMPLE_SKIP : $params['user'], empty($params['replies']) ? DBSIMPLE_SKIP : 0, // i dont know, how to switch the sign around !empty($params['replies']) ? DBSIMPLE_SKIP : 0, + empty($params['unrated']) ? DBSIMPLE_SKIP : null, CC_FLAG_DELETED, User::$id, User::isInGroup(U_GROUP_COMMENTS_MODERATOR), diff --git a/pages/utility.php b/pages/utility.php index a571ccde..45bce104 100644 --- a/pages/utility.php +++ b/pages/utility.php @@ -162,9 +162,7 @@ class UtilityPage extends GenericPage break; case 'unrated-comments': - - // EXPLAIN SELECT ac.* FROM aowow_comments ac LEFT JOIN aowow_comments_rates acr ON acr.commentId = ac.id AND acr.userId <> 0 WHERE acr.commentId IS NULL; - if ($_ = CommunityContent::getCommentPreviews(['user' => User::$id, 'replies' => false], $nFound)) + if ($_ = CommunityContent::getCommentPreviews(['unrated' => true], $nFound)) { $tabData = array( 'data' => $_, @@ -181,7 +179,6 @@ class UtilityPage extends GenericPage $this->lvTabs[] = ['commentpreview', $tabData]; } - $this->lvTabs[] = ['commentpreview', ['data' => []]]; break; case 'missing-screenshots': From 32b4c451e44aafed07200ca6aaed2ad0afe00167 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Thu, 24 Mar 2022 10:37:13 +0100 Subject: [PATCH 007/698] Misc/Fixup * remove unnecessary tab components from ?unrated-comments page * fix urls generated by guides listview --- includes/types/guide.class.php | 4 +--- pages/utility.php | 18 ++---------------- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/includes/types/guide.class.php b/includes/types/guide.class.php index 02359abe..a1957652 100644 --- a/includes/types/guide.class.php +++ b/includes/types/guide.class.php @@ -92,7 +92,7 @@ class GuideList extends BaseType 'description' => $this->getField('description'), 'sticky' => !!($this->getField('cuFlags') & CC_FLAG_STICKY), 'nvotes' => $this->getField('nvotes'), - 'url' => '/?guide=' . ($this->getField('url') ?: $this->id), + 'url' => '?guide=' . ($this->getField('url') ?: $this->id), 'status' => $this->getField('status'), 'author' => $this->getField('author'), 'authorroles' => $this->getField('roles'), @@ -103,8 +103,6 @@ class GuideList extends BaseType 'date' => $this->getField('date'), // ok 'when' => date(Util::$dateFormatInternal, $this->getField('date')) ); - - } return $data; diff --git a/pages/utility.php b/pages/utility.php index 45bce104..441ba989 100644 --- a/pages/utility.php +++ b/pages/utility.php @@ -162,22 +162,8 @@ class UtilityPage extends GenericPage break; case 'unrated-comments': - if ($_ = CommunityContent::getCommentPreviews(['unrated' => true], $nFound)) - { - $tabData = array( - 'data' => $_, - 'onBeforeCreate' => '$Listview.funcBox.beforeUserComments', - '_totalCount' => $nFound - ); - - if ($nFound > CFG_SQL_LIMIT_DEFAULT) - { - $tabData['name'] = '$LANG.tab_latestcomments'; - $tabData['note'] = '$$WH.sprintf(LANG.lvnote_usercomments, '.$nFound.')'; - } - - $this->lvTabs[] = ['commentpreview', $tabData]; - } + if ($_ = CommunityContent::getCommentPreviews(['unrated' => true])) + $this->lvTabs[] = ['commentpreview', ['data' => $_]]; $this->lvTabs[] = ['commentpreview', ['data' => []]]; break; From 04e55b54983aaaee564e06f1cf71fe717fd67237 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 25 Mar 2022 15:24:51 +0100 Subject: [PATCH 008/698] NPCs/Vendors * show restock time if available --- includes/types/item.class.php | 14 ++++++++------ pages/npc.php | 13 ++++++++++--- static/js/locale_dede.js | 2 ++ static/js/locale_enus.js | 2 ++ static/js/locale_eses.js | 2 ++ static/js/locale_frfr.js | 2 ++ static/js/locale_ruru.js | 2 ++ static/js/locale_zhcn.js | 2 ++ template/listviews/vendorRestockCol.tpl.php | 14 ++++++++++++++ 9 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 template/listviews/vendorRestockCol.tpl.php diff --git a/includes/types/item.class.php b/includes/types/item.class.php index 2354f50a..139c11e8 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -102,9 +102,9 @@ class ItemList extends BaseType $itemz = []; $xCostData = []; $rawEntries = DB::World()->select(' - SELECT nv.item, nv.entry, 0 AS eventId, nv.maxcount, nv.extendedCost FROM npc_vendor nv WHERE {nv.entry IN (?a) AND} nv.item IN (?a) + SELECT nv.item, nv.entry, 0 AS eventId, nv.maxcount, nv.extendedCost, nv.incrtime FROM npc_vendor nv WHERE {nv.entry IN (?a) AND} nv.item IN (?a) UNION - SELECT genv.item, c.id AS `entry`, ge.eventEntry AS eventId, genv.maxcount, genv.extendedCost FROM game_event_npc_vendor genv LEFT JOIN game_event ge ON genv.eventEntry = ge.eventEntry JOIN creature c ON c.guid = genv.guid WHERE {c.id IN (?a) AND} genv.item IN (?a)', + SELECT genv.item, c.id AS `entry`, ge.eventEntry AS eventId, genv.maxcount, genv.extendedCost, genv.incrtime FROM game_event_npc_vendor genv LEFT JOIN game_event ge ON genv.eventEntry = ge.eventEntry JOIN creature c ON c.guid = genv.guid WHERE {c.id IN (?a) AND} genv.item IN (?a)', empty($filter[Type::NPC]) || !is_array($filter[Type::NPC]) ? DBSIMPLE_SKIP : $filter[Type::NPC], array_keys($this->templates), empty($filter[Type::NPC]) || !is_array($filter[Type::NPC]) ? DBSIMPLE_SKIP : $filter[Type::NPC], @@ -136,9 +136,10 @@ class ItemList extends BaseType if (!empty($xCostData[$vInfo['extendedCost']])) $costs = $xCostData[$vInfo['extendedCost']]; - $data = array( + $data = array( 'stock' => $vInfo['maxcount'] ?: -1, 'event' => $vInfo['eventId'], + 'restock' => $vInfo['incrtime'], 'reqRating' => $costs ? $costs['reqPersonalRating'] : 0, 'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0 ); @@ -360,9 +361,10 @@ class ItemList extends BaseType $currency[] = [-$k, $qty]; } - $costArr['stock'] = $entries['stock'];// display as column in lv - $costArr['avail'] = $entries['stock'];// display as number on icon - $costArr['cost'] = [empty($entries[0]) ? 0 : $entries[0]]; + $costArr['stock'] = $entries['stock'];// display as column in lv + $costArr['avail'] = $entries['stock'];// display as number on icon + $costArr['cost'] = [empty($entries[0]) ? 0 : $entries[0]]; + $costArr['restock'] = $entries['restock']; if ($entries['event']) { diff --git a/pages/npc.php b/pages/npc.php index b94c4a59..a791b153 100644 --- a/pages/npc.php +++ b/pages/npc.php @@ -621,12 +621,19 @@ class NpcPage extends GenericPage $soldItems = new ItemList(array(['id', $sells])); if (!$soldItems->error) { + $colAddIn = ''; $extraCols = ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost']; - if ($soldItems->hasSetFields(['condition'])) - $extraCols[] = '$Listview.extraCols.condition'; + if ($soldItems->hasSetFields(['condition'])) + $extraCols[] = '$Listview.extraCols.condition'; $lvData = $soldItems->getListviewData(ITEMINFO_VENDOR, [Type::NPC => [$this->typeId]]); + if (array_filter(array_column($lvData, 'restock'))) + { + $extraCols[] = '$_'; + $colAddIn = 'vendorRestockCol'; + } + $sc = Util::getServerConditions(CND_SRC_NPC_VENDOR, $this->typeId); if (!empty($sc[0])) { @@ -645,7 +652,7 @@ class NpcPage extends GenericPage 'name' => '$LANG.tab_sells', 'id' => 'currency-for', 'extraCols' => array_unique($extraCols) - )]; + ), $colAddIn]; $this->extendGlobalData($soldItems->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); } diff --git a/static/js/locale_dede.js b/static/js/locale_dede.js index 5280c9cc..f0333879 100644 --- a/static/js/locale_dede.js +++ b/static/js/locale_dede.js @@ -4850,6 +4850,8 @@ var LANG = { guideAuthor: 'Leitfadenautor', autoresizetextbox: 'Textfeld automatisch anpassen', + restock: 'Nachschub', + descriptionlengthlong_tip: 'Oh nein! Deine Beschreibung ist zu lang bei $1. Es wird wahrscheinlich gekürzt werden.', descriptionlengthoptimal_tip: 'Ihre Beschreibung hat eine gute Länge. Gut gemacht! Sie können sicher bis zu $1 hinzufügen, wenn nötig.', descriptionlengthshort_tip: 'Ihre Beschreibung ist zu kurz! $1 fehlen noch ...', diff --git a/static/js/locale_enus.js b/static/js/locale_enus.js index 7927e634..bf81bafe 100644 --- a/static/js/locale_enus.js +++ b/static/js/locale_enus.js @@ -4898,6 +4898,8 @@ var LANG = { guideAuthor: 'Guide Author', autoresizetextbox: 'Auto-Resize Text Box', + restock: 'Restock', + descriptionlengthlong_tip: 'Oh no! Your description is $1 too long! It will most likely be truncated.', descriptionlengthoptimal_tip: 'Your description is a good length. Good job! You can safely add up to $1 if needed.', descriptionlengthshort_tip: 'Your description is too short! $1 to go...', diff --git a/static/js/locale_eses.js b/static/js/locale_eses.js index 0cb9de05..b3c0243b 100644 --- a/static/js/locale_eses.js +++ b/static/js/locale_eses.js @@ -4853,6 +4853,8 @@ var LANG = { guideAuthor: '[Guide Author]', autoresizetextbox: 'Redimensionar automáticamente el cuadro de texto', + restock: '[Restock]', + descriptionlengthlong_tip: '¡Oh, no! Tu descripción es demasido larga por $1. Es muy posible que sea cortada', descriptionlengthoptimal_tip: 'Tu descripción es de la longitud óptima. ¡Buen trabajo! Si es necesario, puedes agregar hasta $1.', descriptionlengthshort_tip: '¡Tu descripción es demasiado corta! Te faltan $1...', diff --git a/static/js/locale_frfr.js b/static/js/locale_frfr.js index 607fcfcd..0d6242fe 100644 --- a/static/js/locale_frfr.js +++ b/static/js/locale_frfr.js @@ -4852,6 +4852,8 @@ var LANG = { guideAuthor: 'Auteur du guide', autoresizetextbox: 'Redimensionner automatiquement le champ texte', + restock: '[Restock]', + descriptionlengthlong_tip: 'Fichtre ! Votre description $1 est trop longue ! Elle sera probablement tronquée.', descriptionlengthoptimal_tip: 'Votre description est de longueur appropriée. Bien joué ! Vous pouvez sans problème ajouter jusqu\'à $1 si besoin.', descriptionlengthshort_tip: 'Votre description est trop courte ! Encore $1...', diff --git a/static/js/locale_ruru.js b/static/js/locale_ruru.js index 6d9b3d77..bf26973a 100644 --- a/static/js/locale_ruru.js +++ b/static/js/locale_ruru.js @@ -4854,6 +4854,8 @@ var LANG = { guideAuthor: 'Автор руководства', autoresizetextbox: 'Автоматически изменять размер поля с текстом', + restock: '[Restock]', + descriptionlengthlong_tip: 'Не может быть! Ваше описание $1 слишком велико! Вероятнее всего, оно будет сокращено.', descriptionlengthoptimal_tip: 'Ваше описание имеет оптимальную длину. Отлично! Если необходимо, вы можете добавить ещё $1 символов.', descriptionlengthshort_tip: 'Ваше описание слишком короткое! $1 чтобы', diff --git a/static/js/locale_zhcn.js b/static/js/locale_zhcn.js index a0b02959..e5f37443 100644 --- a/static/js/locale_zhcn.js +++ b/static/js/locale_zhcn.js @@ -4877,6 +4877,8 @@ var LANG = { guideAuthor: '[Guide Author]', autoresizetextbox: '自动缩放文字框', + restock: '[Restock]', + descriptionlengthlong_tip: '欧漏,你的描述超出了$1个字!可能会被删减哦。', descriptionlengthoptimal_tip: '你的注释已经达到了合理的长度。干的漂亮!', descriptionlengthshort_tip: '你的注释太短了!请再输入$1$个字。', diff --git a/template/listviews/vendorRestockCol.tpl.php b/template/listviews/vendorRestockCol.tpl.php new file mode 100644 index 00000000..11e17540 --- /dev/null +++ b/template/listviews/vendorRestockCol.tpl.php @@ -0,0 +1,14 @@ +var _ = { + id: 'restock', + name: LANG.restock, + width: '10%', + value: 'restock', + after: 'stack', + compute: function(data, td) { + if (data.restock) { + let t = g_formatTimeElapsed(data.restock); + + $WH.ae(td, $WH.ct(t)); + } + } +}; From 1f5e2645f0d605c1c9bf68d8e152ed9ea5e6c3a6 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 25 Mar 2022 15:57:42 +0100 Subject: [PATCH 009/698] Misc/Fixups * forgotten rename fails --- includes/smartAI.class.php | 4 ++-- includes/types/guide.class.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/smartAI.class.php b/includes/smartAI.class.php index 0929b740..07b648c3 100644 --- a/includes/smartAI.class.php +++ b/includes/smartAI.class.php @@ -1555,7 +1555,7 @@ class SmartAI { $type = Type::NPC; if ($spawnType == 1) - $type == Type::GAMEOBJECT; + $type == Type::OBJECT; $a['param'][7] = $this->spawnFlags('action', 3); @@ -1582,7 +1582,7 @@ class SmartAI case SAI_ACTION_RESPAWN_BY_SPAWNID: // 133 $type = Type::NPC; if ($a['param'][0] == 1) - $type == Type::GAMEOBJECT; + $type == Type::OBJECT; if ($_ = DB::Aowow()->selectCell('SELECT `typeId` FROM ?_spawns WHERE `type` = ?d AND `guid` = ?d', $type, $a['param'][1])) $a['param'][6] = '['.Type::getFileString($type).'='.$_.']'; diff --git a/includes/types/guide.class.php b/includes/types/guide.class.php index a1957652..97bec1ab 100644 --- a/includes/types/guide.class.php +++ b/includes/types/guide.class.php @@ -153,7 +153,7 @@ class GuideList extends BaseType } $tt = '
KeyValueOptions
'.$this->getField('title').'
'; - $tt .= '
'.Lang::guide('guide').''.Lang::guide('byAuthor', [$this->getField('author')]).'
'; + $tt .= '
'.Lang::game('guide').''.Lang::guide('byAuthor', [$this->getField('author')]).'
'; $tt .= '
'.Lang::guide('category', $this->getField('category')).$specStr.''.Lang::guide('patch').' 3.3.5
'; $tt .= '
'.$this->getField('description').'
'; $tt .= '
'; From b3e8f5e50f236a65e3a033273199ce881c397659 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 25 Mar 2022 16:32:04 +0100 Subject: [PATCH 010/698] DB/Mails * add field cuFlags to Type:Mail storage (RandomPage search no longer randomly fails, when randomly selecting mails) --- setup/db_structure.sql | 3 ++- setup/updates/1648222152_01.sql | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 setup/updates/1648222152_01.sql diff --git a/setup/db_structure.sql b/setup/db_structure.sql index daaa37f2..74967047 100644 --- a/setup/db_structure.sql +++ b/setup/db_structure.sql @@ -1623,6 +1623,7 @@ DROP TABLE IF EXISTS `aowow_mails`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `aowow_mails` ( `id` smallint(5) NOT NULL, + `cuFlags` int(10) unsigned NOT NULL DEFAULT 0, `subject_loc0` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, `subject_loc2` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, `subject_loc3` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, @@ -3184,7 +3185,7 @@ UNLOCK TABLES; LOCK TABLES `aowow_dbversion` WRITE; /*!40000 ALTER TABLE `aowow_dbversion` DISABLE KEYS */; -INSERT INTO `aowow_dbversion` VALUES (1647956310,0,NULL,NULL); +INSERT INTO `aowow_dbversion` VALUES (1648222153,0,NULL,NULL); /*!40000 ALTER TABLE `aowow_dbversion` ENABLE KEYS */; UNLOCK TABLES; diff --git a/setup/updates/1648222152_01.sql b/setup/updates/1648222152_01.sql new file mode 100644 index 00000000..e4daa30e --- /dev/null +++ b/setup/updates/1648222152_01.sql @@ -0,0 +1 @@ +ALTER TABLE aowow_mails ADD cuFlags INT UNSIGNED DEFAULT 0 NOT NULL AFTER id; From b08d30d04321023ecfbbd127bc40ac332e2f3a1c Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Mon, 28 Mar 2022 00:58:43 +0200 Subject: [PATCH 011/698] Screenshots/Crop * fixed coordinate filter broken after a8edf6c9123d0f45ead885bfee1388eb86296b0d --- includes/utilities.php | 2 +- pages/screenshot.php | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/includes/utilities.php b/includes/utilities.php index 98d25b6d..ebaa856f 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -103,7 +103,7 @@ trait TrRequestData private static function checkIdListUnsigned(string $val) : array { - if (preg_match('/\d+(,\d+)*/', $val)) + if (preg_match('/^\d+(,\d+)*$/', $val)) return array_map('intVal', explode(',', $val)); return []; diff --git a/pages/screenshot.php b/pages/screenshot.php index 6335b42f..f31a3483 100644 --- a/pages/screenshot.php +++ b/pages/screenshot.php @@ -28,7 +28,7 @@ class ScreenshotPage extends GenericPage protected $imgHash = ''; protected $_post = array( - 'coords' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkIdListUnsigned'], + 'coords' => ['filter' => FILTER_CALLBACK, 'options' => 'ScreenshotPage::checkCoords'], 'screenshotalt' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW] ); @@ -196,7 +196,7 @@ class ScreenshotPage extends GenericPage if (count($dims) != 4) return 3; - Util::checkNumeric($dims, NUM_REQ_INT); + Util::checkNumeric($dims, NUM_CAST_FLOAT); // actually crop the image $srcImg = imagecreatefromjpeg($fullPath); @@ -333,6 +333,14 @@ class ScreenshotPage extends GenericPage return $this->imgHash ? User::$displayName.'-'.$this->destType.'-'.$this->destTypeId.'-'.$this->imgHash : ''; } + protected static function checkCoords(string $val) : array + { + if (preg_match('/^[01]\.[0-9]{3}(,[01]\.[0-9]{3}){3}$/', $val)) + return explode(',', $val); + + return []; + } + protected function generatePath() : void { } protected function generateTitle() : void { From 6db77ed4f28772f688f8b386af1f87fde819fb88 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Mon, 28 Mar 2022 16:16:59 +0200 Subject: [PATCH 012/698] CommunityContent/Listing * generally use indexed/non-asssociative arrays when returning content --- includes/community.class.php | 6 +++--- pages/utility.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/includes/community.class.php b/includes/community.class.php index c12e180e..522d4b33 100644 --- a/includes/community.class.php +++ b/includes/community.class.php @@ -178,7 +178,7 @@ class CommunityContent } } - return $comments; + return array_values($comments); } public static function getCommentReplies(int $commentId, int $limit = 0, ?int &$nFound = 0) : array @@ -440,7 +440,7 @@ class CommunityContent unset($v['user']); } - return $videos; + return array_values($videos); } public static function getScreenshots(int $typeOrUser = 0, int $typeId = 0, int &$nFound = 0, bool $dateFmt = true) : array @@ -484,7 +484,7 @@ class CommunityContent unset($s['user']); } - return $screenshots; + return array_values($screenshots); } public static function getAll(int $type, int $typeId, array &$jsg) : array diff --git a/pages/utility.php b/pages/utility.php index 441ba989..acc1772a 100644 --- a/pages/utility.php +++ b/pages/utility.php @@ -95,7 +95,7 @@ class UtilityPage extends GenericPage else { array_walk($data, fn(&$d) => $d['date'] = date(Util::$dateFormatInternal, $d['date'])); - $this->lvTabs[] = ['commentpreview', ['data' => array_values($data)]]; + $this->lvTabs[] = ['commentpreview', ['data' => $data]]; } break; @@ -126,7 +126,7 @@ class UtilityPage extends GenericPage else { array_walk($data, fn(&$d) => $d['date'] = date(Util::$dateFormatInternal, $d['date'])); - $this->lvTabs[] = ['screenshot', ['data' => array_values($data)]]; + $this->lvTabs[] = ['screenshot', ['data' => $data]]; } break; @@ -157,7 +157,7 @@ class UtilityPage extends GenericPage else { array_walk($data, fn(&$d) => $d['date'] = date(Util::$dateFormatInternal, $d['date'])); - $this->lvTabs[] = ['video', ['data' => array_values($data)]]; + $this->lvTabs[] = ['video', ['data' => $data]]; } break; From 2daa7247208a765331a8f2c3a6bc57190169d8c3 Mon Sep 17 00:00:00 2001 From: HelloKitty Date: Wed, 30 Mar 2022 06:18:16 -0500 Subject: [PATCH 013/698] README/Typo (#337) Fix typo in the Special Thanks section. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 67094695..13019966 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,6 @@ A: A search is only conducted against the currently used locale. You may have on ## Special Thanks Said website with the red smiling rocket, for providing this beautifull website! -Please do not reagard this project as blatant rip-off, rather as "We do really liked your presentation, but since time and content progresses, you are sadly no longer supplying the data we need". +Please do not regard this project as blatant rip-off, rather as "We do really liked your presentation, but since time and content progresses, you are sadly no longer supplying the data we need". ![uses badges](http://forthebadge.com/images/badges/uses-badges.svg) From 8425eeb6859d7d81aea6258c8f3c62c4eb078991 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Mon, 28 Mar 2022 17:47:55 +0200 Subject: [PATCH 014/698] Reports * move related functions to separate class * implement out of date comment handling shorthand * implement admin interface to work with reports - listing based on user group - assign to self / unassign from self - close with reason - comment functionality - reward reputation to creator based on resolution --- includes/ajaxHandler/admin.class.php | 31 ++- includes/ajaxHandler/comment.class.php | 43 +-- includes/ajaxHandler/contactus.class.php | 75 ++---- includes/community.class.php | 2 + includes/utilities.php | 293 +++++++++++++++++++-- pages/admin.php | 32 +++ static/js/global.js | 93 +++---- static/js/staff.js | 2 +- template/listviews/commentAdminCol.tpl.php | 50 ++++ template/pages/admin/reports.tpl.php | 53 ++++ 10 files changed, 506 insertions(+), 168 deletions(-) create mode 100644 template/listviews/commentAdminCol.tpl.php create mode 100644 template/pages/admin/reports.tpl.php diff --git a/includes/ajaxHandler/admin.class.php b/includes/ajaxHandler/admin.class.php index d048071a..ed14b572 100644 --- a/includes/ajaxHandler/admin.class.php +++ b/includes/ajaxHandler/admin.class.php @@ -5,7 +5,7 @@ if (!defined('AOWOW_REVISION')) class AjaxAdmin extends AjaxHandler { - protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override', 'guide']; + protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override', 'guide', 'comment']; protected $_get = array( 'action' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'], @@ -89,6 +89,13 @@ class AjaxAdmin extends AjaxHandler $this->handler = 'guideManage'; } + else if ($this->params[0] == 'comment') + { + if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD)) + return; + + $this->handler = 'commentOutOfDate'; + } } // get all => null (optional) @@ -526,6 +533,28 @@ class AjaxAdmin extends AjaxHandler return '-1'; } + protected function commentOutOfDate() : string + { + $ok = false; + switch ($this->_post['status']) + { + case 0: // up to date + if ($ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` & ~?d WHERE `id` = ?d', CC_FLAG_OUTDATED, $this->_post['id'])) + if ($rep = new Report(Report::MODE_COMMENT, Report::CO_OUT_OF_DATE, $this->_post['id'])) + $rep->close(Report::STATUS_CLOSED_WONTFIX); + break; + case 1: // outdated, mark as deleted and clear other flags (sticky + outdated) + if ($ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = ?d, `deleteUserId` = ?d, `deleteDate` = ?d WHERE `id` = ?d', CC_FLAG_DELETED, User::$id, time(), $this->_post['id'])) + if ($rep = new Report(Report::MODE_COMMENT, Report::CO_OUT_OF_DATE, $this->_post['id'])) + $rep->close(Report::STATUS_CLOSED_SOLVED); + break; + default: + trigger_error('AjaxHandler::comentOutOfDate - called with invalid status'); + } + + return $ok ? '1' : '0'; + } + /***************************/ /* additional input filter */ diff --git a/includes/ajaxHandler/comment.class.php b/includes/ajaxHandler/comment.class.php index c635391f..18cc8c34 100644 --- a/includes/ajaxHandler/comment.class.php +++ b/includes/ajaxHandler/comment.class.php @@ -177,7 +177,7 @@ class AjaxComment extends AjaxHandler } // in theory, there is a username passed alongside... lets just use the current user (see user.js) - $ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d, deleteUserId = ?d, deleteDate = UNIX_TIMESTAMP() WHERE id IN (?a){ AND userId = ?d}', + $ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` | ?d, `deleteUserId` = ?d, `deleteDate` = UNIX_TIMESTAMP() WHERE `id` IN (?a){ AND `userId` = ?d}', CC_FLAG_DELETED, User::$id, $this->_post['id'], @@ -187,13 +187,14 @@ class AjaxComment extends AjaxHandler // deflag hasComment if ($ok) { - $coInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~b.flags) & ?d, 1, 0) as hasMore, b.type, b.typeId FROM ?_comments a JOIN ?_comments b ON a.type = b.type AND a.typeId = b.typeId WHERE a.id = ?d', + $coInfo = DB::Aowow()->select('SELECT IF(BIT_OR(~b.`flags`) & ?d, 1, 0) AS hasMore, b.`type`, b.`typeId` FROM ?_comments a JOIN ?_comments b ON a.`type` = b.`type` AND a.`typeId` = b.`typeId` WHERE a.`id` IN (?a) GROUP BY b.`type`, b.`typeId`', CC_FLAG_DELETED, $this->_post['id'] ); - if (!$coInfo['hasMore'] && ($tbl = Type::getClassAttrib($coInfo['type'], 'dataTable'))) - DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']); + foreach ($coInfo as $co) + if (!$co['hasMore'] && ($tbl = Type::getClassAttrib($co['type'], 'dataTable'))) + DB::Aowow()->query('UPDATE ?# SET `cuFlags` = `cuFlags` & ~?d WHERE `id` = ?d', $tbl, CUSTOM_HAS_COMMENT, $co['typeId']); } else trigger_error('AjaxComment::handleCommentDelete - user #'.User::$id.' could not flag comment #'.$this->_post['id'].' as deleted', E_USER_ERROR); @@ -208,7 +209,7 @@ class AjaxComment extends AjaxHandler } // in theory, there is a username passed alongside... lets just use the current user (see user.js) - $ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id IN (?a){ AND userId = deleteUserId AND deleteUserId = ?d}', + $ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` & ~?d WHERE `id` IN (?a){ AND `userId` = `deleteUserId` AND `deleteUserId` = ?d}', CC_FLAG_DELETED, $this->_post['id'], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id @@ -217,9 +218,10 @@ class AjaxComment extends AjaxHandler // reflag hasComment if ($ok) { - $coInfo = DB::Aowow()->selectRow('SELECT type, typeId FROM ?_comments WHERE id = ?d', $this->_post['id']); - if ($tbl = Type::getClassAttrib($coInfo['type'], 'dataTable')) - DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']); + $coInfo = DB::Aowow()->select('SELECT `type`, `typeId` FROM ?_comments WHERE `id` IN (?a) GROUP BY `type`, `typeId`', $this->_post['id']); + foreach ($coInfo as $co) + if ($tbl = Type::getClassAttrib($co['type'], 'dataTable')) + DB::Aowow()->query('UPDATE ?# SET `cuFlags` = `cuFlags` | ?d WHERE `id` = ?d', $tbl, CUSTOM_HAS_COMMENT, $co['typeId']); } else trigger_error('AjaxComment::handleCommentUndelete - user #'.User::$id.' could not unflag comment #'.$this->_post['id'].' as deleted', E_USER_ERROR); @@ -300,19 +302,24 @@ class AjaxComment extends AjaxHandler if (User::isInGroup(U_GROUP_MODERATOR)) // directly mark as outdated { if (!$this->_post['remove']) - $ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | 0x4 WHERE id = ?d', $this->_post['id'][0]); + $ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]); else - $ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~0x4 WHERE id = ?d', $this->_post['id'][0]); + $ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]); } - else if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND `userId` = ?d', 1, 17, $this->_post['id'][0], User::$id)) - return Lang::main('alreadyReport'); - else if (User::$id && !$this->_post['reason'] || mb_strlen($this->_post['reason']) < self::REPLY_LENGTH_MIN) - return Lang::main('textTooShort'); - else if (User::$id) // only report as outdated - $ok = Util::createReport(1, 17, $this->_post['id'][0], '[Outdated Comment] '.$this->_post['reason']); + else // try to report as outdated + { + $report = new Report(Report::MODE_COMMENT, Report::CO_OUT_OF_DATE, $this->_post['id'][0]); + if ($report->create($this->_post['reason'])) + $ok = true; // the script expects the actual characters 'ok' not some json string like "ok" + else + return Lang::main('intError'); - if ($ok) // this one is very special; as in: completely retarded - return 'ok'; // the script expects the actual characters 'ok' not some string like "ok" + if (count($report->getSimilar()) >= 5) // 5 or more reports on the same comment: trigger flag + $ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]); + } + + if ($ok) + return 'ok'; else trigger_error('AjaxComment::handleCommentOutOfDate - failed to update comment in db', E_USER_ERROR); diff --git a/includes/ajaxHandler/contactus.class.php b/includes/ajaxHandler/contactus.class.php index d2a2517e..a15bfc49 100644 --- a/includes/ajaxHandler/contactus.class.php +++ b/includes/ajaxHandler/contactus.class.php @@ -6,15 +6,15 @@ if (!defined('AOWOW_REVISION')) class AjaxContactus extends AjaxHandler { protected $_post = array( - 'mode' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - 'reason' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - 'ua' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'appname' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'page' => ['filter' => FILTER_SANITIZE_URL], - 'desc' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'id' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - 'relatedurl' => ['filter' => FILTER_SANITIZE_URL], - 'email' => ['filter' => FILTER_SANITIZE_EMAIL] + 'mode' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'reason' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'ua' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'appname' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'page' => ['filter' => FILTER_SANITIZE_URL ], + 'desc' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'relatedurl' => ['filter' => FILTER_SANITIZE_URL ], + 'email' => ['filter' => FILTER_SANITIZE_EMAIL ] ); public function __construct(array $params) @@ -35,58 +35,13 @@ class AjaxContactus extends AjaxHandler */ protected function handleContactUs() : string { - $mode = $this->_post['mode']; - $rsn = $this->_post['reason']; - $ua = $this->_post['ua']; - $app = $this->_post['appname']; - $url = $this->_post['page']; - $desc = $this->_post['desc']; - $subj = $this->_post['id']; - - $contexts = array( - [1, 2, 3, 4, 5, 6, 7, 8], - [15, 16, 17, 18, 19, 20], - [30, 31, 32, 33, 34, 35, 36, 37], - [45, 46, 47, 48], - [60, 61], - [45, 46, 47, 48], - [45, 46, 48] - ); - - if ($mode === null || $rsn === null || $ua === null || $app === null || $url === null) - { - trigger_error('AjaxContactus::handleContactUs - malformed contact request received', E_USER_ERROR); - return Lang::main('intError'); - } - - if (!isset($contexts[$mode]) || !in_array($rsn, $contexts[$mode])) - { - trigger_error('AjaxContactus::handleContactUs - report has invalid context (mode:'.$mode.' / reason:'.$rsn.')', E_USER_ERROR); - return Lang::main('intError'); - } - - if (!$desc) - return 3; - - if (mb_strlen($desc) > 500) - return 2; - - if (!User::$id && !User::$ip) - { - trigger_error('AjaxContactus::handleContactUs - could not determine IP for anonymous user', E_USER_ERROR); - return Lang::main('intError'); - } - - // check already reported - $field = User::$id ? 'userId' : 'ip'; - if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND ?# = ?', $mode, $rsn, $subj, $field, User::$id ?: User::$ip)) - return 7; - - if (Util::createReport($mode, $rsn, $subj, $desc, $ua, $app, $url, $this->_post['relatedurl'], $this->_post['email'])) + $report = new Report($this->_post['mode'], $this->_post['reason'], $this->_post['id']); + if ($report->create($this->_post['desc'], $this->_post['ua'], $this->_post['appname'], $this->_post['page'], $this->_post['relatedurl'], $this->_post['email'])) return 0; - - trigger_error('AjaxContactus::handleContactUs - write to db failed', E_USER_ERROR); - return Lang::main('intError'); + else if ($report->errorCode > 0) + return $report->errorCode; + else + return Lang::main('intError'); } } diff --git a/includes/community.class.php b/includes/community.class.php index 522d4b33..a11a75ed 100644 --- a/includes/community.class.php +++ b/includes/community.class.php @@ -96,6 +96,7 @@ class CommunityContent {c.replyTo <> ?d AND} {c.replyTo = ?d AND} {ur.entry IS ?n AND} + {(c.flags & ?d) AND} ((c.flags & ?d) = 0 OR c.userId = ?d OR ?d) GROUP BY c.id @@ -143,6 +144,7 @@ class CommunityContent empty($params['replies']) ? DBSIMPLE_SKIP : 0, // i dont know, how to switch the sign around !empty($params['replies']) ? DBSIMPLE_SKIP : 0, empty($params['unrated']) ? DBSIMPLE_SKIP : null, + empty($params['flags']) ? DBSIMPLE_SKIP : $params['flags'], CC_FLAG_DELETED, User::$id, User::isInGroup(U_GROUP_COMMENTS_MODERATOR), diff --git a/includes/utilities.php b/includes/utilities.php index ebaa856f..4ba5f6f5 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -1574,32 +1574,6 @@ abstract class Util ); } - static function createReport($mode, $reason, $subject, $desc, $userAgent = null, $appName = null, $url = null, $relUrl = null, $email = null) - { - $update = array( - 'userId' => User::$id, - 'createDate' => time(), - 'mode' => $mode, - 'reason' => $reason, - 'subject' => $subject ?: 0, // not set for utility, tools and misc pages - 'ip' => User::$ip, - 'description' => $desc, - 'userAgent' => $userAgent ?: $_SERVER['HTTP_USER_AGENT'], - 'appName' => $appName ?: (get_browser(null, true)['browser'] ?: '') - ); - - if ($url) - $update['url'] = $url; - - if ($relUrl) - $update['relatedurl'] = $relUrl; - - if ($email) - $update['email'] = $email; - - return DB::Aowow()->query('INSERT INTO ?_reports (?#) VALUES (?a)', array_keys($update), array_values($update)); - } - // orientation is 2*M_PI for a full circle, increasing counterclockwise static function O2Deg($o) { @@ -1871,4 +1845,271 @@ abstract class Type } } + +class Report +{ + public const MODE_GENERAL = 0; + public const MODE_COMMENT = 1; + public const MODE_FORUM_POST = 2; + public const MODE_SCREENSHOT = 3; + public const MODE_CHARACTER = 4; + public const MODE_VIDEO = 5; + public const MODE_GUIDE = 6; + + public const GEN_FEEDBACK = 1; + public const GEN_BUG_REPORT = 2; + public const GEN_TYPO_TRANSLATION = 3; + public const GEN_OP_ADVERTISING = 4; + public const GEN_OP_PARTNERSHIP = 5; + public const GEN_PRESS_INQUIRY = 6; + public const GEN_MISCELLANEOUS = 7; + public const GEN_MISINFORMATION = 8; + public const CO_ADVERTISING = 15; + public const CO_INACCURATE = 16; + public const CO_OUT_OF_DATE = 17; + public const CO_SPAM = 18; + public const CO_INAPPROPRIATE = 19; + public const CO_MISCELLANEOUS = 20; + public const FO_ADVERTISING = 30; + public const FO_AVATAR = 31; + public const FO_INACCURATE = 32; + public const FO_OUT_OF_DATE = 33; + public const FO_SPAM = 34; + public const FO_STICKY_REQUEST = 35; + public const FO_INAPPROPRIATE = 36; + public const FO_MISCELLANEOUS = 37; + public const SS_INACCURATE = 45; + public const SS_OUT_OF_DATE = 46; + public const SS_INAPPROPRIATE = 47; + public const SS_MISCELLANEOUS = 48; + public const PR_INACCURATE_DATA = 60; + public const PR_MISCELLANEOUS = 61; + public const VI_INACCURATE = 45; + public const VI_OUT_OF_DATE = 46; + public const VI_INAPPROPRIATE = 47; + public const VI_MISCELLANEOUS = 48; + public const AR_INACCURATE = 45; + public const AR_OUT_OF_DATE = 46; + public const AR_MISCELLANEOUS = 48; + + private /* array */ $context = array( + self::MODE_GENERAL => array( + self::GEN_FEEDBACK => true, + self::GEN_BUG_REPORT => true, + self::GEN_TYPO_TRANSLATION => true, + self::GEN_OP_ADVERTISING => true, + self::GEN_OP_PARTNERSHIP => true, + self::GEN_PRESS_INQUIRY => true, + self::GEN_MISCELLANEOUS => true, + self::GEN_MISINFORMATION => true + ), + self::MODE_COMMENT => array( + self::CO_ADVERTISING => U_GROUP_MODERATOR, + self::CO_INACCURATE => true, + self::CO_OUT_OF_DATE => true, + self::CO_SPAM => U_GROUP_MODERATOR, + self::CO_INAPPROPRIATE => U_GROUP_MODERATOR, + self::CO_MISCELLANEOUS => U_GROUP_MODERATOR + ), + self::MODE_FORUM_POST => array( + self::FO_ADVERTISING => U_GROUP_MODERATOR, + self::FO_AVATAR => true, + self::FO_INACCURATE => true, + self::FO_OUT_OF_DATE => U_GROUP_MODERATOR, + self::FO_SPAM => U_GROUP_MODERATOR, + self::FO_STICKY_REQUEST => U_GROUP_MODERATOR, + self::FO_INAPPROPRIATE => U_GROUP_MODERATOR + ), + self::MODE_SCREENSHOT => array( + self::SS_INACCURATE => true, + self::SS_OUT_OF_DATE => true, + self::SS_INAPPROPRIATE => U_GROUP_MODERATOR, + self::SS_MISCELLANEOUS => U_GROUP_MODERATOR + ), + self::MODE_CHARACTER => array( + self::PR_INACCURATE_DATA => true, + self::PR_MISCELLANEOUS => true + ), + self::MODE_VIDEO => array( + self::VI_INACCURATE => true, + self::VI_OUT_OF_DATE => true, + self::VI_INAPPROPRIATE => U_GROUP_MODERATOR, + self::VI_MISCELLANEOUS => U_GROUP_MODERATOR + ), + self::MODE_GUIDE => array( + self::AR_INACCURATE => true, + self::AR_OUT_OF_DATE => true, + self::AR_MISCELLANEOUS => true + ) + ); + + private const ERR_NONE = 0; // aka: success + private const ERR_INVALID_CAPTCHA = 1; // captcha not in use + private const ERR_DESC_TOO_LONG = 2; + private const ERR_NO_DESC = 3; + private const ERR_ALREADY_REPORTED = 7; + private const ERR_MISCELLANEOUS = -1; + + public const STATUS_OPEN = 0; + public const STATUS_ASSIGNED = 1; + public const STATUS_CLOSED_WONTFIX = 2; + public const STATUS_CLOSED_SOLVED = 3; + + private /* int */ $mode = 0; + private /* int */ $reason = 0; + private /* int */ $subject = 0; + + public /* readonly int */ $errorCode; + + + public function __construct(int $mode, int $reason, int $subject = 0) + { + if ($mode < 0 || $reason <= 0 || !$subject) + { + trigger_error('AjaxContactus::handleContactUs - malformed contact request received', E_USER_ERROR); + $this->errorCode = self::ERR_MISCELLANEOUS; + return; + } + + if (!isset($this->context[$mode][$reason])) + { + trigger_error('AjaxContactus::handleContactUs - report has invalid context (mode:'.$mode.' / reason:'.$reason.')', E_USER_ERROR); + $this->errorCode = self::ERR_MISCELLANEOUS; + return; + } + + if (!User::$id && !User::$ip) + { + trigger_error('AjaxContactus::handleContactUs - could not determine IP for anonymous user', E_USER_ERROR); + $this->errorCode = self::ERR_MISCELLANEOUS; + return; + } + + $this->mode = $mode; + $this->reason = $reason; + $this->subject = $subject; // 0 for utility, tools and misc pages? + } + + private function checkTargetContext() : int + { + // check already reported + $field = User::$id ? 'userId' : 'ip'; + if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND ?# = ?', $this->mode, $this->reason, $this->subject, $field, User::$id ?: User::$ip)) + return self::ERR_ALREADY_REPORTED; + + // check targeted post/postOwner staff status + $ctxCheck = $this->context[$this->mode][$this->reason]; + if (is_int($ctxCheck)) + { + $roles = User::$groups; + if ($this->mode == self::MODE_COMMENT) + $roles = DB::Aowow()->selectCell('SELECT `roles` FROM ?_comments WHERE `id` = ?d', $this->subject); + // else if if ($this->mode == self::MODE_FORUM_POST) + // $roles = DB::Aowow()->selectCell('SELECT `roles` FROM ?_forum_posts WHERE `id` = ?d', $this->subject); + + return $roles & $ctxCheck ? self::ERR_NONE : self::ERR_MISCELLANEOUS; + } + else + return $ctxCheck ? self::ERR_NONE : self::ERR_MISCELLANEOUS; + + // Forum not in use, else: + // check post owner + // User::$id == post.op && !post.sticky; + // check user custom avatar + // g_users[post.user].avatar == 2 && (post.roles & U_GROUP_MODERATOR) == 0 + } + + public function create(string $desc, ?string $userAgent = null, ?string $appName = null, ?string $pageUrl = null, ?string $relUrl = null, ?string $email = null) : bool + { + if ($this->errorCode) + return false; + + if (!$desc) + { + $this->errorCode = self::ERR_NO_DESC; + return false; + } + + if (mb_strlen($desc) > 500) + { + $this->errorCode = self::ERR_DESC_TOO_LONG; + return false; + } + + if($err = $this->checkTargetContext()) + { + $this->errorCode = $err; + return false; + } + + $update = array( + 'userId' => User::$id, + 'createDate' => time(), + 'mode' => $this->mode, + 'reason' => $this->reason, + 'subject' => $this->subject, + 'ip' => User::$ip, + 'description' => $desc, + 'userAgent' => $userAgent ?: $_SERVER['HTTP_USER_AGENT'], + 'appName' => $appName ?: (get_browser(null, true)['browser'] ?: '') + ); + + if ($pageUrl) + $update['url'] = $pageUrl; + + if ($relUrl) + $update['relatedurl'] = $relUrl; + + if ($email) + $update['email'] = $email; + + return DB::Aowow()->query('INSERT INTO ?_reports (?#) VALUES (?a)', array_keys($update), array_values($update)); + } + + public function getSimilar(int ...$status) : array + { + if ($this->errorCode) + return []; + + foreach ($status as &$s) + if ($s < self::STATUS_OPEN || $s > self::STATUS_CLOSED_SOLVED) + unset($s); + + return DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, r.* FROM ?_reports r WHERE {`status` IN (?a) AND }`mode` = ?d AND `reason` = ?d AND `subject` = ?d', + $status ?: DBSIMPLE_SKIP, $this->mode, $this->reason, $this->subject); + } + + public function close(int $closeStatus, bool $inclAssigned = false) : bool + { + if ($closeStatus != self::STATUS_CLOSED_SOLVED && $closeStatus != self::STATUS_CLOSED_WONTFIX) + return false; + + if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD)) + return false; + + $fromStatus = [self::STATUS_OPEN]; + if ($inclAssigned) + $fromStatus[] = self::STATUS_ASSIGNED; + + if ($reports = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `userId` FROM ?_reports WHERE `status` IN (?a) AND `mode` = ?d AND `reason` = ?d AND `subject` = ?d', + $fromStatus, $this->mode, $this->reason, $this->subject)) + { + DB::Aowow()->query('UPDATE ?_reports SET `status` = ?d, `assigned` = 0 WHERE `id` IN (?a)', $closeStatus, array_keys($reports)); + + foreach ($reports as $rId => $uId) + Util::gainSiteReputation($uId, $closeStatus == self::STATUS_CLOSED_SOLVED ? SITEREP_ACTION_GOOD_REPORT : SITEREP_ACTION_BAD_REPORT, ['id' => $rId]); + + return true; + } + + return false; + } + + public function reopen(int $assignedTo = 0) : bool + { + // assignedTo = 0 ? status = STATUS_OPEN : status = STATUS_ASSIGNED, userId = assignedTo + return false; + } +} + ?> diff --git a/pages/admin.php b/pages/admin.php index 70b3b0c3..46e0f782 100644 --- a/pages/admin.php +++ b/pages/admin.php @@ -65,6 +65,22 @@ class AdminPage extends GenericPage array_push($this->path, 1, 25); $this->name = 'Pending Guides'; break; + case 'out-of-date': + $this->reqUGroup = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD; + $this->generator = 'handleOutOfDate'; + $this->tpl = 'list-page-generic'; + + array_push($this->path, 1, 23); + $this->name = 'Out of Date Comments'; + break; + case 'reports': + $this->reqUGroup = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR | U_GROUP_MOD | U_GROUP_LOCALIZER | U_GROUP_SCREENSHOT | U_GROUP_VIDEO; + $this->generator = 'handleReports'; + $this->tpl = 'admin/reports'; + + array_push($this->path, 5); + $this->name = 'Reports'; + break; default: // error out through unset template } @@ -280,6 +296,22 @@ class AdminPage extends GenericPage ), 'guideAdminCol']; } + private function handleOutOfDate() : void + { + $data = CommunityContent::getCommentPreviews(['flags' => CC_FLAG_OUTDATED]); + + $this->lvTabs[] = ['commentpreview', array( + 'data' => $data, + 'extraCols' => '$_' + ), 'commentAdminCol']; + } + + private function handleReports() : void + { + // todo: handle reports listing + // + } + private function configAddRow($r) { $buff = ''; diff --git a/static/js/global.js b/static/js/global.js index d2edbd78..c6d014a4 100644 --- a/static/js/global.js +++ b/static/js/global.js @@ -21213,52 +21213,28 @@ var ContactTool = new function() { [7, true] // Other ], 1: [ // comment - [15, function(post) { - return ((post.roles & U_GROUP_MODERATOR) == 0); - }], // Advertising - [16, true], // Inaccurate - [17, true], // Out of date - [18, function(post) { - return ((post.roles & U_GROUP_MODERATOR) == 0); - }], // Spam - [19, function(post) { - return ((post.roles & U_GROUP_MODERATOR) == 0); - }], // Vulgar/inappropriate - [20, function(post) { - return ((post.roles & U_GROUP_MODERATOR) == 0); - }] // Other + [15, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Advertising + [16, true], // Inaccurate + [17, true], // Out of date + [18, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Spam + [19, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate + [20, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }] // Other ], 2: [ // forum post - [30, function(post) { - return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); - }], // Advertising - [37, function(post) { - return ((post.roles & U_GROUP_MODERATOR) == 0 && g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && g_users[post.user].avatar == 2); - }], // Avatar - [31, true], // Inaccurate - [32, true], // Out of date - [33, function(post) { - return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); - }], // Spam - [34, function(post) { - return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && post.op && !post.sticky); - }], // Sticky request - [35, function(post) { - return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); - }], // Vulgar/inappropriate - [36, function(post) { - return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); - }] // Other + [30, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Advertising + [37, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && (post.roles & U_GROUP_MODERATOR) == 0 && g_users[post.user].avatar == 2); }], // Avatar + [31, true], // Inaccurate + [32, true], // Out of date + [33, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Spam + [34, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && post.op && !post.sticky); }], // Sticky request + [35, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate + [36, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0);}] // Other ], 3: [ // screenshot [45, true], // Inaccurate, [46, true], // Out of date, - [47, function(screen) { - return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); - }], // Vulgar/inappropriate - [48, function(screen) { - return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); - }] // Other + [47, function(screen) { return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate + [48, function(screen) { return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); }] // Other ], 4: [ // character [60, true], // Inaccurate completion data @@ -21267,14 +21243,10 @@ var ContactTool = new function() { 5: [ // video [45, true], // Inaccurate, [46, true], // Out of date, - [47, function(video) { - return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); - }], // Vulgar/inappropriate - [48, function(video) { - return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); - }] // Other + [47, function(video) { return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate + [48, function(video) { return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); }] // Other ], - 6: [ // Guide + 6: [ // guide [45, true], // Inaccurate, [46, true], // Out of date, [48, true] // Other @@ -21323,12 +21295,12 @@ var ContactTool = new function() { var params = [ 'contact=1', - 'mode=' + $WH.urlencode(data.mode), - 'reason=' + $WH.urlencode(data.reason), - 'desc=' + $WH.urlencode(data.description), - 'ua=' + $WH.urlencode(navigator.userAgent), + 'mode=' + $WH.urlencode(data.mode), + 'reason=' + $WH.urlencode(data.reason), + 'desc=' + $WH.urlencode(data.description), + 'ua=' + $WH.urlencode(navigator.userAgent), 'appname=' + $WH.urlencode(navigator.appName), - 'page=' + $WH.urlencode(data.currenturl) + 'page=' + $WH.urlencode(data.currenturl) ]; if (data.mode == 0) { // contact us @@ -21366,30 +21338,27 @@ var ContactTool = new function() { onSuccess: function(xhr, opt) { var resp = xhr.responseText; if (resp == 0) { - if (g_user.name) { + if (g_user.name) alert($WH.sprintf(LANG.ct_dialog_thanks_user, g_user.name)); - } - else { + else alert(LANG.ct_dialog_thanks); - } + Lightbox.hide(); } else { - if (errors[resp]) { + if (errors[resp]) alert(errors[resp]); - } - else { + else alert('Error: ' + resp); - } } }, onFailure: function(xhr, opt) { alert('Failure submitting contact request: ' + xhr.statusText); }, onComplete: function(xhr, opt) { - for (var i = 0; i < form.elements.length; ++i) { + for (var i = 0; i < form.elements.length; ++i) form.elements[i].disabled = false; - } + data.submitting = false; } }); diff --git a/static/js/staff.js b/static/js/staff.js index fafda9c2..d2bbdcc2 100644 --- a/static/js/staff.js +++ b/static/js/staff.js @@ -106,7 +106,7 @@ var mn_staff = [ // [3, 'Localization', null, mn_localization], // [7, 'Statistics', null, mn_statistics, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}], // [4, 'Users', null, mn_users], -// [5, 'View Reports', '?admin=reports', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR | U_GROUP_MOD | U_GROUP_LOCALIZER | U_GROUP_SCREENSHOT | U_GROUP_VIDEO} ], + [5, 'View Reports', '?admin=reports', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR | U_GROUP_MOD | U_GROUP_LOCALIZER | U_GROUP_SCREENSHOT | U_GROUP_VIDEO} ], [, 'Page'], [102, 'Validate', 'http://validator.w3.org/check/referer', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_TESTER}]]; diff --git a/template/listviews/commentAdminCol.tpl.php b/template/listviews/commentAdminCol.tpl.php new file mode 100644 index 00000000..f6b6908a --- /dev/null +++ b/template/listviews/commentAdminCol.tpl.php @@ -0,0 +1,50 @@ +var _ = [ + { + id: 'manage', + name: 'Manage', + type: 'text', + align: 'center', + value: 'subject', + sortable: false, + compute: function(comment, td, tr) { + let wrapper = $WH.ce('div'); + + let send = function (el, id, status) + { + $.ajax({cache: false, url: '?admin=comment', type: 'POST', + error: function() { + alert('Operation failed.'); + }, + success: function(json) { + if (json != 1) + alert('Operation failed.'); + else + $WH.de(el.parentNode); + }, + data: { id: id, status: status } + }) + + return true; + }; + + let a = $WH.ce('a'); + a.style.fontFamily = 'Verdana, sans-serif'; + a.style.marginLeft = '10px'; + a.href = '#'; + + _ = a.cloneNode(); + _.className = 'icon-tick'; + _.onclick = send.bind(this, td, comment.id, 0); + g_addTooltip(_, LANG.lvcomment_uptodate); + $WH.ae(wrapper, _); + + _ = a.cloneNode(); + _.className = 'icon-delete'; + _.onclick = send.bind(this, td, comment.id, 1); + g_addTooltip(_, LANG.delete); + $WH.ae(wrapper, _); + + $WH.ae(td, wrapper); + } + } +]; diff --git a/template/pages/admin/reports.tpl.php b/template/pages/admin/reports.tpl.php new file mode 100644 index 00000000..e0495b3b --- /dev/null +++ b/template/pages/admin/reports.tpl.php @@ -0,0 +1,53 @@ +brick('header'); ?> + + + +
+
+
+ +brick('announcement'); + +$this->brick('pageTemplate'); +?> +
+

name;?>

+ +brick('article'); + + if (isset($this->extraText)): +?> +
+ + +
+extraHTML)): + echo $this->extraHTML; + endif; +?> +

Edit

+
+
Icon
+
+
+
+
Scale
+
+
+
+
+
+
+ +brick('footer'); ?> From 6594d6fa4242a4ff348d1bebbed03dda60a16005 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Tue, 5 Apr 2022 18:28:45 +0200 Subject: [PATCH 015/698] Spells/Tooltips * htmlify \n in spell tooltips & buffs * allow recursion of Util::parseHtmlText() --- includes/types/spell.class.php | 11 +++++++++-- includes/utilities.php | 10 +++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index 09e6c0d2..14b3c7ad 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -1800,6 +1800,13 @@ class SpellList extends BaseType } } + // this should be 0 if all went well + if ($condBrktCnt > 0) + { + trigger_error('SpellList::handleConditions() - string contains unbalanced condition', E_USER_WARNING); + $condParts[3] = $condParts[3] ?? ''; + } + // check if it is know-compatible $know = 0; if (preg_match('/\(?(\!?)[as](\d+)\)?$/i', $condParts[0], $m)) @@ -1889,7 +1896,7 @@ class SpellList extends BaseType // scaling information - spellId:min:max:curr $x .= ''; - return [$x, $btt[1]]; + return [$x, Util::parseHtmlText($btt[1])]; } public function renderTooltip($level = MAX_LEVEL, $interactive = false) @@ -2038,7 +2045,7 @@ class SpellList extends BaseType // scaling information - spellId:min:max:curr $x .= ''; - return [$x, $desc[1]]; + return [$x, Util::parseHtmlText($desc[1])]; } public function getTalentHeadForCurrent() diff --git a/includes/utilities.php b/includes/utilities.php index 4ba5f6f5..a3a2c056 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -671,8 +671,16 @@ abstract class Util } // pageText for Books (Item or GO) and questText - public static function parseHtmlText(string $text, bool $markdown = false) : string + public static function parseHtmlText(/*string|array*/ $text, bool $markdown = false) // : /*string|array*/ { + if (is_array($text)) + { + foreach ($text as &$t) + $t = self::parseHtmlText($t, $markdown); + + return $text; + } + if (stristr($text, '')) // text is basically a html-document with weird linebreak-syntax { $pairs = array( From df3694b5394735a18b53e532323dcb9fa5fdf005 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sun, 8 May 2022 00:22:10 +0200 Subject: [PATCH 016/698] Setup/Mails (#340) * fix borked setup after https://github.com/Sarjuuk/aowow/commit/b3e8f5e50f236a65e3a033273199ce881c397659 * thx @jackpoz for the research --- setup/tools/sqlgen/mailtemplate.func.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/setup/tools/sqlgen/mailtemplate.func.php b/setup/tools/sqlgen/mailtemplate.func.php index 5a8b3272..abf4872e 100644 --- a/setup/tools/sqlgen/mailtemplate.func.php +++ b/setup/tools/sqlgen/mailtemplate.func.php @@ -19,13 +19,20 @@ SqlGen::register(new class extends SetupScript DB::Aowow()->query('TRUNCATE aowow_mails'); // copy data over from dbc - DB::Aowow()->query('INSERT INTO ?_mails SELECT *, 0 FROM dbc_mailtemplate'); + DB::Aowow()->query(' + INSERT INTO ?_mails SELECT + id, 0, + subject_loc0, subject_loc2, subject_loc3, subject_loc4, subject_loc6, subject_loc8, + text_loc0, text_loc2, text_loc3, text_loc4, text_loc6, text_loc8, + 0 + FROM dbc_mailtemplate + '); CLI::write('SqlGen::generate() - merging achievement_reward into aowow_mails'); $acvMail = DB::World()->select(' SELECT - -ar.ID, + -ar.ID, 0, IFNULL(ar.Subject, "") AS s0, IFNULL(arl2.Subject, "") AS s2, IFNULL(arl3.Subject, "") AS s3, IFNULL(arl4.Subject, "") AS s4, IFNULL(arl6.Subject, "") AS s6, IFNULL(arl8.Subject, "") AS s8, IFNULL(ar.Body, "") AS t0, IFNULL(arl2.Body, "") AS t2, IFNULL(arl3.Body, "") AS t3, IFNULL(arl4.Body, "") AS t4, IFNULL(arl6.Body, "") AS t6, IFNULL(arl8.Body, "") AS t8, ItemID From 1bd752a60f0ca1892de4ffa1015df1297c8829ca Mon Sep 17 00:00:00 2001 From: Dima Date: Mon, 30 May 2022 21:27:56 +0700 Subject: [PATCH 017/698] Typo/Spells (#343) * fixed legacy typo in spell power calculation --- includes/types/spell.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index 09e6c0d2..622bfd7f 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -2306,7 +2306,7 @@ class SpellList extends BaseType $originalCastTime = 1500; // Portion to Over Time - $PtOT = ($overTime / 15000) / (($overTime / 15000) + (OriginalCastTime / 3500)); + $PtOT = ($overTime / 15000) / (($overTime / 15000) + ($originalCastTime / 3500)); if ($asDOT) $castingTime = $castingTime * $PtOT; From c0e9159c1e228136042c2aa7268056f2adc839ad Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Tue, 5 Apr 2022 16:13:56 +0200 Subject: [PATCH 018/698] Misc/Fixups * colAddins should be null if not in use * fix index warnings in search + profiler * cast url param 'locale' to int for all uses * fix breadcrumbs for sounds page * fix determining actionOwner for SmartAI --- includes/ajaxHandler/profile.class.php | 4 ++-- includes/kernel.php | 9 ++++++--- includes/smartAI.class.php | 8 ++++++-- includes/utilities.php | 4 ++-- pages/npc.php | 2 +- pages/profile.php | 3 ++- pages/search.php | 2 +- pages/sounds.php | 2 +- template/pages/quest.tpl.php | 3 +-- 9 files changed, 22 insertions(+), 15 deletions(-) diff --git a/includes/ajaxHandler/profile.class.php b/includes/ajaxHandler/profile.class.php index 64e3654a..163d13d6 100644 --- a/includes/ajaxHandler/profile.class.php +++ b/includes/ajaxHandler/profile.class.php @@ -360,7 +360,7 @@ class AjaxProfile extends AjaxHandler $cuProfile['sourceId'] = $_; } - if ($cuProfile['sourceId']) + if (!empty($cuProfile['sourceId'])) $cuProfile['sourceName'] = DB::Aowow()->selectCell('SELECT name FROM ?_profiler_profiles WHERE id = ?d', $cuProfile['sourceId']); $charId = -1; @@ -420,7 +420,7 @@ class AjaxProfile extends AjaxHandler $itemData[2] = 0; // item sockets are fubar - $nSockets = $items->json[$itemData[1]]['nsockets']; + $nSockets = $items->json[$itemData[1]]['nsockets'] ?? 0; $nSockets += in_array($slot, [SLOT_WAIST, SLOT_WRISTS, SLOT_HANDS]) ? 1 : 0; for ($i = 5; $i < 9; $i++) if ($itemData[$i] > 0 && (!$items->getEntry($itemData[$i]) || $i >= (5 + $nSockets))) diff --git a/includes/kernel.php b/includes/kernel.php index 4a999553..a4814662 100644 --- a/includes/kernel.php +++ b/includes/kernel.php @@ -255,9 +255,12 @@ if (!CLI) // all strings attached.. if (!empty($AoWoWconf['aowow'])) { - if (isset($_GET['locale']) && (int)$_GET['locale'] <= MAX_LOCALES && (int)$_GET['locale'] >= 0) - if (CFG_LOCALES & (1 << $_GET['locale'])) - User::useLocale($_GET['locale']); + if (isset($_GET['locale'])) + { + $loc = intVal($_GET['locale']); + if ($loc <= MAX_LOCALES && $loc >= 0 && (CFG_LOCALES & (1 << $loc))) + User::useLocale($loc); + } Lang::load(User::$localeString); } diff --git a/includes/smartAI.class.php b/includes/smartAI.class.php index 07b648c3..45ceeef2 100644 --- a/includes/smartAI.class.php +++ b/includes/smartAI.class.php @@ -164,7 +164,11 @@ class SmartAI } if ($q) - $result = DB::Aowow()->selectCol(sprintf('SELECT `type` AS ARRAY_KEY, `typeId` FROM ?_spawns WHERE (%s)', implode(') OR (', $q))); + { + $owner = DB::Aowow()->select(sprintf('SELECT `type` AS "0", `typeId` AS "1" FROM ?_spawns WHERE (%s)', implode(') OR (', $q))); + foreach ($owner as [$ty, $id]) + $result[$ty][] = $id; + } } foreach ($smartS as [$st, $eog]) @@ -258,7 +262,7 @@ class SmartAI return self::getOwnerAction($srcType, $entry, $lookup); } - private static function getOwnerAction(int $sourceType, int $entry, array $lookup, ?array $moreInfo = []) : array + private static function getOwnerAction(int $sourceType, int $entry, array $lookup, ?array &$moreInfo = []) : array { if ($entry < 0) // please not individual entities :( return []; diff --git a/includes/utilities.php b/includes/utilities.php index a3a2c056..60d0cc99 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -1577,8 +1577,8 @@ abstract class Util } return array( - round($mainHand['gearscore'] * $mh), - round($offHand['gearscore'] * $oh) + round(($mainHand['gearscore'] ?? 0) * $mh), + round(($offHand['gearscore'] ?? 0) * $oh) ); } diff --git a/pages/npc.php b/pages/npc.php index a791b153..178272be 100644 --- a/pages/npc.php +++ b/pages/npc.php @@ -621,7 +621,7 @@ class NpcPage extends GenericPage $soldItems = new ItemList(array(['id', $sells])); if (!$soldItems->error) { - $colAddIn = ''; + $colAddIn = null; $extraCols = ["\$Listview.funcBox.createSimpleCol('stack', 'stack', '10%', 'stack')", '$Listview.extraCols.cost']; if ($soldItems->hasSetFields(['condition'])) $extraCols[] = '$Listview.extraCols.condition'; diff --git a/pages/profile.php b/pages/profile.php index d3decda8..e264bb92 100644 --- a/pages/profile.php +++ b/pages/profile.php @@ -38,6 +38,7 @@ class ProfilePage extends GenericPage private $isCustom = false; private $profile = null; + private $subject = null; private $rnItr = 0; private $powerTpl = '$WowheadPower.registerProfile(%s, %d, %s);'; @@ -108,7 +109,7 @@ class ProfilePage extends GenericPage $this->notFound(); } // 2) not yet synced but exists on realm (and not a gm character) - else if (!$this->rnItr && ($char = DB::Characters($this->realmId)->selectRow('SELECT c.guid AS realmGUID, c.name, c.race, c.class, c.level, c.gender, g.guildid AS guildGUID, IFNULL(g.name, "") AS guildName, IFNULL(gm.rank, 0) AS guildRank FROM characters c LEFT JOIN guild_member gm ON gm.guid = c.guid LEFT JOIN guild g ON g.guildid = gm.guildid WHERE c.name = ? AND level <= ?d AND (extra_flags & ?d) = 0', Util::ucFirst($this->subjectName), MAX_LEVEL, Profiler::CHAR_GMFLAGS))) + else if (!$this->rnItr && ($char = DB::Characters($this->realmId)->selectRow('SELECT c.guid AS realmGUID, c.name, c.race, c.class, c.level, c.gender, c.at_login, g.guildid AS guildGUID, IFNULL(g.name, "") AS guildName, IFNULL(gm.rank, 0) AS guildRank FROM characters c LEFT JOIN guild_member gm ON gm.guid = c.guid LEFT JOIN guild g ON g.guildid = gm.guildid WHERE c.name = ? AND level <= ?d AND (extra_flags & ?d) = 0', Util::ucFirst($this->subjectName), MAX_LEVEL, Profiler::CHAR_GMFLAGS))) { $char['realm'] = $this->realmId; $char['cuFlags'] = PROFILER_CU_NEEDS_RESYNC; diff --git a/pages/search.php b/pages/search.php index 97243867..8cc86e8e 100644 --- a/pages/search.php +++ b/pages/search.php @@ -640,7 +640,7 @@ class SearchPage extends GenericPage { $multiClass = 0; for ($i = 1; $i <= 10; $i++) - if ($d['reqclass'] & (1 << ($i - 1))) + if (isset($d['reqclass']) && ($d['reqclass'] & (1 << ($i - 1)))) $multiClass++; if ($multiClass > 1) diff --git a/pages/sounds.php b/pages/sounds.php index ea7e382f..28948e48 100644 --- a/pages/sounds.php +++ b/pages/sounds.php @@ -81,7 +81,7 @@ class SoundsPage extends GenericPage { $form = $this->filterObj->getForm(); if (isset($form['ty']) && count($form['ty']) == 1) - $this->path[] = $form['ty']; + $this->path[] = $form['ty'][0]; } } diff --git a/template/pages/quest.tpl.php b/template/pages/quest.tpl.php index 3bb9a83e..3389c82b 100644 --- a/template/pages/quest.tpl.php +++ b/template/pages/quest.tpl.php @@ -132,9 +132,8 @@ if ($this->offerReward && ($this->requestItems || $this->objectives)): rewards): - $offset = 0; - echo '

'.Lang::main('rewards')."

\n"; if (!empty($r['choice'])): From 6de6853cfeeaef2a27899a4a891e96c1b6cd94a8 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 10 Jun 2022 14:00:35 +0200 Subject: [PATCH 019/698] Core/PHP * bump version requirements to v8.0 --- README.md | 2 +- includes/shared.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 13019966..8c3cd7b3 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 ≥ 7.4 — 8.0 including extensions: ++ Webserver running PHP ≥ 8.0 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/shared.php b/includes/shared.php index 48b2adbf..80a6859f 100644 --- a/includes/shared.php +++ b/includes/shared.php @@ -10,8 +10,8 @@ foreach ($reqExt as $r) if (!extension_loaded($r)) $error .= 'Required Extension '.$r." was not found. Please check if it should exist, using \"php -m\"\n\n"; -if (version_compare(PHP_VERSION, '7.4.0') < 0) - $error .= 'PHP Version 7.4 or higher required! Your version is '.PHP_VERSION.".\nCore functions are unavailable!\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 ($error) { From e493acca0dd80a1d87cfd6001cae854d8af8dd50 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 10 Jun 2022 14:40:30 +0200 Subject: [PATCH 020/698] Item/XML * fix output for currency, quest and key subclasses --- pages/item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/item.php b/pages/item.php index 379d178d..ac53190b 100644 --- a/pages/item.php +++ b/pages/item.php @@ -1057,7 +1057,7 @@ class ItemPage extends genericPage $xml->addChild('class')->addCData(is_array($x) ? $x[0] : $x)->addAttribute('id', $this->subject->getField('class')); // subclass $x = $this->subject->getField('class') == 2 ? Lang::spell('weaponSubClass') : Lang::item('cat', $this->subject->getField('class'), 1); - $xml->addChild('subclass')->addCData(is_array($x) ? (is_array($x[$this->subject->getField('subClass')]) ? $x[$this->subject->getField('subClass')][0] : $x[$this->subject->getField('subClass')]) : null)->addAttribute('id', $this->subject->getField('subClass')); + $xml->addChild('subclass')->addCData(is_array($x) ? (is_array($x[$this->subject->getField('subClass')]) ? $x[$this->subject->getField('subClass')][0] : $x[$this->subject->getField('subClass')]) : Lang::item('cat', $this->subject->getField('class')))->addAttribute('id', $this->subject->getField('subClass')); // icon + displayId $xml->addChild('icon', $this->subject->getField('iconString', true, true))->addAttribute('displayId', $this->subject->getField('displayId')); // inventorySlot From 7e5659f49fb37651fcc537791940bb0dcba361fe Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 10 Jun 2022 15:15:28 +0200 Subject: [PATCH 021/698] NPC/Waypoints * improve display for NPCs traversing zones and/or floors (e.g.: npc 844) --- includes/basetype.class.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/basetype.class.php b/includes/basetype.class.php index 4bb50195..3ad4dd6b 100644 --- a/includes/basetype.class.php +++ b/includes/basetype.class.php @@ -607,14 +607,14 @@ trait spawnHelper ); // connective line - if ($i > 0) + if ($i > 0 && $wPoints[$i - 1]['areaId'] == $p['areaId']) $opts['lines'] = [[$wPoints[$i - 1]['posX'], $wPoints[$i - 1]['posY']]]; - $data[$s['areaId']][$s['floor']]['coords'][] = [$p['posX'], $p['posY'], $opts]; - if (empty($wpSum[$s['areaId']][$s['floor']])) - $wpSum[$s['areaId']][$s['floor']] = 1; + $data[$p['areaId']][$p['floor']]['coords'][] = [$p['posX'], $p['posY'], $opts]; + if (empty($wpSum[$p['areaId']][$p['floor']])) + $wpSum[$p['areaId']][$p['floor']] = 1; else - $wpSum[$s['areaId']][$s['floor']]++; + $wpSum[$p['areaId']][$p['floor']]++; } $wpIdx++; } From 117ab617b62ce43d37f31bc2fed3585573457e69 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 10 Jun 2022 15:58:09 +0200 Subject: [PATCH 022/698] SAI/Teleport (#346) * fixed resolving teleport target for NPCs --- includes/smartAI.class.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/includes/smartAI.class.php b/includes/smartAI.class.php index 45ceeef2..53ac07f0 100644 --- a/includes/smartAI.class.php +++ b/includes/smartAI.class.php @@ -1271,7 +1271,15 @@ class SmartAI $a['param'][6] = $this->aiTemplate($a['param'][0]); break; case SAI_ACTION_TELEPORT: // 62 -> invoker [resolved coords already stored in areatrigger entry] - $a['param'][6] = $this->miscData['teleportA']; + if (isset($this->miscData['teleportA'])) + $a['param'][6] = $this->miscData['teleportA']; + else if ($pos = Game::worldPosToZonePos($a['param'][0], $this->itr['target']['pos'][0], $this->itr['target']['pos'][1])) + $a['param'][6] = $pos['areaId']; + else if ($areaId = DB::Aowow()->selectCell('SELECT id FROM ?_zones WHERE mapId = ?d LIMIT 1', $a['param'][0])) + $a['param'][6] = $areaId; + else + trigger_error('SmartAI::action - could not resolve teleport target: map:'.$a['param'][0].' x:'.$this->itr['target']['pos'][0].' y:'.$this->itr['target']['pos'][1]); + $this->jsGlobals[Type::ZONE][] = $a['param'][6]; break; case SAI_ACTION_SET_ORIENTATION: // 66 -> any target From 47da18b717723806cea170843883598e934d7569 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 10 Jun 2022 16:10:33 +0200 Subject: [PATCH 023/698] Profiler/Caching * redirect to search for subjects without cache, instead of hanging on an empty profile * todo: fix properly --- includes/types/profile.class.php | 2 +- pages/profile.php | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/includes/types/profile.class.php b/includes/types/profile.class.php index aa98f29a..0fd5a2ae 100644 --- a/includes/types/profile.class.php +++ b/includes/types/profile.class.php @@ -340,7 +340,7 @@ class ProfileListFilter extends Filter // table key differs between remote and local :< $k = $this->useLocalList ? 'p' : 'c'; - // name [str] - the table is case sensitive. Since i down't want to destroy indizes, lets alter the search terms + // name [str] - the table is case sensitive. Since i don't want to destroy indizes, lets alter the search terms if (!empty($_v['na'])) { $lower = $this->modularizeString([$k.'.name'], Util::lower($_v['na']), !empty($_v['ex']) && $_v['ex'] == 'on', true); diff --git a/pages/profile.php b/pages/profile.php index e264bb92..fd216101 100644 --- a/pages/profile.php +++ b/pages/profile.php @@ -230,7 +230,7 @@ class ProfilePage extends GenericPage private function handleIncompleteData($params, $guid) { - if ($this->mode == CACHE_TYPE_TOOLTIP) // enable tooltip display with basic data we just added + if ($this->mode == CACHE_TYPE_TOOLTIP) // enable tooltip display with basic data we just added { $this->subject = new LocalProfileList(array(['id', $this->subjectGUID]), ['sv' => $params[1]]); if ($this->subject->error) @@ -238,15 +238,18 @@ class ProfilePage extends GenericPage $this->profile = $params; } - else // display empty page and queue status + else // display empty page and queue status { $this->mode = CACHE_TYPE_NONE; // queue full fetch - $newId = Profiler::scheduleResync(Type::PROFILE, $this->realmId, $guid); - - $this->doResync = ['profile', $newId]; - $this->initialSync(); + if ($newId = Profiler::scheduleResync(Type::PROFILE, $this->realmId, $guid)) + { + $this->doResync = ['profile', $newId]; + $this->initialSync(); + } + else // todo: base info should have been created in __construct .. why are we here..? + header('Location: ?profiles='.$params[0].'.'.$params[1].'&filter=na='.Util::ucFirst($this->subjectName).';ex=on'); } } } From df1ba841c5a70e889bd7b689d495471f465606f7 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 10 Jun 2022 16:58:18 +0200 Subject: [PATCH 024/698] Item/Tooltip * display hidden/cosmetic spells for staff --- includes/types/item.class.php | 39 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/includes/types/item.class.php b/includes/types/item.class.php index 139c11e8..552a1a65 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -970,28 +970,31 @@ class ItemList extends BaseType if ($itemSpellsAndTrigger) { - $cooldown = ''; - $itemSpells = new SpellList(array(['s.id', array_keys($itemSpellsAndTrigger)])); - foreach ($itemSpells->iterate() as $__) - if ($parsed = $itemSpells->parseText('description', $_reqLvl > 1 ? $_reqLvl : MAX_LEVEL, false, $causesScaling)[0]) + foreach ($itemSpells->iterate() as $sId => $__) + { + $parsed = $itemSpells->parseText('description', $_reqLvl > 1 ? $_reqLvl : MAX_LEVEL, false, $causesScaling)[0]; + if (!$parsed && User::isInGroup(U_GROUP_EMPLOYEE)) + $parsed = '<'.$itemSpells->getField('name', true, true).'>'; + else if (!$parsed) + continue; + + if ($interactive) { - if ($interactive) - { - $link = '%s'; - $parsed = preg_replace_callback('/([^;]*)( .*?<\/small>)([^&]*)/i', function($m) use($link) { - $m[1] = $m[1] ? sprintf($link, $m[1]) : ''; - $m[3] = $m[3] ? sprintf($link, $m[3]) : ''; - return $m[1].$m[2].$m[3]; - }, $parsed, -1, $nMatches - ); + $link = '%s'; + $parsed = preg_replace_callback('/([^;]*)( .*?<\/small>)([^&]*)/i', function($m) use($link) { + $m[1] = $m[1] ? sprintf($link, $m[1]) : ''; + $m[3] = $m[3] ? sprintf($link, $m[3]) : ''; + return $m[1].$m[2].$m[3]; + }, $parsed, -1, $nMatches + ); - if (!$nMatches) - $parsed = sprintf($link, $parsed); - } - - $green[] = Lang::item('trigger', $itemSpellsAndTrigger[$itemSpells->id][0]).$parsed.$itemSpellsAndTrigger[$itemSpells->id][1]; + if (!$nMatches) + $parsed = sprintf($link, $parsed); } + + $green[] = Lang::item('trigger', $itemSpellsAndTrigger[$itemSpells->id][0]).$parsed.$itemSpellsAndTrigger[$itemSpells->id][1]; + } } } From 2b15c13e88316407e2ebc3be19c71d0b274bee46 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Tue, 26 Apr 2022 13:39:07 +0200 Subject: [PATCH 025/698] User/Guides * fixed copy/paste fail --- static/js/global.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/static/js/global.js b/static/js/global.js index c6d014a4..bd544c2c 100644 --- a/static/js/global.js +++ b/static/js/global.js @@ -641,8 +641,11 @@ var PageTemplate = new function() { var submenu = []; + if (!g_user.guides || !g_user.guides.length) + return; + // Sort by name - g_user.profiles.sort(function(a, b) + g_user.guides.sort(function(a, b) { return $WH.strcmp(a.title, b.title); }); From f05fe60030694f27cbb80ba10124eb50a7b1e011 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sun, 21 Aug 2022 20:28:56 +0200 Subject: [PATCH 026/698] Spells/Tooltips * fix level slider for spells with buffs but without tooltips --- includes/types/spell.class.php | 65 +++++++++++++++++++++------------ static/js/basic.js | 7 ++++ template/bricks/tooltip.tpl.php | 29 ++++++++------- 3 files changed, 65 insertions(+), 36 deletions(-) diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index eae3ca6b..86412fc5 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -51,6 +51,8 @@ class SpellList extends BaseType private $tools = []; private $interactive = false; private $charLevel = MAX_LEVEL; + private $scaling = []; + private $parsedText = []; protected $queryBase = 'SELECT s.*, s.id AS ARRAY_KEY FROM ?_spell s'; protected $queryOpts = array( @@ -61,13 +63,19 @@ class SpellList extends BaseType 'src' => ['j' => ['?_source src ON type = 6 AND typeId = s.id', true], 's' => ', src1, src2, src3, src4, src5, src6, src7, src8, src9, src10, src11, src12, src13, src14, src15, src16, src17, src18, src19, src20, src21, src22, src23, src24'] ); - public function __construct($conditions = []) + public function __construct($conditions = [], $miscData = []) { parent::__construct($conditions); if ($this->error) return; + if (isset($miscData['interactive'])) + $this->interactive = $miscData['interactive']; + + if (isset($miscData['charLevel'])) + $this->charLevel = $miscData['charLevel']; + // post processing $foo = DB::World()->selectCol('SELECT perfectItemType FROM skill_perfect_item_template WHERE spellId IN (?a)', $this->getFoundIDs()); foreach ($this->iterate() as &$_curTpl) @@ -129,6 +137,8 @@ class SpellList extends BaseType if (!$_curTpl['iconString']) $_curTpl['iconString'] = 'inv_misc_questionmark'; + + $this->scaling[$this->id] = false; } if ($foo) @@ -1066,7 +1076,7 @@ class SpellList extends BaseType // description-, buff-parsing component // returns [min, max, minFulltext, maxFulltext, ratingId] - private function resolveVariableString($varParts, &$usesScalingRating) + private function resolveVariableString($varParts) { $signs = ['+', '-', '/', '*', '%', '^']; @@ -1187,7 +1197,7 @@ class SpellList extends BaseType $rType = 0; if ($aura == 189) if ($rType = Game::itemModByRatingMask($mv)) - $usesScalingRating = true; + $this->scaling[$this->id] = true; // Aura end if ($rType) @@ -1274,7 +1284,7 @@ class SpellList extends BaseType $rType = 0; if ($aura == 189) if ($rType = Game::itemModByRatingMask($mv)) - $usesScalingRating = true; + $this->scaling[$this->id] = true; // Aura end if ($rType) @@ -1342,7 +1352,7 @@ class SpellList extends BaseType } // description-, buff-parsing component - private function resolveFormulaString($formula, $precision = 0, &$scaling) + private function resolveFormulaString($formula, $precision = 0) { $fSuffix = '%s'; $fRating = 0; @@ -1381,7 +1391,7 @@ class SpellList extends BaseType ++$formCurPos; // for some odd reason the precision decimal survives if we dont increment further.. } - [$formOutStr, $fSuffix, $fRating] = $this->resolveFormulaString($formOutStr, $formPrecision, $scaling); + [$formOutStr, $fSuffix, $fRating] = $this->resolveFormulaString($formOutStr, $formPrecision); $formula = substr_replace($formula, $formOutStr, $formStartPos, ($formCurPos - $formStartPos)); } @@ -1415,7 +1425,7 @@ class SpellList extends BaseType $pos += $len; // we are resolving a formula -> omit ranges - $var = $this->resolveVariableString($varParts, $scaling); + $var = $this->resolveVariableString($varParts); // time within formula -> rebase to seconds and omit timeUnit if (strtolower($varParts['var']) == 'd') @@ -1447,7 +1457,7 @@ class SpellList extends BaseType // should probably used only once to create ?_spell. come to think of it, it yields the same results every time.. it absolutely has to! // although it seems to be pretty fast, even on those pesky test-spells with extra complex tooltips (Ron Test Spell X)) - public function parseText($type = 'description', $level = MAX_LEVEL, $interactive = false, &$scaling = false) + public function parseText($type = 'description', $level = MAX_LEVEL, $interactive = false) { // oooo..kaaayy.. parsing text in 6 or 7 easy steps // we don't use the internal iterator here. This func has to be called for the individual template. @@ -1533,6 +1543,10 @@ class SpellList extends BaseType $this->interactive = $interactive; $this->charLevel = $level; + // step -1: already handled? + if (isset($this->parsedText[$this->id][$type][$this->charLevel][(int)$this->interactive])) + return $this->parsedText[$this->id][$type][$this->charLevel][(int)$this->interactive]; + // step 0: get text $data = $this->getField($type, true); if (empty($data) || $data == "[]") // empty tooltip shouldn't be displayed anyway @@ -1582,13 +1596,13 @@ class SpellList extends BaseType */ $relSpells = []; - $data = $this->handleConditions($data, $scaling, $relSpells, true); + $data = $this->handleConditions($data, $relSpells, true); // step 3: unpack formulas ${ .. }.X - $data = $this->handleFormulas($data, $scaling, true); + $data = $this->handleFormulas($data, true); // step 4: find and eliminate regular variables - $data = $this->handleVariables($data, $scaling, true); + $data = $this->handleVariables($data, true); // step 5: variable-dependant variable-text // special case $lONE:ELSE[:ELSE2]; or $|ONE:ELSE[:ELSE2]; @@ -1636,10 +1650,13 @@ class SpellList extends BaseType // line endings $data = strtr($data, ["\r" => '', "\n" => '
']); + // cache result + $this->parsedText[$this->id][$type][$this->charLevel][(int)$this->interactive] = [$data, $relSpells]; + return [$data, $relSpells]; } - private function handleFormulas($data, &$scaling, $topLevel = false) + private function handleFormulas($data, $topLevel = false) { // they are stacked recursively but should be balanced .. hf while (($formStartPos = strpos($data, '${')) !== false) @@ -1678,7 +1695,7 @@ class SpellList extends BaseType $formPrecision = $data[$formCurPos + 1]; $formCurPos += 2; } - [$formOutVal, $formOutStr, $ratingId] = $this->resolveFormulaString($formOutStr, $formPrecision ?: ($topLevel ? 0 : 10), $scaling); + [$formOutVal, $formOutStr, $ratingId] = $this->resolveFormulaString($formOutStr, $formPrecision ?: ($topLevel ? 0 : 10)); if ($ratingId && Util::checkNumeric($formOutVal) && $this->interactive) $resolved = sprintf($formOutStr, $ratingId, abs($formOutVal), sprintf(Util::$setRatingLevelString, $this->charLevel, $ratingId, abs($formOutVal), Util::setRatingLevel($this->charLevel, $ratingId, abs($formOutVal)))); @@ -1693,7 +1710,7 @@ class SpellList extends BaseType return $data; } - private function handleVariables($data, &$scaling, $topLevel = false) + private function handleVariables($data, $topLevel = false) { $pos = 0; // continue strpos-search from this offset $str = ''; @@ -1716,7 +1733,7 @@ class SpellList extends BaseType $pos += $len; - $var = $this->resolveVariableString($varParts, $scaling); + $var = $this->resolveVariableString($varParts); $resolved = is_numeric($var[0]) ? abs($var[0]) : $var[0]; if (isset($var[2])) { @@ -1743,7 +1760,7 @@ class SpellList extends BaseType return $str; } - private function handleConditions($data, &$scaling, &$relSpells, $topLevel = false) + private function handleConditions($data, &$relSpells, $topLevel = false) { while (($condStartPos = strpos($data, '$?')) !== false) { @@ -1830,17 +1847,17 @@ class SpellList extends BaseType // recursive conditions if (strstr($condParts[$targetPart], '$?')) - $condParts[$targetPart] = $this->handleConditions($condParts[$targetPart], $scaling, $relSpells); + $condParts[$targetPart] = $this->handleConditions($condParts[$targetPart], $relSpells); if ($know && $topLevel) { foreach ([1, 3] as $pos) { if (strstr($condParts[$pos], '${')) - $condParts[$pos] = $this->handleFormulas($condParts[$pos], $scaling); + $condParts[$pos] = $this->handleFormulas($condParts[$pos]); if (strstr($condParts[$pos], '$')) - $condParts[$pos] = $this->handleVariables($condParts[$pos], $scaling); + $condParts[$pos] = $this->handleVariables($condParts[$pos]); } // false condition first @@ -1868,6 +1885,7 @@ class SpellList extends BaseType return ['', []]; $this->interactive = $interactive; + $this->charLevel = $level; $x = ''; @@ -1884,7 +1902,7 @@ class SpellList extends BaseType $x .= '
'; // parse Buff-Text - $btt = $this->parseText('buff', $level, $this->interactive, $scaling); + $btt = $this->parseText('buff'); $x .= $btt[0].'
'; // duration @@ -1894,7 +1912,7 @@ class SpellList extends BaseType $x .= '
'; // scaling information - spellId:min:max:curr - $x .= ''; + $x .= ''; return [$x, Util::parseHtmlText($btt[1])]; } @@ -1905,11 +1923,12 @@ class SpellList extends BaseType return ['', []]; $this->interactive = $interactive; + $this->charLevel = $level; // fetch needed texts $name = $this->getField('name', true); $rank = $this->getField('rank', true); - $desc = $this->parseText('description', $level, $this->interactive, $scaling); + $desc = $this->parseText('description'); $tools = $this->getToolsForCurrent(); $cool = $this->createCooldownForCurrent(); $cast = $this->createCastTimeForCurrent(); @@ -2043,7 +2062,7 @@ class SpellList extends BaseType $x .= '
'.implode('
', $xTmp).'
'; // scaling information - spellId:min:max:curr - $x .= ''; + $x .= ''; return [$x, Util::parseHtmlText($desc[1])]; } diff --git a/static/js/basic.js b/static/js/basic.js index ea14ae11..5820fec1 100644 --- a/static/js/basic.js +++ b/static/js/basic.js @@ -1852,6 +1852,13 @@ $WH.Tooltip = { Slider.setSize(tooltip.slider, m - 6); tooltip.className += ' tooltip-slider'; } + // btt empty, try to find tt + else if (tt = $WH.ge(tooltip.id.substr(1))) { // aowow - added for spells with buff, but w/o tooltip + if (tt.slider) { + Slider.setSize(tt.slider, tt.offsetWidth - 6); + tooltip.className += ' tooltip-slider'; + } + } if (!noShrink && tooltip.offsetHeight > document.body.clientHeight) { table.className = 'shrink'; diff --git a/template/bricks/tooltip.tpl.php b/template/bricks/tooltip.tpl.php index a58fe520..d09dbb1a 100644 --- a/template/bricks/tooltip.tpl.php +++ b/template/bricks/tooltip.tpl.php @@ -1,16 +1,16 @@ -
-
+
+
-
-
+
+
jsGlobals[6][2][$this->typeId]['buff']); // not set with items +$hasBuff = !empty($this->jsGlobals[Type::SPELL][2][$this->typeId]['buff']); // not set with items if ($hasBuff): ?>

-
+
From ca26955ac2b822bf5c179f384d60743a7b0b7454 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Fri, 10 Mar 2023 17:43:39 +0100 Subject: [PATCH 027/698] Setup/SQL * change sql batching to account for non continuous indizes in world tables --- setup/tools/sqlgen/creature.func.php | 17 ++++++----------- setup/tools/sqlgen/items.func.php | 17 ++++++----------- setup/tools/sqlgen/objects.func.php | 21 ++++++++------------- setup/tools/sqlgen/quests.func.php | 21 ++++++++------------- 4 files changed, 28 insertions(+), 48 deletions(-) diff --git a/setup/tools/sqlgen/creature.func.php b/setup/tools/sqlgen/creature.func.php index ac216555..ab94aea9 100644 --- a/setup/tools/sqlgen/creature.func.php +++ b/setup/tools/sqlgen/creature.func.php @@ -120,15 +120,14 @@ SqlGen::register(new class extends SetupScript creature_template_resistance ctr5 ON ct.entry = ctr5.CreatureID AND ctr5.School = 5 LEFT JOIN creature_template_resistance ctr6 ON ct.entry = ctr6.CreatureID AND ctr6.School = 6 - WHERE - ct.entry > ?d { - AND ct.entry IN (?a) + WHERE + ct.entry IN (?a) } ORDER BY ct.entry ASC LIMIT - ?d'; + ?d, ?d'; $dummyQuery = ' UPDATE @@ -157,14 +156,10 @@ SqlGen::register(new class extends SetupScript c.iconString = cdi.iconString, c.humanoid = IF(cdie.id IS NULL, 0, 1)'; - $lastMax = 0; - while ($npcs = DB::World()->select($baseQuery, NPC_CU_INSTANCE_BOSS, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + $i = 0; + while ($npcs = DB::World()->select($baseQuery, NPC_CU_INSTANCE_BOSS, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize * $i, SqlGen::$sqlBatchSize)) { - $newMax = max(array_column($npcs, 'entry')); - - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); - - $lastMax = $newMax; + CLI::write(' * batch #' . ++$i . ' (' . count($npcs) . ')'); foreach ($npcs as $npc) DB::Aowow()->query('REPLACE INTO ?_creature VALUES (?a)', array_values($npc)); diff --git a/setup/tools/sqlgen/items.func.php b/setup/tools/sqlgen/items.func.php index ba98c1ad..aa1444a2 100644 --- a/setup/tools/sqlgen/items.func.php +++ b/setup/tools/sqlgen/items.func.php @@ -131,24 +131,19 @@ SqlGen::register(new class extends SetupScript spell_group sg ON sg.spell_id = it.spellid_1 AND it.class = 0 AND it.subclass = 2 AND sg.id IN (1, 2) LEFT JOIN game_event ge ON ge.holiday = it.HolidayId AND it.HolidayId > 0 - WHERE - it.entry > ?d { - AND it.entry IN (?a) + WHERE + it.entry IN (?a) } ORDER BY it.entry ASC LIMIT - ?d'; + ?d, ?d'; - $lastMax = 0; - while ($items = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + $i = 0; + while ($items = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize * $i, SqlGen::$sqlBatchSize)) { - $newMax = max(array_column($items, 'entry')); - - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); - - $lastMax = $newMax; + CLI::write(' * batch #' . ++$i . ' (' . count($items) . ')'); foreach ($items as $item) DB::Aowow()->query('REPLACE INTO ?_items VALUES (?a)', array_values($item)); diff --git a/setup/tools/sqlgen/objects.func.php b/setup/tools/sqlgen/objects.func.php index fd17074a..fe99ea4f 100644 --- a/setup/tools/sqlgen/objects.func.php +++ b/setup/tools/sqlgen/objects.func.php @@ -76,17 +76,16 @@ SqlGen::register(new class extends SetupScript gameobject_template_locale gtl8 ON go.entry = gtl8.entry AND gtl8.`locale` = "ruRU" LEFT JOIN gameobject_questitem gqi ON gqi.GameObjectEntry = go.entry - WHERE - go.entry > ?d { - AND go.entry IN (?a) + WHERE + go.entry IN (?a) } GROUP BY go.entry ORDER BY go.entry ASC LIMIT - ?d'; + ?d, ?d'; $updateQuery = ' UPDATE @@ -104,17 +103,13 @@ SqlGen::register(new class extends SetupScript o.id IN (?a) }'; - $lastMax = 0; - while ($objects = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + $i = 0; + while ($objects = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize * $i, SqlGen::$sqlBatchSize)) { - $newMax = max(array_column($objects, 'entry')); + CLI::write(' * batch #' . ++$i . ' (' . count($objects) . ')'); - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); - - $lastMax = $newMax; - - foreach ($objects as $o) - DB::Aowow()->query('REPLACE INTO ?_objects VALUES (?a)', array_values($o)); + foreach ($objects as $object) + DB::Aowow()->query('REPLACE INTO ?_objects VALUES (?a)', array_values($object)); } // apply typeCat and reqSkill depending on locks diff --git a/setup/tools/sqlgen/quests.func.php b/setup/tools/sqlgen/quests.func.php index da6103d1..a3602004 100644 --- a/setup/tools/sqlgen/quests.func.php +++ b/setup/tools/sqlgen/quests.func.php @@ -129,15 +129,14 @@ SqlGen::register(new class extends SetupScript game_event_seasonal_questrelation gesqr ON gesqr.questId = q.ID LEFT JOIN disables d ON d.entry = q.ID AND d.sourceType = 1 - WHERE - q.id > ?d { - AND q.id IN (?a) + WHERE + q.ID IN (?a) } ORDER BY q.ID ASC LIMIT - ?d'; + ?d, ?d'; $xpQuery = ' UPDATE @@ -171,17 +170,13 @@ SqlGen::register(new class extends SetupScript }'; - $lastMax = 0; - while ($quests = DB::World()->select($baseQuery, $lastMax, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize)) + $i = 0; + while ($quests = DB::World()->select($baseQuery, $ids ?: DBSIMPLE_SKIP, SqlGen::$sqlBatchSize * $i, SqlGen::$sqlBatchSize)) { - $newMax = max(array_column($quests, 'ID')); + CLI::write(' * batch #' . ++$i . ' (' . count($quests) . ')'); - CLI::write(' * sets '.($lastMax + 1).' - '.$newMax); - - $lastMax = $newMax; - - foreach ($quests as $q) - DB::Aowow()->query('REPLACE INTO ?_quests VALUES (?a)', array_values($q)); + foreach ($quests as $quest) + DB::Aowow()->query('REPLACE INTO ?_quests VALUES (?a)', array_values($quest)); } /* From ffa4cf5b29d9d544f80c5c9023928fb320ce49d3 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Thu, 9 Mar 2023 17:13:34 +0100 Subject: [PATCH 028/698] Misc/Fixes * resolve more spellEffects/Auras * fixed item filter with multiple upgrade items * localized unknown spellAura/Effects text * remove unreferenced error code from image setup --- includes/smartAI.class.php | 6 ++-- includes/types/item.class.php | 4 +-- includes/types/spell.class.php | 4 +-- localization/lang.class.php | 9 ----- localization/locale_dede.php | 6 ++-- localization/locale_enus.php | 8 ++--- localization/locale_eses.php | 6 ++-- localization/locale_frfr.php | 6 ++-- localization/locale_ruru.php | 6 ++-- localization/locale_zhcn.php | 6 ++-- pages/spell.php | 46 ++++++++++++++----------- setup/tools/filegen/complexImg.func.php | 3 -- setup/tools/filegen/simpleImg.func.php | 3 -- 13 files changed, 51 insertions(+), 62 deletions(-) diff --git a/includes/smartAI.class.php b/includes/smartAI.class.php index 53ac07f0..0df29d0e 100644 --- a/includes/smartAI.class.php +++ b/includes/smartAI.class.php @@ -165,9 +165,9 @@ class SmartAI if ($q) { - $owner = DB::Aowow()->select(sprintf('SELECT `type` AS "0", `typeId` AS "1" FROM ?_spawns WHERE (%s)', implode(') OR (', $q))); - foreach ($owner as [$ty, $id]) - $result[$ty][] = $id; + $owner = DB::Aowow()->select(sprintf('SELECT `type`, `typeId` FROM ?_spawns WHERE (%s)', implode(') OR (', $q))); + foreach ($owner as $o) + $result[$o['type']][] = $o['typeId']; } } diff --git a/includes/types/item.class.php b/includes/types/item.class.php index 552a1a65..96d07d4a 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -1995,7 +1995,7 @@ class ItemListFilter extends Filter 'cr' => [FILTER_V_RANGE, [1, 177], true ], // criteria ids 'crs' => [FILTER_V_LIST, [FILTER_ENUM_NONE, FILTER_ENUM_ANY, [0, 99999]], true ], // criteria operators 'crv' => [FILTER_V_REGEX, '/[\p{C};:%\\\\]/ui', true ], // criteria values - only printable chars, no delimiters - 'upg' => [FILTER_V_RANGE, [1, 999999], true ], // upgrade item ids + 'upg' => [FILTER_V_REGEX, '/[^\d:]/ui', false], // upgrade item ids 'gb' => [FILTER_V_LIST, [0, 1, 2, 3], false], // search result grouping 'na' => [FILTER_V_REGEX, '/[\p{C};%\\\\]/ui', false], // name - only printable chars, no delimiter 'ma' => [FILTER_V_EQUAL, 1, false], // match any / all filter @@ -2103,7 +2103,7 @@ class ItemListFilter extends Filter // upgrade for [form only] if (isset($_v['upg'])) { - $_ = DB::Aowow()->selectCol('SELECT id as ARRAY_KEY, slot FROM ?_items WHERE class IN (2, 3, 4) AND id IN (?a)', (array)$_v['upg']); + $_ = DB::Aowow()->selectCol('SELECT id as ARRAY_KEY, slot FROM ?_items WHERE class IN (2, 3, 4) AND id IN (?a)', explode(':', $_v['upg'])); if ($_ === null) { unset($_v['upg']); diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index 86412fc5..0b258c14 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -1092,10 +1092,10 @@ class SpellList extends BaseType $effIdx = 1; // cache at least some lookups.. should be moved to single spellList :/ - if ($lookup && !isset($this->refSpells[$lookup])) + if ($lookup && $lookup != $this->id && !isset($this->refSpells[$lookup])) $this->refSpells[$lookup] = new SpellList(array(['s.id', $lookup])); - $srcSpell = $lookup ? $this->refSpells[$lookup] : $this; + $srcSpell = $lookup && $lookup != $this->id ? $this->refSpells[$lookup] : $this; if ($srcSpell->error) return $result; diff --git a/localization/lang.class.php b/localization/lang.class.php index ffe38855..b8076ea0 100644 --- a/localization/lang.class.php +++ b/localization/lang.class.php @@ -96,15 +96,6 @@ class Lang $var = $var[$arg]; } - // meh :x - if ($var === null && $prop == 'spell' && count($args) == 1) - { - if ($args[0] == 'effects') - $var = self::$$prop['unkEffect']; - else if ($args[0] == 'auras') - $var = self::$$prop['unkAura']; - } - return self::vspf($var, $vspfArgs); } diff --git a/localization/locale_dede.php b/localization/locale_dede.php index d857e1b2..f835fe5f 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -378,7 +378,7 @@ $lang = array( 'si' => [1 => "Allianz", -1 => "Nur für Allianz", 2 => "Horde", -2 => "Nur für Horde", 3 => "Beide"], 'resistances' => [null, 'Heiligwiderstand', 'Feuerwiderstand', 'Naturwiderstand', 'Frostwiderstand', 'Schattenwiderstand', 'Arkanwiderstand'], 'sc' => ["Körperlich", "Heilig", "Feuer", "Natur", "Frost", "Schatten", "Arkan"], - 'dt' => [null, "Magie", "Fluch", "Krankheit", "Gift", "Verstohlenheit", "Unsichtbarkeit", null, null, "Wut"], + 'dt' => [null, "Magie", "Fluch", "Krankheit", "Gift", "Verstohlenheit", "Unsichtbarkeit", "Magie, Fluch, Krankheit, Gift", "Zauber (NSC)", "Wut"], 'cl' => [null, "Krieger", "Paladin", "Jäger", "Schurke", "Priester", "Todesritter", "Schamane", "Magier", "Hexenmeister", null, "Druide"], 'ra' => [-2 => "Horde", -1 => "Allianz", null, "Mensch", "Orc", "Zwerg", "Nachtelf", "Untoter", "Tauren", "Gnom", "Troll", null, "Blutelf", "Draenei"], 'rep' => ["Hasserfüllt", "Feindselig", "Unfreundlich", "Neutral", "Freundlich", "Wohlwollend", "Respektvoll", "Ehrfürchtig"], @@ -1625,7 +1625,7 @@ $lang = array( 89 => "Verwendbar, während Ihr verängstigt seid", 65 => "Braucht alle Ressourcen auf" ), - 'unkEffect' => 'Unknown Effect', + 'unkEffect' => 'Unknown Effect (%1$d)', 'effects' => array( /*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units', /*6+ */ 'Apply Aura', 'Environmental Damage', 'Drain Power', 'Drain Health', 'Heal', 'Bind', @@ -1656,7 +1656,7 @@ $lang = array( /*156+ */ 'Add Socket to Item', 'Create Tradeskill Item', 'Milling', 'Rename Pet', null, 'Change Talent Spec. Count', /*162-167*/ 'Activate Talent Spec.', null, 'Remove Aura', null, null, 'Update Player Phase' ), - 'unkAura' => 'Unknown Aura', + 'unkAura' => 'Unknown Aura (%1$d)', 'auras' => array( /*0- */ 'None', 'Bind Sight', 'Possess', 'Periodic Damage - Flat', 'Dummy', /*5+ */ 'Confuse', 'Charm', 'Fear', 'Periodic Heal', 'Mod Attack Speed', diff --git a/localization/locale_enus.php b/localization/locale_enus.php index f3d908c4..14b4dd0e 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -377,10 +377,10 @@ $lang = array( 'gl' => [null, "Major", "Minor"], // MAJOR_GLYPH, MINOR_GLYPH 'si' => [1 => "Alliance", -1 => "Alliance only", 2 => "Horde", -2 => "Horde only", 3 => "Both"], 'resistances' => [null, 'Holy Resistance', 'Fire Resistance', 'Nature Resistance', 'Frost Resistance', 'Shadow Resistance', 'Arcane Resistance'], // RESISTANCE?_NAME - 'dt' => [null, "Magic", "Curse", "Disease", "Poison", "Stealth", "Invisibility", null, null, "Enrage"], // SpellDispalType.dbc + 'dt' => [null, "Magic", "Curse", "Disease", "Poison", "Stealth", "Invisibility", "Magic, Curse, Disease, Poison", "Spell (NPC)", "Enrage"], // SpellDispalType.dbc 'sc' => ["Physical", "Holy", "Fire", "Nature", "Frost", "Shadow", "Arcane"], // STRING_SCHOOL_* 'cl' => [null, "Warrior", "Paladin", "Hunter", "Rogue", "Priest", "Death Knight", "Shaman", "Mage", "Warlock", null, "Druid"], // ChrClasses.dbc - 'ra' => [-2 => "Horde", -1 => "Alliance", null, "Human", "Orc", "Dwarf", "Night Elf", "Undead", "Tauren", "Gnome", "Troll", null, "Blood Elf", "Draenei"], // ChrRaces.dbc + 'ra' => [-2 => "Horde", -1 => "Alliance", null, "Human", "Orc", "Dwarf", "Night Elf", "Undead", "Tauren", "Gnome", "Troll", null, "Blood Elf", "Draenei"], // ChrRaces.dbc 'rep' => ["Hated", "Hostile", "Unfriendly", "Neutral", "Friendly", "Honored", "Revered", "Exalted"], // FACTION_STANDING_LABEL* 'st' => array( // SpellShapeshiftForm.dbc // with minor deviations on 27, 28 "Default", "Cat Form", "Tree of Life", "Travel Form", "Aquatic Form", "Bear From", @@ -1625,7 +1625,7 @@ $lang = array( 89 => "Usable while feared", 65 => "Uses all power" ), - 'unkEffect' => 'Unknown Effect', + 'unkEffect' => 'Unknown Effect (%1$d)', 'effects' => array( /*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units', /*6+ */ 'Apply Aura', 'Environmental Damage', 'Drain Power', 'Drain Health', 'Heal', 'Bind', @@ -1656,7 +1656,7 @@ $lang = array( /*156+ */ 'Add Socket to Item', 'Create Tradeskill Item', 'Milling', 'Rename Pet', null, 'Change Talent Spec. Count', /*162-167*/ 'Activate Talent Spec.', null, 'Remove Aura', null, null, 'Update Player Phase' ), - 'unkAura' => 'Unknown Aura', + 'unkAura' => 'Unknown Aura (%1$d)', 'auras' => array( /*0- */ 'None', 'Bind Sight', 'Possess', 'Periodic Damage - Flat', 'Dummy', /*5+ */ 'Confuse', 'Charm', 'Fear', 'Periodic Heal', 'Mod Attack Speed', diff --git a/localization/locale_eses.php b/localization/locale_eses.php index b80f7902..ac234fea 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -378,7 +378,7 @@ $lang = array( 'si' => [1 => "Alianza", -1 => "Alianza solamente", 2 => "Horda", -2 => "Horda solamente", 3 => "Ambos"], 'resistances' => [null, 'Resistencia a lo Sagrado', 'v', 'Resistencia a la Naturaleza', 'Resistencia a la Escarcha', 'Resistencia a las Sombras', 'Resistencia a lo Arcano'], 'sc' => ["Física", "Sagrado", "Fuego", "Naturaleza", "Escarcha", "Sombras", "Arcano"], - 'dt' => [null, "Magia", "Maldición", "Enfermedad", "Veneno", "Sigilo", "Invisibilidad", null, null, "Enfurecer"], + 'dt' => [null, "Magia", "Maldición", "Enfermedad", "Veneno", "Sigilo", "Invisibilidad", "Magia, Maldición, Enfermedad, Veneno", "Hechizo (PNJ)", "Enfurecer"], 'cl' => [null, "Guerrero", "Paladín", "Cazador", "Pícaro", "Sacerdote", "Caballero de la Muerte", "Chamán", "Mago", "Brujo", null, "Druida"], 'ra' => [-2 => "Horda", -1 => "Alianza", null, "Humano", "Orco", "Enano", "Elfo de la noche", "No-muerto", "Tauren", "Gnomo", "Trol ", null, "Blood Elf", "Elfo de sangre"], 'rep' => ["Odiado", "Hostil", "Adverso", "Neutral", "Amistoso", "Honorable", "Reverenciado", "Exaltado"], @@ -1625,7 +1625,7 @@ $lang = array( 89 => "Utilizable mientras se esta aterrorizado", 65 => "Utiliza todo el poder" ), - 'unkEffect' => 'Unknown Effect', + 'unkEffect' => 'Unknown Effect (%1$d)', 'effects' => array( /*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units', /*6+ */ 'Apply Aura', 'Environmental Damage', 'Drain Power', 'Drain Health', 'Heal', 'Bind', @@ -1656,7 +1656,7 @@ $lang = array( /*156+ */ 'Add Socket to Item', 'Create Tradeskill Item', 'Milling', 'Rename Pet', null, 'Change Talent Spec. Count', /*162-167*/ 'Activate Talent Spec.', null, 'Remove Aura', null, null, 'Update Player Phase' ), - 'unkAura' => 'Unknown Aura', + 'unkAura' => 'Unknown Aura (%1$d)', 'auras' => array( /*0- */ 'None', 'Bind Sight', 'Possess', 'Periodic Damage - Flat', 'Dummy', /*5+ */ 'Confuse', 'Charm', 'Fear', 'Periodic Heal', 'Mod Attack Speed', diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index 2ed96a91..5b2b8497 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -377,7 +377,7 @@ $lang = array( 'gl' => [null, "Majeur", "Mineur"], 'si' => [1 => "Alliance", -1 => "Alliance seulement", 2 => "Horde", -2 => "Horde seulement", 3 => "Les deux"], 'resistances' => [null, 'Résistance au Sacré', 'Résistance au Feu', 'Résistance à la Nature', 'Résistance au Givre', 'Résistance à l\'Ombre', 'Résistance aux Arcanes'], - 'dt' => [null, "Magie", "Malédiction", "Maladie", "Poison", "Camouflage", "Invisibilité", null, null, "Enrager"], + 'dt' => [null, "Magie", "Malédiction", "Maladie", "Poison", "Camouflage", "Invisibilité", "Magie, Malédiction, Maladie, Poison", "Sort (PNJ)", "Enrager"], 'sc' => ["Physique", "Sacré", "Feu", "Nature", "Givre", "Ombre", "Arcane"], 'cl' => [null, "Guerrier", "Paladin", "Chasseur", "Voleur", "Prêtre", "DeathChevalier de la mort", "Chaman", "Mage", "Démoniste", null, "Druide"], 'ra' => [-2 => "Horde", -1 => "Alliance", null, "Humain", "Orc", "Nain", "Elfe de la nuit", "Mort-vivant", "Tauren", "Gnome", "Troll", null, "Elfe de sang", "Draeneï"], @@ -1625,7 +1625,7 @@ $lang = array( 89 => "Utilisable sous l'effet de peur", 65 => "Utilise toute la puissance" ), - 'unkEffect' => 'Unknown Effect', + 'unkEffect' => 'Unknown Effect (%1$d)', 'effects' => array( /*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units', /*6+ */ 'Apply Aura', 'Environmental Damage', 'Drain Power', 'Drain Health', 'Heal', 'Bind', @@ -1656,7 +1656,7 @@ $lang = array( /*156+ */ 'Add Socket to Item', 'Create Tradeskill Item', 'Milling', 'Rename Pet', null, 'Change Talent Spec. Count', /*162-167*/ 'Activate Talent Spec.', null, 'Remove Aura', null, null, 'Update Player Phase' ), - 'unkAura' => 'Unknown Aura', + 'unkAura' => 'Unknown Aura (%1$d)', 'auras' => array( /*0- */ 'None', 'Bind Sight', 'Possess', 'Periodic Damage - Flat', 'Dummy', /*5+ */ 'Confuse', 'Charm', 'Fear', 'Periodic Heal', 'Mod Attack Speed', diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index a929147e..52650f4d 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -377,7 +377,7 @@ $lang = array( 'gl' => array(null, "Большой", "Малый"), 'si' => array(1 => "Альянс", -1 => "Альянс только", 2 => "Орда", -2 => "Орда только", null, 3 => "Обе"), 'resistances' => array(null, "Сопротивление светлой магии", "Сопротивление огню", "Сопротивление силам природы", "Сопротивление магии льда", "Сопротивление темной магии", "Сопротивление тайной магии"), - 'dt' => array(null, "Магия", "Проклятие", "Болезнь", "Яд", "Незаметность", "Невидимость", null, null, "Исступление"), + 'dt' => array(null, "Магия", "Проклятие", "Болезнь", "Яд", "Незаметность", "Невидимость", "Магия, Проклятие, Болезнь, Яд", "Заклинание (НИП)", "Исступление"), 'sc' => array("Физический урон", "Свет", "Огонь", "природа", "Лед", "Тьма", "Тайная магия"), 'cl' => array(null, "Воин", "Паладин", "Охотник", "Разбойник", "Жрец", "Рыцарь смерти", "Шаман", "Маг", "Чернокнижник", null, "Друид"), 'ra' => array(-2 => "Орда", -1 => "Альянс", null, "Человек", "Орк", "Дворф", "Ночной эльф", "Нежить", "Таурен", "Гном", "Тролль", null, "Эльф крови", "Дреней"), @@ -1625,7 +1625,7 @@ $lang = array( 89 => "usablefearedМожет быть использовано, пока наложен Страх", 65 => "Использует ресурс полностью" ), - 'unkEffect' => 'Unknown Effect', + 'unkEffect' => 'Unknown Effect (%1$d)', 'effects' => array( /*0-5 */ 'None', 'Instakill', 'School Damage', 'Dummy', 'Portal Teleport', 'Teleport Units', /*6+ */ 'Apply Aura', 'Environmental Damage', 'Drain Power', 'Drain Health', 'Heal', 'Bind', @@ -1656,7 +1656,7 @@ $lang = array( /*156+ */ 'Add Socket to Item', 'Create Tradeskill Item', 'Milling', 'Rename Pet', null, 'Change Talent Spec. Count', /*162-167*/ 'Activate Talent Spec.', null, 'Remove Aura', null, null, 'Update Player Phase' ), - 'unkAura' => 'Unknown Aura', + 'unkAura' => 'Unknown Aura (%1$d)', 'auras' => array( /*0- */ 'None', 'Bind Sight', 'Possess', 'Periodic Damage - Flat', 'Dummy', /*5+ */ 'Confuse', 'Charm', 'Fear', 'Periodic Heal', 'Mod Attack Speed', diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php index fc3b6d8a..48df95a1 100644 --- a/localization/locale_zhcn.php +++ b/localization/locale_zhcn.php @@ -376,7 +376,7 @@ $lang = array( 'gl' => [null, "大", "小"], 'si' => [1 => "联盟", -1 => "仅限联盟", 2 => "部落", -2 => "仅限部落", 3 => "双方"], 'resistances' => [null, '神圣抗性', '火焰抗性', '自然抗性', '冰霜抗性', '暗影抗性', '奥术抗性'], - 'dt' => [null, "魔法", "诅咒", "疾病", "中毒", "潜行", "隐形", null, null, "激怒"], + 'dt' => [null, "魔法", "诅咒", "疾病", "中毒", "潜行", "隐形", "魔法, 诅咒, 疾病, 中毒", "法术 (NPC)", "激怒"], 'sc' => ["物理", "神圣", "火焰", "自然", "冰霜", "暗影", "奥术"], 'cl' => [null, "战士", "圣骑士", "猎人", "潜行者", "牧师", "死亡骑士", "萨满祭司", "法师", "术士", null, "德鲁伊"], 'ra' => [-2 => "部落", -1 => "联盟", null, "人类", "兽人", "矮人", "暗夜精灵", "亡灵", "牛头人", "侏儒", "巨魔", null, "血精灵", "德莱尼"], @@ -1624,7 +1624,7 @@ $lang = array( 89 => "恐惧时可用", 65 => "消耗所有力量" ), - 'unkEffect' => '未知效果', + 'unkEffect' => '未知效果 (%1$d)', 'effects' => array( /*0-5 */ '无', '杀死', '类型伤害', 'Dummy', '传送门', '传送单位', /*6+ */ '应用光环', '环境伤害', 'Drain Power', 'Drain Health', 'Heal', 'Bind', @@ -1655,7 +1655,7 @@ $lang = array( /*156+ */ 'Add Socket to Item', 'Create Tradeskill Item', 'Milling', 'Rename Pet', null, 'Change Talent Spec. Count', /*162-167*/ 'Activate Talent Spec.', null, 'Remove Aura', null, null, 'Update Player Phase' ), - 'unkAura' => '未知光环', + 'unkAura' => '未知光环 (%1$d)', 'auras' => array( /*0- */ '无', 'Bind Sight', 'Possess', 'Periodic Damage - Flat', 'Dummy', /*5+ */ 'Confuse', 'Charm', 'Fear', 'Periodic Heal', 'Mod Attack Speed', diff --git a/pages/spell.php b/pages/spell.php index 195668cb..9c393f9e 100644 --- a/pages/spell.php +++ b/pages/spell.php @@ -1555,6 +1555,14 @@ class SpellPage extends GenericPage $itemIdx = $this->subject->canCreateItem(); $perfItem = DB::World()->selectRow('SELECT * FROM skill_perfect_item_template WHERE spellId = ?d', $this->typeId); + $fmtStaffTT = function($text, $tip) + { + if (User::isInGroup(U_GROUP_EMPLOYEE)) + return sprintf(Util::$dfnString, $tip, $text); + else + return $text; + }; + // Iterate through all effects: for ($i = 1; $i < 4; $i++) { @@ -1633,9 +1641,9 @@ class SpellPage extends GenericPage // Effect Name if ($_ = Lang::spell('effects', $effId)) - $foo['name'] = (User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'EffectId: '.$effId, $_) : Lang::spell('effects', $effId)).Lang::main('colon'); + $foo['name'] = $fmtStaffTT($_, 'Effect'.Lang::main('colon').$effId).Lang::main('colon'); else - $foo['name'] = 'Unknow Effect (#'.$effId.')'; + $foo['name'] = Lang::spell('unkEffect', [$effId]); if ($this->subject->getField('effect'.$i.'RadiusMax') > 0) $foo['radius'] = $this->subject->getField('effect'.$i.'RadiusMax'); @@ -1669,28 +1677,25 @@ class SpellPage extends GenericPage case 30: // Energize case 62: // Power Burn case 137: // Energize Pct - $_ = Lang::spell('powerTypes', $effMV); - if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) - $_ = sprintf(Util::$dfnString, 'MiscValue'.Lang::main('colon').$effMV, $_); - else if (!$_) - $_ = $effMV; + if ($_ = Lang::spell('powerTypes', $effMV)) + $foo['name'] .= $fmtStaffTT('('.$_.')', 'MiscValue'.Lang::main('colon').$effMV); + else + $foo['name'] .= '('.$effMV.')'; if ($effMV == POWER_RAGE || $effMV == POWER_RUNIC_POWER) $foo['value'] = ($effDS && $effDS != 1 ? (($effBP + 1) / 10).Lang::game('valueDelim') : null).(($effBP + $effDS) / 10); - $foo['name'] .= ' ('.$_.')'; break; case 11: // Bind - if (!$effMV && User::isInGroup(U_GROUP_EMPLOYEE)) - $foo['name'] .= sprintf(Util::$dfnString, 'MiscValue'.Lang::main('colon').$effMV, '(current zone)'); - else if (!$effMV) - $foo['name'] .= '('.Lang::spell('currentArea').')'; + if ($effMV <= 0) + $foo['name'] .= $fmtStaffTT('('.Lang::spell('currentArea').')', 'MiscValue'.Lang::main('colon').$effMV); else if ($_ = ZoneList::getName($effMV)) $foo['name'] .= '('.$_.')'; else - $foo['name'] .= Util::ucFirst(Lang::game('zone')).' #'.$effMV;; + $foo['name'] .= Util::ucFirst(Lang::game('zone')).' #'.$effMV; break; - case 16: // QuestComplete + case 16: // Complete Quest + case 139: // Abandon Quest if ($_ = QuestList::getName($effMV)) $foo['name'] .= '('.$_.')'; else @@ -1711,13 +1716,11 @@ class SpellPage extends GenericPage $foo['name'] .= $_; break; case 33: // Open Lock - $_ = $effMV ? Lang::spell('lockType', $effMV) : $effMV; - if ($_ && User::isInGroup(U_GROUP_EMPLOYEE)) - $_ = sprintf(Util::$dfnString, 'MiscValue'.Lang::main('colon').$effMV, $_); - else if (!$_) - $_ = $effMV; + if ($effMV && ($_ = Lang::spell('lockType', $effMV))) + $foo['name'] .= ' ('.$fmtStaffTT($_, 'MiscValue'.Lang::main('colon').$effMV).')'; + else + $foo['name'] .= ' ('.$effMV.')'; - $foo['name'] .= ' ('.$_.')'; break; case 53: // Enchant Item Perm case 54: // Enchant Item Temp @@ -1990,6 +1993,7 @@ class SpellPage extends GenericPage case 39: // School Immunity case 40: // Damage Immunity case 50: // Mod Critical Healing Amount + case 52: // Mod Physical Crit Chance case 57: // Mod Spell Crit Chance case 69: // School Absorb case 71: // Mod Spell Crit Chance School @@ -2166,7 +2170,7 @@ class SpellPage extends GenericPage } else if ($effAura > 0) - $foo['name'] .= 'Unknown Aura ('.$effAura.')'; + $foo['name'] .= Lang::spell('unkAura', [$effAura]); break; } diff --git a/setup/tools/filegen/complexImg.func.php b/setup/tools/filegen/complexImg.func.php index 056ebb65..1e5af596 100644 --- a/setup/tools/filegen/complexImg.func.php +++ b/setup/tools/filegen/complexImg.func.php @@ -268,9 +268,6 @@ if (!CLI) if (count(array_filter(array_column($paths, 2))) != count($paths)) { CLI::write('one or more required directories are missing:', CLI::LOG_ERROR); - foreach ($missing as $m) - CLI::write(' - '.$m, CLI::LOG_ERROR); - return; } else diff --git a/setup/tools/filegen/simpleImg.func.php b/setup/tools/filegen/simpleImg.func.php index 595ac452..dac42edf 100644 --- a/setup/tools/filegen/simpleImg.func.php +++ b/setup/tools/filegen/simpleImg.func.php @@ -245,9 +245,6 @@ if (!CLI) if (count(array_filter(array_column($paths, 5))) != count($paths)) { CLI::write('one or more required directories are missing:', CLI::LOG_ERROR); - foreach ($missing as $m) - CLI::write(' - '.$m, CLI::LOG_ERROR); - return; } else From 0c47f262eac26573b935c274f71de9f47fad8413 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Thu, 16 Mar 2023 17:59:09 +0100 Subject: [PATCH 029/698] Userdata * replace input filter FILTER_UNSAFE_RAW (+ STRIP flags) with regex checks to preserve \n and utf8 chars --- includes/ajaxHandler/account.class.php | 2 +- includes/ajaxHandler/admin.class.php | 18 +++++------ includes/ajaxHandler/comment.class.php | 20 ++++++------ includes/ajaxHandler/contactus.class.php | 12 +++---- includes/ajaxHandler/cookie.class.php | 2 +- includes/ajaxHandler/data.class.php | 8 ++--- includes/ajaxHandler/edit.class.php | 4 +-- includes/ajaxHandler/getdescription.class.php | 2 +- includes/ajaxHandler/profile.class.php | 32 ++++++++++++++----- includes/utilities.php | 10 ++++-- pages/account.php | 6 ++-- pages/guide.php | 10 +++--- pages/screenshot.php | 2 +- 13 files changed, 75 insertions(+), 53 deletions(-) diff --git a/includes/ajaxHandler/account.class.php b/includes/ajaxHandler/account.class.php index e851f553..5a7c354e 100644 --- a/includes/ajaxHandler/account.class.php +++ b/includes/ajaxHandler/account.class.php @@ -171,7 +171,7 @@ class AjaxAccount extends AjaxHandler { $var = trim(urldecode($val)); - return filter_var($var, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_AOWOW); + return filter_var($var, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_LOW); } } diff --git a/includes/ajaxHandler/admin.class.php b/includes/ajaxHandler/admin.class.php index ed14b572..c89eebec 100644 --- a/includes/ajaxHandler/admin.class.php +++ b/includes/ajaxHandler/admin.class.php @@ -7,25 +7,25 @@ class AjaxAdmin extends AjaxHandler { protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override', 'guide', 'comment']; protected $_get = array( - 'action' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'action' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine' ], 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'], 'key' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkKey' ], - 'all' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], + 'all' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet' ], 'type' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], 'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], 'user' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkUser' ], - 'val' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], + 'val' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob' ], 'guid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], 'area' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], 'floor' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ] ); protected $_post = array( - 'alt' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], - 'scale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkScale'], - '__icon' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkKey' ], - 'status' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], - 'msg' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW] + 'alt' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob'], + 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], + 'scale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkScale' ], + '__icon' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxAdmin::checkKey' ], + 'status' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt' ], + 'msg' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob'] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/comment.class.php b/includes/ajaxHandler/comment.class.php index 18cc8c34..728a8e4f 100644 --- a/includes/ajaxHandler/comment.class.php +++ b/includes/ajaxHandler/comment.class.php @@ -12,22 +12,22 @@ class AjaxComment extends AjaxHandler protected $_post = array( 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'], - 'body' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], - 'commentbody' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext' ], - 'response' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], - 'reason' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], - 'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - 'commentId' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - 'replyId' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - 'sticky' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - // 'username' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ] + 'body' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob' ], + 'commentbody' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob' ], + 'response' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob' ], + 'reason' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob' ], + 'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + 'commentId' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + 'replyId' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + 'sticky' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + // 'username' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine' ] ); protected $_get = array( 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], 'type' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], 'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], - 'rating' => ['filter' => FILTER_SANITIZE_NUMBER_INT] + 'rating' => ['filter' => FILTER_SANITIZE_NUMBER_INT ] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/contactus.class.php b/includes/ajaxHandler/contactus.class.php index a15bfc49..072fc182 100644 --- a/includes/ajaxHandler/contactus.class.php +++ b/includes/ajaxHandler/contactus.class.php @@ -6,13 +6,13 @@ if (!defined('AOWOW_REVISION')) class AjaxContactus extends AjaxHandler { protected $_post = array( - 'mode' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], - 'reason' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], - 'ua' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'appname' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + 'mode' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + 'reason' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], + 'ua' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], + 'appname' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], 'page' => ['filter' => FILTER_SANITIZE_URL ], - 'desc' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'], + 'desc' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob'], + 'id' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], 'relatedurl' => ['filter' => FILTER_SANITIZE_URL ], 'email' => ['filter' => FILTER_SANITIZE_EMAIL ] ); diff --git a/includes/ajaxHandler/cookie.class.php b/includes/ajaxHandler/cookie.class.php index ccc36166..066b742c 100644 --- a/includes/ajaxHandler/cookie.class.php +++ b/includes/ajaxHandler/cookie.class.php @@ -12,7 +12,7 @@ class AjaxCookie extends AjaxHandler return; $this->_get = array( - $params[0] => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], + $params[0] => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], ); // NOW we know, what to expect and sanitize diff --git a/includes/ajaxHandler/data.class.php b/includes/ajaxHandler/data.class.php index b114baa9..6b6c7b10 100644 --- a/includes/ajaxHandler/data.class.php +++ b/includes/ajaxHandler/data.class.php @@ -6,12 +6,12 @@ if (!defined('AOWOW_REVISION')) class AjaxData extends AjaxHandler { protected $_get = array( - 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale'], - 't' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale' ], + 't' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], 'catg' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], - 'skill' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkSkill' ], + 'skill' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkSkill' ], 'class' => ['filter' => FILTER_SANITIZE_NUMBER_INT ], - 'callback' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkCallback' ] + 'callback' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkCallback' ] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/edit.class.php b/includes/ajaxHandler/edit.class.php index f1b81400..e8f31539 100644 --- a/includes/ajaxHandler/edit.class.php +++ b/includes/ajaxHandler/edit.class.php @@ -6,8 +6,8 @@ if (!defined('AOWOW_REVISION')) class AjaxEdit extends AjaxHandler { protected $_get = array( - 'qqfile' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'guide' => ['filter' => FILTER_SANITIZE_NUMBER_INT] + 'qqfile' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], + 'guide' => ['filter' => FILTER_SANITIZE_NUMBER_INT ] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/getdescription.class.php b/includes/ajaxHandler/getdescription.class.php index 3a88282c..5ba6ee1d 100644 --- a/includes/ajaxHandler/getdescription.class.php +++ b/includes/ajaxHandler/getdescription.class.php @@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION')) class AjaxGetdescription extends AjaxHandler { protected $_post = array( - 'description' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkFulltext']] + 'description' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkTextBlob']] ); public function __construct(array $params) diff --git a/includes/ajaxHandler/profile.class.php b/includes/ajaxHandler/profile.class.php index 163d13d6..94a4d63a 100644 --- a/includes/ajaxHandler/profile.class.php +++ b/includes/ajaxHandler/profile.class.php @@ -11,14 +11,14 @@ class AjaxProfile extends AjaxHandler protected $_get = array( 'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdList' ], 'items' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkItemList'], - 'size' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ], + 'size' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], 'guild' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'], 'arena-team' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkEmptySet'], 'user' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkUser' ] ); protected $_post = array( - 'name' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext'], + 'name' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'], 'level' => ['filter' => FILTER_SANITIZE_NUMBER_INT], 'class' => ['filter' => FILTER_SANITIZE_NUMBER_INT], 'race' => ['filter' => FILTER_SANITIZE_NUMBER_INT], @@ -28,12 +28,12 @@ class AjaxProfile extends AjaxHandler 'talenttree2' => ['filter' => FILTER_SANITIZE_NUMBER_INT], 'talenttree3' => ['filter' => FILTER_SANITIZE_NUMBER_INT], 'activespec' => ['filter' => FILTER_SANITIZE_NUMBER_INT], - 'talentbuild1' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'glyphs1' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'talentbuild2' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'glyphs2' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'icon' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'description' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkFulltext'], + 'talentbuild1' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkTalentString'], + 'glyphs1' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkGlyphString' ], + 'talentbuild2' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkTalentString'], + 'glyphs2' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxProfile::checkGlyphString' ], + 'icon' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine' ], + 'description' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextBlob' ], 'source' => ['filter' => FILTER_SANITIZE_NUMBER_INT], 'copy' => ['filter' => FILTER_SANITIZE_NUMBER_INT], 'public' => ['filter' => FILTER_SANITIZE_NUMBER_INT], @@ -762,6 +762,22 @@ class AjaxProfile extends AjaxHandler return ''; } + + protected static function checkTalentString(string $val) : string + { + if (preg_match('/^\d+$/', $val)) + return $val; + + return ''; + } + + protected static function checkGlyphString(string $val) : string + { + if (preg_match('/^\d+(:\d+)*$/', $val)) + return $val; + + return ''; + } } ?> diff --git a/includes/utilities.php b/includes/utilities.php index 60d0cc99..49ee92f5 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -109,10 +109,16 @@ trait TrRequestData return []; } - private static function checkFulltext(string $val) : string + private static function checkTextLine(string $val) : string { // trim non-printable chars - return preg_replace('/[\p{Cf}\p{Co}\p{Cs}\p{Cn}]/ui', '', $val); + return preg_replace('/[\p{Cc}\p{Cf}\p{Co}\p{Cs}\p{Cn}]/ui', '', $val); + } + + private static function checkTextBlob(string $val) : string + { + // trim non-printable chars + return preg_replace('/[\x00-\x09\x0B-\x1F\p{Cf}\p{Co}\p{Cs}\p{Cn}]/ui', '', $val); } } diff --git a/pages/account.php b/pages/account.php index a910efc4..589fc067 100644 --- a/pages/account.php +++ b/pages/account.php @@ -34,9 +34,9 @@ class AccountPage extends GenericPage protected $_post = array( 'username' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'password' => ['filter' => FILTER_UNSAFE_RAW], - 'c_password' => ['filter' => FILTER_UNSAFE_RAW], - 'token' => ['filter' => FILTER_UNSAFE_RAW], + 'password' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextLine'], + 'c_password' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextLine'], + 'token' => ['filter' => FILTER_SANITIZE_SPECIAL_CHARS, 'flags' => FILTER_FLAG_STRIP_AOWOW], 'remember_me' => ['filter' => FILTER_CALLBACK, 'options' => 'AccountPage::rememberCallback'], 'email' => ['filter' => FILTER_SANITIZE_EMAIL] ); diff --git a/pages/guide.php b/pages/guide.php index 923ff653..ab3fb85a 100644 --- a/pages/guide.php +++ b/pages/guide.php @@ -42,11 +42,11 @@ class GuidePage extends GenericPage protected /* array */ $_post = array( 'save' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'], 'submit' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet'], - 'title' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'name' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'description' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'changelog' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW], - 'body' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkFulltext'], + 'title' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextLine'], + 'name' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextLine'], + 'description' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextBlob'], + 'changelog' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextBlob'], + 'body' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextBlob'], 'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], 'category' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], 'specId' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'], diff --git a/pages/screenshot.php b/pages/screenshot.php index f31a3483..c58e6e64 100644 --- a/pages/screenshot.php +++ b/pages/screenshot.php @@ -29,7 +29,7 @@ class ScreenshotPage extends GenericPage protected $_post = array( 'coords' => ['filter' => FILTER_CALLBACK, 'options' => 'ScreenshotPage::checkCoords'], - 'screenshotalt' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW] + 'screenshotalt' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkTextBlob'] ); public function __construct($pageCall, $pageParam) From 6ee0d637669f0a8745040e45c4a46b773ad26004 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sun, 19 Mar 2023 18:02:57 +0100 Subject: [PATCH 030/698] Update external links to point to wotlk speciffic database --- includes/kernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/kernel.php b/includes/kernel.php index a4814662..81b9a16d 100644 --- a/includes/kernel.php +++ b/includes/kernel.php @@ -271,7 +271,7 @@ if (!CLI) $pageCall = $_[0]; $pageParam = $_[1] ?? ''; - Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str; + Util::$wowheadLink = 'https://www.wowhead.com/wotlk/'.(User::$localeId ? Util::$subDomains[User::$localeId].'/' : '').$str; } else if (!empty($AoWoWconf['aowow'])) Lang::load('enus'); From d77e459da3d5e34ac0d4b795177c6fd5936a821a Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sat, 18 Mar 2023 21:30:55 +0100 Subject: [PATCH 031/698] Tooltips/TimeFMT * use strings from globalstrings.lua to format time in item and spell tooltips * fixed item filter ItemCooldown * fixed timeAgo format * move item duration to correct position in tooltip --- includes/basetype.class.php | 2 +- includes/types/item.class.php | 32 ++++++++++++++++----------- includes/types/spell.class.php | 7 ++---- includes/utilities.php | 4 ++-- localization/lang.class.php | 33 +++++++++++++++++++++++++++- localization/locale_dede.php | 39 ++++++++++++++++++++++++++++++--- localization/locale_enus.php | 39 ++++++++++++++++++++++++++++++--- localization/locale_eses.php | 39 ++++++++++++++++++++++++++++++--- localization/locale_frfr.php | 39 ++++++++++++++++++++++++++++++--- localization/locale_ruru.php | 40 +++++++++++++++++++++++++++++++--- localization/locale_zhcn.php | 39 ++++++++++++++++++++++++++++++--- 11 files changed, 273 insertions(+), 40 deletions(-) diff --git a/includes/basetype.class.php b/includes/basetype.class.php index 3ad4dd6b..ceb0b281 100644 --- a/includes/basetype.class.php +++ b/includes/basetype.class.php @@ -942,7 +942,7 @@ abstract class Filter public function getExtraCols() { - return $this->formData['extraCols']; + return array_unique($this->formData['extraCols']); } public function getSetCriteria() diff --git a/includes/types/item.class.php b/includes/types/item.class.php index 96d07d4a..a5051369 100644 --- a/includes/types/item.class.php +++ b/includes/types/item.class.php @@ -604,16 +604,6 @@ class ItemList extends BaseType $x .= '
'.sprintf(Lang::item($limit['isGem'] ? 'uniqueEquipped' : 'unique', 2), Util::localizedString($limit, 'name'), $limit['count']); } - // max duration - if ($dur = $this->curTpl['duration']) - { - $rt = ''; - if ($this->curTpl['flagsCustom'] & 0x1) - $rt = $interactive ? ' ('.sprintf(Util::$dfnString, 'LANG.tooltip_realduration', Lang::item('realTime')).')' : ' ('.Lang::item('realTime').')'; - - $x .= "
".Lang::game('duration').Lang::main('colon').Util::formatTime(abs($dur) * 1000).$rt; - } - // required holiday if ($eId = $this->curTpl['eventId']) if ($hName = DB::Aowow()->selectRow('SELECT h.* FROM ?_holidays h JOIN ?_events e ON e.holidayId = h.id WHERE e.id = ?d', $eId)) @@ -875,6 +865,16 @@ class ItemList extends BaseType if ($dur = $this->curTpl['durability']) $x .= sprintf(Lang::item('durability'), $dur, $dur).'
'; + // max duration + if ($dur = $this->curTpl['duration']) + { + $rt = ''; + if ($this->curTpl['flagsCustom'] & 0x1) + $rt = $interactive ? ' ('.sprintf(Util::$dfnString, 'LANG.tooltip_realduration', Lang::item('realTime')).')' : ' ('.Lang::item('realTime').')'; + + $x .= Lang::formatTime(abs($dur) * 1000, 'item', 'duration').$rt."
"; + } + $jsg = []; // required classes if ($classes = Lang::getClassString($this->curTpl['requiredClass'], $jsg)) @@ -959,12 +959,18 @@ class ItemList extends BaseType $extra = []; if ($cd >= 5000) - $extra[] = Lang::game('cooldown', [Util::formatTime($cd, true)]); + { + $pt = Util::parseTime($cd); + if (count(array_filter($pt)) == 1) // simple time: use simple method + $extra[] = Lang::formatTime($cd, 'item', 'cooldown'); + else // build block with generic time + $extra[] = Lang::item('cooldown', 0, [Lang::formatTime($cd, 'game', 'timeAbbrev', true)]); + } if ($this->curTpl['spellTrigger'.$j] == 2) if ($ppm = $this->curTpl['spellppmRate'.$j]) $extra[] = Lang::spell('ppm', [$ppm]); - $itemSpellsAndTrigger[$this->curTpl['spellId'.$j]] = [$this->curTpl['spellTrigger'.$j], $extra ? ' ('.implode(', ', $extra).')' : '']; + $itemSpellsAndTrigger[$this->curTpl['spellId'.$j]] = [$this->curTpl['spellTrigger'.$j], $extra ? ' '.implode(', ', $extra) : '']; } } @@ -2437,7 +2443,7 @@ class ItemListFilter extends Filter $cr[2] *= 1000; // field supplied in milliseconds $this->formData['extraCols'][] = $cr[0]; - $this->extraOpts['is']['s'][] = ', IF(spellCooldown1 > 1, spellCooldown1, IF(spellCooldown2 > 1, spellCooldown2, IF(spellCooldown3 > 1, spellCooldown3, IF(spellCooldown4 > 1, spellCooldown4, IF(spellCooldown5 > 1, spellCooldown5,))))) AS cooldown'; + $this->extraOpts['is']['s'][] = ', GREATEST(spellCooldown1, spellCooldown2, spellCooldown3, spellCooldown4, spellCooldown5) AS cooldown'; return [ 'OR', diff --git a/includes/types/spell.class.php b/includes/types/spell.class.php index 0b258c14..3a44ec3a 100644 --- a/includes/types/spell.class.php +++ b/includes/types/spell.class.php @@ -1123,10 +1123,7 @@ class SpellList extends BaseType case 'D': // todo (med): min/max?; /w unit? $base = $srcSpell->getField('duration'); - if ($base <= 0) - $result[2] = Lang::spell('untilCanceled'); - else - $result[2] = Util::formatTime($base, true); + $result[2] = Lang::formatTime($srcSpell->getField('duration'), 'spell', 'duration'); if (in_array($op, $signs) && is_numeric($oparg) && is_numeric($base)) eval("\$base = $base $op $oparg;"); @@ -1907,7 +1904,7 @@ class SpellList extends BaseType // duration if ($this->curTpl['duration'] > 0) - $x .= ''.sprintf(Lang::spell('remaining'), Util::formatTime($this->curTpl['duration'])).''; + $x .= ''.Lang::formatTime($this->curTpl['duration'], 'spell', 'timeRemaining').''; $x .= ''; diff --git a/includes/utilities.php b/includes/utilities.php index 49ee92f5..1f7f75cf 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -573,7 +573,7 @@ abstract class Util return $money; } - private static function parseTime(int $msec) : array + public static function parseTime(int $msec) : array { $time = [0, 0, 0, 0, 0]; @@ -671,7 +671,7 @@ abstract class Util else if ($h) // hours, minutes ago return Lang::main('timeAgo', [$h . ' ' . Lang::timeUnits('ab', 4) . ' ' . $m . ' ' . Lang::timeUnits('ab', 5)]); else if ($m) // minutes, seconds ago - return Lang::main('timeAgo', [$m . ' ' . Lang::timeUnits('ab', 5) . ' ' . $m . ' ' . Lang::timeUnits('ab', 6)]); + return Lang::main('timeAgo', [$m . ' ' . Lang::timeUnits('ab', 5) . ' ' . $s . ' ' . Lang::timeUnits('ab', 6)]); else // seconds ago return Lang::main('timeAgo', [$s . ' ' . Lang::timeUnits($s == 1 ? 'sg' : 'pl', 6)]); } diff --git a/localization/lang.class.php b/localization/lang.class.php index b8076ea0..6953b6c9 100644 --- a/localization/lang.class.php +++ b/localization/lang.class.php @@ -487,8 +487,39 @@ class Lang return Util::ucFirst(self::game(Type::getFileString($type))); } + public static function formatTime(int $msec, string $prop = 'game', string $src = 'timeAbbrev', bool $concat = false) : string + { + if ($msec < 0) + $msec = 0; - private static function vspf($var, $args) + [$ms, $s, $m, $h, $d] = Util::parseTime($msec); + $ref = []; + $result = []; + + if (is_array(self::$$prop[$src])) + $ref = &self::$$prop[$src]; + else + { + trigger_error('Lang::formatTime - tried to access undefined property Lang::$'.$prop, E_USER_WARNING); + return ''; + } + + if ($d >= 1) + $result[] = self::vspf($ref[4], [$d + $h / 24]); + if ($h >= 1 && ($concat || !$result)) + $result[] = self::vspf($ref[3], [$h + $m / 60]); + if ($m >= 1 && ($concat || !$result)) + $result[] = self::vspf($ref[2], [$m + $s / 60]); + if ($s >= 1 && ($concat || !$result)) + $result[] = self::vspf($ref[1], [$s]); + + if (!$result) + $result[] = self::vspf($ref[0]); + + return implode(', ', $result); + } + + private static function vspf($var, array $args = []) { if (is_array($var)) { diff --git a/localization/locale_dede.php b/localization/locale_dede.php index f835fe5f..d60ed1e1 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -358,6 +358,13 @@ $lang = array( 'modes' => [-1 => "Beliebig", "Normal / Normal 10", "Heroisch / Normal 25", "Heroisch 10", "Heroisch 25"], 'expansions' => ["Classic", "The Burning Crusade", "Wrath of the Lich King"], 'stats' => ["Stärke", "Beweglichkeit", "Ausdauer", "Intelligenz", "Willenskraft"], + 'timeAbbrev' => array( + '', + "%d |4Sek.:Sek.;", + "%d |4Min.:Min.;", + "%d |4Std.:Std.;", + "%d |4Tag:Tage;" + ), 'sources' => array( "Unbekannt", "Hergestellt", "Drop", "PvP", "Quest", "Händler", "Lehrer", "Entdeckung", "Einlösung", "Talent", "Startausrüstung", "Ereignis", @@ -1445,12 +1452,10 @@ $lang = array( '_transfer' => 'Dieser Zauber wird mit %s vertauscht, wenn Ihr zur %s wechselt.', 'currentArea' => '<Momentanes Gebiet>', 'discovered' => "Durch Geistesblitz erlernt", - 'ppm' => "%s Auslösungen pro Minute", + 'ppm' => "(%s Auslösungen pro Minute)", 'procChance' => "Procchance", 'starter' => "Basiszauber", 'trainingCost' => "Trainingskosten", - 'remaining' => "Noch %s", - 'untilCanceled' => "bis Abbruch", 'castIn' => "Wirken in %s Sek.", 'instantPhys' => "Sofort", 'instantMagic' => "Spontanzauber", @@ -1467,6 +1472,20 @@ $lang = array( 'stackGroup' => "Stack Gruppierung", 'linkedWith' => "Verknüpft mit", '_scaling' => "Skalierung", + 'duration' => array( + "bis Abbruch", + "%.2G Sek.", + "%.2G Min.", + "%.2G |4Stunde:Stunden;", + "%.2G |4Tag:Tage;" + ), + 'timeRemaining' => array( + "", + "Noch %d |4Sekunde:Sekunden;", + "Noch %d |4Minute:Minuten;", + "Noch %d |4Stunde:Stunden;", + "Noch %d |4Tag:Tage;" + ), 'scaling' => array( 'directSP' => "+%.2f%% der Zaubermacht zum direkten Effekt", 'directAP' => "+%.2f%% der Angriffskraft zum direkten Effekt", 'dotSP' => "+%.2f%% der Zaubermacht pro Tick", 'dotAP' => "+%.2f%% der Angriffskraft pro Tick" @@ -1783,6 +1802,20 @@ $lang = array( 'uniqueEquipped'=> ["Einzigartig anlegbar", null, "Einzigartig angelegt: %s (%d)"], 'speed' => "Tempo", 'dps' => "(%.1f Schaden pro Sekunde)", + 'duration' => array( // ITEM_DURATION_* + '', + "Dauer: %d Sek.", + "Dauer: %d Min.", + "Dauer: %d |4Stunde:Stunden;", + "Dauer: %d |4Tag:Tage;" + ), + 'cooldown' => array( // ITEM_COOLDOWN_TOTAL* + '(%s Abklingzeit)', + "(%d Sek. Abklingzeit)", + "(%d Min. Abklingzeit)", + "(%d |4Stunde:Stunden; Abklingzeit)", + "(%d |4Tag:Tage; Abklingzeit)" + ), 'damage' => array( // *DAMAGE_TEMPLATE* // basic, basic /w school, add basic, add basic /w school 'single' => ['%d Schaden', '%1$d %2$sschaden', '+ %1$d Schaden', '+ %1$d %2$sschaden' ], diff --git a/localization/locale_enus.php b/localization/locale_enus.php index 14b4dd0e..9779d1c2 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -358,6 +358,13 @@ $lang = array( 'modes' => [-1 => "Any", "Normal / Normal 10", "Heroic / Normal 25", "Heroic 10", "Heroic 25"], 'expansions' => ["Classic", "The Burning Crusade", "Wrath of the Lich King"], 'stats' => ["Strength", "Agility", "Stamina", "Intellect", "Spirit"], + 'timeAbbrev' => array( //