From fd04e9f97784823000cfd8e6ca4db99ca26f217c Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Sat, 15 Dec 2018 01:49:55 +0100 Subject: [PATCH] Implemented new type: mail * display and link clientside mails to other types and events * fixed favorites menu for new types * fixed sorting column triggered spells in enchantment listview * some misc cleanups --- includes/community.class.php | 21 +-- includes/defines.php | 1 + includes/types/areatrigger.class.php | 22 +-- includes/types/mail.class.php | 69 +++++++++ includes/user.class.php | 2 +- includes/utilities.php | 87 ++++++----- index.php | 2 + localization/lang.class.php | 29 +++- localization/locale_dede.php | 21 ++- localization/locale_enus.php | 21 ++- localization/locale_eses.php | 21 ++- localization/locale_frfr.php | 21 ++- localization/locale_ruru.php | 21 ++- localization/locale_zhcn.php | 21 ++- pages/account.php | 8 +- pages/achievement.php | 6 +- pages/genericPage.class.php | 1 + pages/mail.php | 168 +++++++++++++++++++++ pages/mails.php | 46 ++++++ pages/quest.php | 7 +- setup/db_structure.sql | 18 +-- setup/tools/CLISetup.class.php | 4 +- setup/tools/clisetup/firstrun.func.php | 8 +- setup/tools/filegen/simpleImg.func.php | 6 +- setup/tools/sqlgen/mailtemplate.func.php | 46 +++++- setup/tools/sqlgen/source.func.php | 2 +- setup/updates/1581549222_01.sql | 21 +++ static/js/global.js | 3 +- static/js/locale_dede.js | 7 +- static/js/locale_enus.js | 7 +- static/js/locale_eses.js | 8 +- static/js/locale_frfr.js | 8 +- static/js/locale_ruru.js | 8 +- static/js/locale_zhcn.js | 9 +- template/bricks/mail.tpl.php | 2 +- template/listviews/enchantment.tpl.php | 2 +- template/listviews/mail.tpl.php | 97 ++++++++++++ template/pages/detail-page-generic.tpl.php | 2 +- 38 files changed, 682 insertions(+), 171 deletions(-) create mode 100644 includes/types/mail.class.php create mode 100644 pages/mail.php create mode 100644 pages/mails.php create mode 100644 setup/updates/1581549222_01.sql create mode 100644 template/listviews/mail.tpl.php diff --git a/includes/community.class.php b/includes/community.class.php index db9ca888..3ca0d368 100644 --- a/includes/community.class.php +++ b/includes/community.class.php @@ -172,25 +172,8 @@ class CommunityContent if (empty($params['replies'])) unset($c['commentid']); - // remove line breaks - $c['preview'] = strtr($c['preview'], ["\n" => ' ', "\r" => ' ']); - // limit whitespaces to one at a time - $c['preview'] = preg_replace('/\s+/', ' ', $c['preview']); - // limit previews to 100 chars + whatever it takes to make the last word full - if (mb_strlen($c['preview']) > 100) - { - $n = 0; - $b = []; - $parts = explode(' ', $c['preview']); - while ($n < 100 && $parts) - { - $_ = array_shift($parts); - $n += mb_strlen($_); - $b[] = $_; - } - - $c['preview'] = implode(' ', $b).'…'; - } + // format text for listview + $c['preview'] = Lang::trimTextClean($c['preview']); } else { diff --git a/includes/defines.php b/includes/defines.php index 813fd27f..dfd6c364 100644 --- a/includes/defines.php +++ b/includes/defines.php @@ -36,6 +36,7 @@ define('TYPE_USER', 500); define('TYPE_EMOTE', 501); define('TYPE_ENCHANTMENT', 502); define('TYPE_AREATRIGGER', 503); +define('TYPE_MAIL', 504); define('CACHE_TYPE_NONE', 0); // page will not be cached define('CACHE_TYPE_PAGE', 1); diff --git a/includes/types/areatrigger.class.php b/includes/types/areatrigger.class.php index 27d6dd57..dc34233a 100644 --- a/includes/types/areatrigger.class.php +++ b/includes/types/areatrigger.class.php @@ -18,18 +18,6 @@ class AreaTriggerList extends BaseType 's' => ['j' => ['?_spawns s ON s.type = 503 AND s.typeId = a.id', true], 's' => ', s.areaId'] ); - public function __construct($conditions = []) - { - parent::__construct($conditions); - - // post processing - foreach ($this->iterate() as &$curTpl) - { - // remap for generic access - // $curTpl['name'] = $curTpl['cmd']; - } - } - public function getListviewData() { $data = []; @@ -49,15 +37,7 @@ class AreaTriggerList extends BaseType return $data; } - public function getJSGlobals($addMask = GLOBALINFO_ANY) - { - $data = []; - - // foreach ($this->iterate() as $__) - // $data[TYPE_EMOTE][$this->id] = ['name' => $this->getField('cmd')]; - - return $data; - } + public function getJSGlobals($addMask = GLOBALINFO_ANY) { } public function renderTooltip() { } } diff --git a/includes/types/mail.class.php b/includes/types/mail.class.php new file mode 100644 index 00000000..25b7c3e6 --- /dev/null +++ b/includes/types/mail.class.php @@ -0,0 +1,69 @@ +error) + return; + + // post processing + foreach ($this->iterate() as &$_curTpl) + { + $_curTpl['name'] = Util::localizedString($_curTpl, 'subject', true); + } + } + + public static function getName($id) + { + $n = DB::Aowow()->SelectRow('SELECT subject_loc0, subject_loc2, subject_loc3, subject_loc4, subject_loc6, subject_loc8 FROM ?_mails WHERE id = ?d', $id); + return Util::localizedString($n, 'subject'); + } + + public function getListviewData() + { + $data = []; + + foreach ($this->iterate() as $__) + { + $body = str_replace('[br]', ' ', Util::parseHtmlText($this->getField('text', true), true)); + + $data[$this->id] = array( + 'id' => $this->id, + 'subject' => $this->getField('subject', true), + 'body' => Lang::trimTextClean($body), + 'attachments' => [$this->getField('attachment')] + ); + } + + return $data; + } + + public function getJSGlobals($addMask = 0) + { + $data = []; + + foreach ($this->iterate() as $__) + if ($a = $this->curTpl['attachment']) + $data[TYPE_ITEM][$a] = $a; + + return $data; + } + + public function renderTooltip() { } +} + +?> diff --git a/includes/user.class.php b/includes/user.class.php index 351533d7..9e567624 100644 --- a/includes/user.class.php +++ b/includes/user.class.php @@ -671,7 +671,7 @@ class User $entities = []; foreach ($tc->iterate() as $id => $__) - $entities[] = [$id, $tc->getField('name', true)]; + $entities[] = [$id, $tc->getField('name', true, true)]; if ($entities) $data[] = ['id' => $type, 'entities' => $entities]; diff --git a/includes/utilities.php b/includes/utilities.php index bd3c2bf0..44aaa0b2 100644 --- a/includes/utilities.php +++ b/includes/utilities.php @@ -6,11 +6,11 @@ if (!defined('AOWOW_REVISION')) class SimpleXML extends SimpleXMLElement { - public function addCData($str) + public function addCData(string $cData) : SimpleXMLElement { $node = dom_import_simplexml($this); $no = $node->ownerDocument; - $node->appendChild($no->createCDATASection($str)); + $node->appendChild($no->createCDATASection($cData)); return $this; } @@ -40,7 +40,7 @@ class CLI /* logging */ /***********/ - public static function initLogFile($file = '') + public static function initLogFile(string $file = '') : void { if (!$file) return; @@ -61,32 +61,32 @@ class CLI } } - public static function red($str) + public static function red(string $str) : string { return OS_WIN ? $str : "\e[31m".$str."\e[0m"; } - public static function green($str) + public static function green(string $str) : string { return OS_WIN ? $str : "\e[32m".$str."\e[0m"; } - public static function yellow($str) + public static function yellow(string $str) : string { return OS_WIN ? $str : "\e[33m".$str."\e[0m"; } - public static function blue($str) + public static function blue(string $str) : string { return OS_WIN ? $str : "\e[36m".$str."\e[0m"; } - public static function bold($str) + public static function bold(string $str) : string { return OS_WIN ? $str : "\e[1m".$str."\e[0m"; } - public static function write($txt = '', $lvl = -1) + public static function write(string $txt = '', int $lvl = -1) : void { $msg = "\n"; if ($txt) @@ -121,14 +121,22 @@ class CLI flush(); } - public static function nicePath(string $file, string ...$pathParts) : string + public static function nicePath(string $fileOrPath, string ...$pathParts) : string { $path = ''; - if (!$pathParts) - return $file; + if ($pathParts) + { + foreach ($pathParts as &$pp) + $pp = trim($pp); - $path = implode(DIRECTORY_SEPARATOR, $pathParts).DIRECTORY_SEPARATOR.$file; + $path .= implode(DIRECTORY_SEPARATOR, $pathParts); + } + + $path .= ($path ? DIRECTORY_SEPARATOR : '').trim($fileOrPath); + + // remove quotes (from erronous user input) + $path = str_replace(['"', "'"], ['', ''], $path); if (DIRECTORY_SEPARATOR == '/') // *nix { @@ -143,8 +151,6 @@ class CLI else CLI::write('Dafuq! Your directory separator is "'.DIRECTORY_SEPARATOR.'". Please report this!', CLI::LOG_ERROR); - $path = trim($path); - // resolve *nix home shorthand if (!OS_WIN) { @@ -156,9 +162,6 @@ class CLI $path = substr($path, 1); } - // remove quotes (from erronous user input) - $path = str_replace(['"', "'"], ['', ''], $path); - return $path; } @@ -174,7 +177,7 @@ class CLI this also means, you can't hide input at all, least process it */ - public static function readInput(&$fields, $singleChar = false) + public static function readInput(array &$fields, bool $singleChar = false) : bool { // first time set if (self::$hasReadline === null) @@ -283,7 +286,9 @@ class Util 'CharRaceList', 'SkillList', null, 'CurrencyList', null, 'SoundList', TYPE_ICON => 'IconList', TYPE_EMOTE => 'EmoteList', - TYPE_ENCHANTMENT => 'EnchantmentList' + TYPE_ENCHANTMENT => 'EnchantmentList', + TYPE_AREATRIGGER => 'AreatriggerList', + TYPE_MAIL => 'MailList' ); public static $typeStrings = array( // zero-indexed @@ -293,7 +298,9 @@ class Util TYPE_ICON => 'icon', TYPE_USER => 'user', TYPE_EMOTE => 'emote', - TYPE_ENCHANTMENT => 'enchantment' + TYPE_ENCHANTMENT => 'enchantment', + TYPE_AREATRIGGER => 'areatrigger', + TYPE_MAIL => 'mail' ); # todo (high): find a sensible way to write data here on setup @@ -369,12 +376,12 @@ class Util public static $wowheadLink = ''; private static $notes = []; - public static function addNote($uGroupMask, $str) + public static function addNote(int $uGroupMask, string $str) : void { self::$notes[] = [$uGroupMask, $str]; } - public static function getNotes() + public static function getNotes() : array { $notes = []; @@ -387,16 +394,16 @@ class Util private static $execTime = 0.0; - public static function execTime($set = false) + public static function execTime(bool $set = false) : string { if ($set) { self::$execTime = microTime(true); - return; + return ''; } if (!self::$execTime) - return; + return ''; $newTime = microTime(true); $tDiff = $newTime - self::$execTime; @@ -405,7 +412,7 @@ class Util return self::formatTime($tDiff * 1000, true); } - public static function formatMoney($qty) + public static function formatMoney(int $qty) : string { $money = ''; @@ -429,7 +436,7 @@ class Util return $money; } - public static function parseTime($sec) + public static function parseTime(int $sec) : array { $time = ['d' => 0, 'h' => 0, 'm' => 0, 's' => 0, 'ms' => 0]; @@ -463,9 +470,9 @@ class Util return $time; } - public static function formatTime($base, $short = false) + public static function formatTime(int $msec, bool $short = false) : string { - $s = self::parseTime($base / 1000); + $s = self::parseTime($msec / 1000); $fmt = []; if ($short) @@ -514,7 +521,7 @@ class Util } // pageText for Books (Item or GO) and questText - public static function parseHtmlText($text , $markdown = false) + public static function parseHtmlText(string $text, bool $markdown = false) : string { if (stristr($text, '')) // text is basically a html-document with weird linebreak-syntax { @@ -554,14 +561,14 @@ class Util $toMD = array( '[icon name=\2]', '[span color=#\1>\2[/span]', - '<\1/\2>', + '<\1/\2>', '', '\1', - '<\1>', + '<\1>', '[span class=q0>WorldState #\1[/span]', - '<'.Lang::game('class').'>', - '<'.Lang::game('race').'>', - '<'.Lang::main('name').'>', + '<'.Lang::game('class').'>', + '<'.Lang::game('race').'>', + '<'.Lang::main('name').'>', '[br]', '' ); @@ -584,7 +591,7 @@ class Util return preg_replace($from, $markdown ? $toMD : $toHTML, $text); } - public static function asHex($val) + public static function asHex($val) : string { $_ = decHex($val); while (fMod(strLen($_), 4)) // in 4-blocks @@ -593,7 +600,7 @@ class Util return '0x'.strToUpper($_); } - public static function asBin($val) + public static function asBin($val) : string { $_ = decBin($val); while (fMod(strLen($_), 4)) // in 4-blocks @@ -653,7 +660,7 @@ class Util } // default back to enUS if localization unavailable - public static function localizedString($data, $field, $silent = false) + public static function localizedString(array $data, string $field, bool $silent = false) : string { // only display placeholder markers for staff if (!User::isInGroup(U_GROUP_EMPLOYEE | U_GROUP_TESTER | U_GROUP_LOCALIZER)) @@ -681,7 +688,7 @@ class Util } // for item and spells - public static function setRatingLevel($level, $type, $val) + public static function setRatingLevel(int $level, int $type, int $val) : string { if (in_array($type, [ITEM_MOD_DEFENSE_SKILL_RATING, ITEM_MOD_DODGE_RATING, ITEM_MOD_PARRY_RATING, ITEM_MOD_BLOCK_RATING, ITEM_MOD_RESILIENCE_RATING]) && $level < 34) $level = 34; diff --git a/index.php b/index.php index 97cb03b6..f02c93a8 100644 --- a/index.php +++ b/index.php @@ -48,6 +48,8 @@ switch ($pageCall) case 'itemset': case 'itemsets': case 'maps': // tool: map listing + case 'mail': + case 'mails': case 'npc': case 'npcs': case 'object': diff --git a/localization/lang.class.php b/localization/lang.class.php index 65a8fb2c..422c7aae 100644 --- a/localization/lang.class.php +++ b/localization/lang.class.php @@ -6,7 +6,6 @@ class Lang private static $main; private static $account; private static $user; - private static $mail; private static $game; private static $maps; private static $profiler; @@ -26,6 +25,7 @@ class Lang private static $icon; private static $item; private static $itemset; + private static $mail; private static $npc; private static $pet; private static $quest; @@ -124,6 +124,33 @@ class Lang return $b; } + public static function trimTextClean(string $text, int $length = 100) : string + { + // remove line breaks + $text = strtr($text, ["\n" => ' ', "\r" => ' ']); + + // limit whitespaces to one at a time + $text = preg_replace('/\s+/', ' ', trim($text)); + + // limit previews to 100 chars + whatever it takes to make the last word full + if ($length > 0 && mb_strlen($text) > $length) + { + $n = 0; + $b = []; + $parts = explode(' ', $text); + while ($n < $length && $parts) + { + $_ = array_shift($parts); + $n += mb_strlen($_); + $b[] = $_; + } + + $text = implode(' ', $b).'…'; + } + + return $text; + } + public static function sort($prop, $group, $method = SORT_NATURAL) { diff --git a/localization/locale_dede.php b/localization/locale_dede.php index 863a5ec2..99b49c91 100644 --- a/localization/locale_dede.php +++ b/localization/locale_dede.php @@ -236,6 +236,8 @@ $lang = array( 'items' => "Gegenstände", 'itemset' => "Ausrüstungsset", 'itemsets' => "Ausrüstungssets", + 'mail' => "Brief", + 'mails' => "Briefe", 'mechanic' => "Auswirkung", 'mechAbbr' => "Ausw.", 'meetingStone' => "Versammlungsstein", @@ -783,9 +785,8 @@ $lang = array( 'comments' => "Kommentare", 'screenshots' => "Screenshots", 'videos' => "Videos", - 'posts' => "Forenbeiträge" - ), - 'mail' => array( + 'posts' => "Forenbeiträge", + // user mail 'tokenExpires' => "Das Token wird in %s verfallen.", 'accConfirm' => ["Kontobestätigung", "Willkommen bei ".CFG_NAME_SHORT."!\r\n\r\nKlicke auf den Link um euren Account zu aktivieren.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nFalls Ihr diese Mail nicht angefordert habt kann sie einfach ignoriert werden."], 'recoverUser' => ["Benutzernamenanfrage", "Folgt diesem Link um euch anzumelden.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nFalls Ihr diese Mail nicht angefordert habt kann sie einfach ignoriert werden."], @@ -1028,9 +1029,6 @@ $lang = array( 'enabledByQDesc'=> "Ihr könnt diese Quest nur annehmen, wenn eins der nachfolgenden Quests aktiv ist", 'gainsDesc' => "Bei Abschluss dieser Quest erhaltet Ihr", 'theTitle' => 'den Titel "%s"', - 'mailDelivery' => "Ihr werdet diesen Brief%s%s erhalten", - 'mailBy' => ' von %s', - 'mailIn' => " nach %s", 'unavailable' => "Diese Quest wurde als nicht genutzt markiert und kann weder erhalten noch vollendet werden.", 'experience' => "Erfahrung", 'expConvert' => "(oder %s, wenn auf Stufe %d vollendet)", @@ -1042,7 +1040,6 @@ $lang = array( 'spellLearn' => "Ihr erlernt", 'bonusTalents' => "%d |4Talentpunkt:Talentpunkte;", 'spellDisplayed'=> ' (%s wird angezeigt)', - 'attachment' => "Anlage", 'questInfo' => array( 0 => "Normal", 1 => "Gruppe", 21 => "Leben", 41 => "PvP", 62 => "Schlachtzug", 81 => "Dungeon", 82 => "Weltereignis", 83 => "Legendär", 84 => "Eskorte", 85 => "Heroisch", 88 => "Schlachtzug (10)", 89 => "Schlachtzug (25)" @@ -1159,6 +1156,16 @@ $lang = array( "Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Meine Playlist" ) ), + 'mail' => array( + 'notFound' => "Dieser Brief existiert nicht.", + 'attachment' => "Anlage", + 'mailDelivery' => 'Ihr werdet diesen Brief%s%s erhalten', + 'mailBy' => ' von %s', + 'mailIn' => " nach %s", + 'delay' => "Verzögerung", + 'sender' => "Absender", + 'untitled' => "Unbetitelter Brief" + ), 'pet' => array( 'notFound' => "Diese Tierart existiert nicht.", 'exotic' => "Exotisch", diff --git a/localization/locale_enus.php b/localization/locale_enus.php index ff69e0b3..8d64f545 100644 --- a/localization/locale_enus.php +++ b/localization/locale_enus.php @@ -236,6 +236,8 @@ $lang = array( 'items' => "Items", 'itemset' => "item Set", 'itemsets' => "Item Sets", + 'mail' => "mail", + 'mails' => "Mails", 'mechanic' => "Mechanic", 'mechAbbr' => "Mech.", 'meetingStone' => "Meeting Stone", @@ -783,9 +785,8 @@ $lang = array( 'comments' => "Comments", 'screenshots' => "Screenshots", 'videos' => "Videos", - 'posts' => "Forum posts" - ), - 'mail' => array( + 'posts' => "Forum posts", + // user mail 'tokenExpires' => "This token expires in %s.", 'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."], 'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."], @@ -1028,9 +1029,6 @@ $lang = array( 'enabledByQDesc'=> "This quest is available only, when one of these quests are active", 'gainsDesc' => "Upon completion of this quest you will gain", 'theTitle' => 'the title "%s"', // partly REWARD_TITLE - 'mailDelivery' => "You will receive this letter%s%s", - 'mailBy' => ' by %s', - 'mailIn' => " after %s", 'unavailable' => "This quest was marked obsolete and cannot be obtained or completed.", 'experience' => "experience", 'expConvert' => "(or %s if completed at level %d)", @@ -1042,7 +1040,6 @@ $lang = array( 'spellLearn' => "You will learn", // REWARD_SPELL 'bonusTalents' => "%d talent |4point:points;", // partly LEVEL_UP_CHAR_POINTS 'spellDisplayed'=> ' (%s is displayed)', - 'attachment' => "Attachment", 'questInfo' => array( 0 => "Normal", 1 => "Group", 21 => "Life", 41 => "PvP", 62 => "Raid", 81 => "Dungeon", 82 => "World Event", 83 => "Legendary", 84 => "Escort", 85 => "Heroic", 88 => "Raid (10)", 89 => "Raid (25)" @@ -1159,6 +1156,16 @@ $lang = array( "Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "My Playlist" ) ), + 'mail' => array( + 'notFound' => "This mail doesn't exist.", + 'attachment' => "Attachment", + 'mailDelivery' => 'You will receive this letter%s%s', + 'mailBy' => ' by %s', + 'mailIn' => " after %s", + 'delay' => "Delay", + 'sender' => "Sender", + 'untitled' => "Untitled Mail" + ), 'pet' => array( 'notFound' => "This pet family doesn't exist.", 'exotic' => "Exotic", diff --git a/localization/locale_eses.php b/localization/locale_eses.php index f8d22b37..4fbba791 100644 --- a/localization/locale_eses.php +++ b/localization/locale_eses.php @@ -236,6 +236,8 @@ $lang = array( 'items' => "Objetos", 'itemset' => "conjunto de objetos", 'itemsets' => "Conjuntos de objetos", + 'mail' => "mail", + 'mails' => "Mails", 'mechanic' => "Mecanica", 'mechAbbr' => "Mec.", 'meetingStone' => "Roca de encuentro", @@ -783,9 +785,8 @@ $lang = array( 'comments' => "Comentarios", 'screenshots' => "Capturas de pantalla", 'videos' => "Vídeos", - 'posts' => "Mensajes en los foros" - ), - 'mail' => array( + 'posts' => "Mensajes en los foros", + // user mail 'tokenExpires' => "Este token expira en %s", 'accConfirm' => ["Confirmación de Cuenta", "Bienvenido a ".CFG_NAME_SHORT."!\r\n\r\nHaga click en el enlace siguiente para activar su cuenta.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nSi usted no solicitó este correo, por favor ignorelo."], 'recoverUser' => ["Recuperacion de Usuario", "Siga a este enlace para ingresar.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nSi usted no solicitó este correo, por favor ignorelo."], @@ -1028,9 +1029,6 @@ $lang = array( 'enabledByQDesc'=> "Para aceptar esta misión debes haber tener activa alguna de estas misiones", 'gainsDesc' => "Cuando completes esta misión ganarás", 'theTitle' => 'el título "%s"', - 'mailDelivery' => "Usted recibirá esta carta%s%s", - 'mailBy' => ' del %s', - 'mailIn' => " después de %s", 'unavailable' => "Esta misión fue marcada como obsoleta y no puede ser obtenida o completada.", 'experience' => "experiencia", 'expConvert' => "(o %s si se completa al nivel %d)", @@ -1042,7 +1040,6 @@ $lang = array( 'spellLearn' => "Aprenderás", 'bonusTalents' => "%d |4punto:puntos; de talento", 'spellDisplayed'=> ' (mostrando %s)', - 'attachment' => "Adjunto", 'questInfo' => array( 0 => "Normal", 1 => "Élite", 21 => "Vida", 41 => "JcJ", 62 => "Banda", 81 => "Mazmorra", 82 => "Evento del mundo", 83 => "Legendaria", 84 => "Escolta", 85 => "Heroica", 88 => "Banda (10)", 89 => "Banda (25)" @@ -1159,6 +1156,16 @@ $lang = array( "Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Mi Lista de Reproducción" ) ), + 'mail' => array( + 'notFound' => "This mail doesn't exist.", + 'attachment' => "Adjunto", + 'mailDelivery' => "Usted recibirá esta carta%s%s", + 'mailBy' => ' del %s', + 'mailIn' => " después de %s", + 'delay' => "Delay", + 'sender' => "Sender", + 'untitled' => "Untitled Mail" + ), 'pet' => array( 'notFound' => "Esta familia de mascotas no existe.", 'exotic' => "Exótica", diff --git a/localization/locale_frfr.php b/localization/locale_frfr.php index 8a51c68b..d5dd6ba4 100644 --- a/localization/locale_frfr.php +++ b/localization/locale_frfr.php @@ -236,6 +236,8 @@ $lang = array( 'items' => "Objets", 'itemset' => "ensemble d'objets", 'itemsets' => "Ensembles d'objets", + 'mail' => "mail", + 'mails' => "Mails", 'mechanic' => "Mécanique", 'mechAbbr' => "Mécan.", 'meetingStone' => "Pierre de rencontre", @@ -783,9 +785,8 @@ $lang = array( 'comments' => "Commentaires", 'screenshots' => "Captures d'écran", 'videos' => "Vidéos", - 'posts' => "Messages sur le forum" - ), - 'mail' => array( + 'posts' => "Messages sur le forum", + // user mail 'tokenExpires' => "This token expires in %s.", 'accConfirm' => ["Activation de compte", "Bienvenue sur ".CFG_NAME_SHORT."!\r\n\r\nCliquez sur le lien ci-dessous pour activer votre compte.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nSi vous n'avez pas demandé cet email, ignorez le."], 'recoverUser' => ["Récupération d'utilisateur", "Suivez ce lien pour vous connecter.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nSi vous n'avez pas demandé cet email, ignorez le."], @@ -1028,9 +1029,6 @@ $lang = array( 'enabledByQDesc'=> "Vous pouvez faire cette quête seulement quand cette quête est active", 'gainsDesc' => "Lors de l'achèvement de cette quête vous gagnerez", 'theTitle' => '"%s"', // empty on purpose! - 'mailDelivery' => "Vous recevrez cette lettre%s%s", - 'mailBy' => ' de %s', - 'mailIn' => " après %s", 'unavailable' => "Cette quête est marquée comme obsolète et ne peut être obtenue ou accomplie.", 'experience' => "points d'expérience", 'expConvert' => "(ou %s si completé au niveau %d)", @@ -1042,7 +1040,6 @@ $lang = array( 'spellLearn' => "Vous apprendrez", 'bonusTalents' => "%d |4point:points; de talent", 'spellDisplayed'=> ' (%s affichés)', - 'attachment' => "[Attachment]", 'questInfo' => array( 0 => "Standard", 1 => "Groupe", 21 => "Vie", 41 => "JcJ", 62 => "Raid", 81 => "Donjon", 82 => "Évènement mondial", 83 => "Légendaire", 84 => "Escorte", 85 => "Héroïque", 88 => "Raid (10)", 89 => "Raid (25)" @@ -1159,6 +1156,16 @@ $lang = array( "Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Ma playlist" ) ), + 'mail' => array( + 'notFound' => "This mail doesn't exist.", + 'attachment' => "[Attachment]", + 'mailDelivery' => "Vous recevrez cette lettre%s%s", + 'mailBy' => ' de %s', + 'mailIn' => " après %s", + 'delay' => "Delay", + 'sender' => "Sender", + 'untitled' => "Untitled Mail" + ), 'pet' => array( 'notFound' => "Cette famille de familiers n'existe pas.", 'exotic' => "Exotique", diff --git a/localization/locale_ruru.php b/localization/locale_ruru.php index 67f02d23..ae6a9e08 100644 --- a/localization/locale_ruru.php +++ b/localization/locale_ruru.php @@ -236,6 +236,8 @@ $lang = array( 'items' => "Предметы", 'itemset' => "комплект", 'itemsets' => "Комплекты", + 'mail' => "mail", + 'mails' => "Mails", 'mechanic' => "Механика", 'mechAbbr' => "Механика", 'meetingStone' => "Камень встреч", @@ -783,9 +785,8 @@ $lang = array( 'comments' => "Комментарии", 'screenshots' => "Скриншоты", 'videos' => "Видео", - 'posts' => "Сообщений на форумах" - ), - 'mail' => array( + 'posts' => "Сообщений на форумах", + // user mail 'tokenExpires' => "This token expires in %s.", 'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."], 'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."], @@ -1028,9 +1029,6 @@ $lang = array( 'enabledByQDesc'=> "Вы можете получить это задание, только когда эти задания доступны", 'gainsDesc' => "По завершении этого задания, вы получите", 'theTitle' => '"%s"', // empty on purpose! - 'mailDelivery' => "Вы получите это письмо%s%s", - 'mailBy' => ' от %s', - 'mailIn' => " через %s", 'unavailable' => "пометили это задание как устаревшее — его нельзя получить или выполнить.", 'experience' => "опыта", 'expConvert' => "(или %s на %d-м уровне)", @@ -1042,7 +1040,6 @@ $lang = array( 'spellLearn' => "Вы изучите", 'bonusTalents' => "%d |4очко талантов:очка талантов:очков талантов;", 'spellDisplayed'=> ' (показано: %s)', - 'attachment' => "[Attachment]", 'questInfo' => array( 0 => "Обычный", 1 => "Группа", 21 => "Жизнь", 41 => "PvP", 62 => "Рейд", 81 => "Подземелье", 82 => "Игровое событие", 83 => "Легенда", 84 => "Сопровождение", 85 => "Героическое", 88 => "Рейд (10)", 89 => "Рейд (25)" @@ -1159,6 +1156,16 @@ $lang = array( "Narration Music", "Narration", 50 => "Zone Ambience", 52 => "Emitters", 53 => "Vehicles", 1000 => "Мой плейлист" ) ), + 'mail' => array( + 'notFound' => "This mail doesn't exist.", + 'attachment' => "[Attachment]", + 'mailDelivery' => "Вы получите это письмо%s%s", + 'mailBy' => ' от %s', + 'mailIn' => " через %s", + 'delay' => "Delay", + 'sender' => "Sender", + 'untitled' => "Untitled Mail" + ), 'pet' => array( 'notFound' => "Такой породы питомцев не существует.", 'exotic' => "Экзотический", diff --git a/localization/locale_zhcn.php b/localization/locale_zhcn.php index af1fc7e5..3fae88a1 100644 --- a/localization/locale_zhcn.php +++ b/localization/locale_zhcn.php @@ -236,6 +236,8 @@ $lang = array( 'items' => "物品", 'itemset' => "套装", 'itemsets' => "套装", + 'mail' => "mail", + 'mails' => "Mails", 'mechanic' => "机制", 'mechAbbr' => "机制", 'meetingStone' => "集合石", @@ -783,9 +785,8 @@ $lang = array( 'comments' => "评论", 'screenshots' => "截图", 'videos' => "视频", - 'posts' => "Forum posts" - ), - 'mail' => array( + 'posts' => "Forum posts", + // user mail 'tokenExpires' => "此令牌将在%s过期。", 'accConfirm' => ["Account Confirmation", "Welcome to ".CFG_NAME_SHORT."!\r\n\r\nClick the Link below to activate your account.\r\n\r\n".HOST_URL."?account=signup&token=%s\r\n\r\nIf you did not request this mail simply ignore it."], 'recoverUser' => ["User Recovery", "Follow this link to log in.\r\n\r\n".HOST_URL."?account=signin&token=%s\r\n\r\nIf you did not request this mail simply ignore it."], @@ -1028,9 +1029,6 @@ $lang = array( 'enabledByQDesc'=> "只有当这些任务中的一个活跃时,这个任务才可用", 'gainsDesc' => "完成这个任务后,你将获得", 'theTitle' => '头衔 "%s"', - 'mailDelivery' => "你会收到这封信%s%s", - 'mailBy' => '由%s所写', - 'mailIn' => " after %s", 'unavailable' => "这项任务已被标记为过时,无法获得或完成。", 'experience' => "经验", 'expConvert' => "(或%s如果在等级%d完成)", @@ -1042,7 +1040,6 @@ $lang = array( 'spellLearn' => "你将学会", 'bonusTalents' => "%d天赋|4点数:点数;", 'spellDisplayed'=> ' (%s is displayed)', - 'attachment' => "附件", 'questInfo' => array( 0 => "普通", 1 => "组队", 21 => "职业", 41 => "PvP", 62 => "团队", 81 => "地下城", 82 => "世界事件", 83 => "传说", 84 => "护送", 85 => "英雄", 88 => "团队(10)", 89 => "团队(25)" @@ -1159,6 +1156,16 @@ $lang = array( "叙事音乐", "叙事", 50 => "区域气氛", 52 => "发射器", 53 => "载具", 1000 => "我的播放列表" ) ), + 'mail' => array( + 'notFound' => "This mail doesn't exist.", + 'attachment' => "附件", + 'mailDelivery' => 'You will receive this letter%s%s', // "你会收到这封信%s%s", + 'mailBy' => '由%s所写', + 'mailIn' => " after %s", + 'delay' => "Delay", + 'sender' => "Sender", + 'untitled' => "Untitled Mail" + ), 'pet' => array( 'notFound' => "这个宠物家族不存在。", 'exotic' => "异域的", diff --git a/pages/account.php b/pages/account.php index 707147f0..a95ef3e0 100644 --- a/pages/account.php +++ b/pages/account.php @@ -433,7 +433,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup ); if (!$ok) return Lang::main('intError'); - else if ($_ = $this->sendMail(Lang::mail('accConfirm', 0), sprintf(Lang::mail('accConfirm', 1), $token), CFG_ACC_CREATE_SAVE_DECAY)) + else if ($_ = $this->sendMail(Lang::user('accConfirm', 0), sprintf(Lang::user('accConfirm', 1), $token), CFG_ACC_CREATE_SAVE_DECAY)) { if ($id = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE token = ?', $token)) Util::gainSiteReputation($id, SITEREP_ACTION_REGISTER); @@ -454,7 +454,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup return $_; // send recovery mail - return $this->sendMail(Lang::mail('resetPass', 0), sprintf(Lang::mail('resetPass', 1), $token), CFG_ACC_RECOVERY_DECAY); + return $this->sendMail(Lang::user('resetPass', 0), sprintf(Lang::user('resetPass', 1), $token), CFG_ACC_RECOVERY_DECAY); } private function doResetPass() @@ -486,7 +486,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup return $_; // send recovery mail - return $this->sendMail(Lang::mail('recoverUser', 0), sprintf(Lang::mail('recoverUser', 1), $token), CFG_ACC_RECOVERY_DECAY); + return $this->sendMail(Lang::user('recoverUser', 0), sprintf(Lang::user('recoverUser', 1), $token), CFG_ACC_RECOVERY_DECAY); } private function initRecovery($type, $delay, &$token) @@ -508,7 +508,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup { // send recovery mail $subj = CFG_NAME_SHORT.Lang::main('colon') . $subj; - $msg .= "\r\n\r\n".sprintf(Lang::mail('tokenExpires'), Util::formatTime($delay * 1000))."\r\n"; + $msg .= "\r\n\r\n".sprintf(Lang::user('tokenExpires'), Util::formatTime($delay * 1000))."\r\n"; $header = 'From: '.CFG_CONTACT_EMAIL . "\r\n" . 'Reply-To: '.CFG_CONTACT_EMAIL . "\r\n" . 'X-Mailer: PHP/' . phpversion(); diff --git a/pages/achievement.php b/pages/achievement.php index a8929bf9..6c2b9b1c 100644 --- a/pages/achievement.php +++ b/pages/achievement.php @@ -572,12 +572,13 @@ class AchievementPage extends GenericPage if ($_ = $this->subject->getField('mailTemplate')) { - $letter = DB::Aowow()->selectRow('SELECT * FROM ?_mailtemplate WHERE id = ?d', $_); + $letter = DB::Aowow()->selectRow('SELECT * FROM ?_mails WHERE id = ?d', $_); if (!$letter) return []; $reqCss = true; $mail = array( + 'id' => $_, 'delay' => null, 'sender' => null, 'attachments' => [], @@ -589,6 +590,7 @@ class AchievementPage extends GenericPage { $reqCss = true; $mail = array( + 'id' => -$this->typeId, 'delay' => null, 'sender' => null, 'attachments' => [], @@ -598,7 +600,7 @@ class AchievementPage extends GenericPage } if ($_ = CreatureList::getName($this->subject->getField('sender'))) - $mail['sender'] = sprintf(Lang::quest('mailBy'), $this->subject->getField('sender'), $_); + $mail['sender'] = sprintf(Lang::mail('mailBy'), $this->subject->getField('sender'), $_); return $mail; } diff --git a/pages/genericPage.class.php b/pages/genericPage.class.php index 28ab7ca7..b772b679 100644 --- a/pages/genericPage.class.php +++ b/pages/genericPage.class.php @@ -213,6 +213,7 @@ class GenericPage 'icongallery' => ['template' => 'icongallery', 'id' => 'icons', 'parent' => 'lv-generic', 'data' => [] ], 'item' => ['template' => 'item', 'id' => 'items', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_items' ], 'itemset' => ['template' => 'itemset', 'id' => 'itemsets', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_itemsets' ], + 'mail' => ['template' => 'mail', 'id' => 'mails', 'parent' => 'lv-generic', 'data' => [] ], 'model' => ['template' => 'model', 'id' => 'gallery', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_gallery' ], 'object' => ['template' => 'object', 'id' => 'objects', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_objects' ], 'pet' => ['template' => 'pet', 'id' => 'hunter-pets', 'parent' => 'lv-generic', 'data' => [], 'name' => '$LANG.tab_pets' ], diff --git a/pages/mail.php b/pages/mail.php new file mode 100644 index 00000000..a827d4b3 --- /dev/null +++ b/pages/mail.php @@ -0,0 +1,168 @@ +typeId = intVal($id); + + $this->subject = new MailList(array(['id', $this->typeId])); + + if ($this->subject->error) + $this->notFound(lang::game('mail'), Lang::mail('notFound')); + + $this->extendGlobalData($this->subject->getJSGlobals()); + + $this->name = Util::ucFirst($this->subject->getField('subject', true)); + if (!$this->name) + $this->name = Lang::mail('untitled'); + } + + protected function generateContent() + { + /***********/ + /* Infobox */ + /***********/ + + $infobox = []; + + // sender + delay + if ($this->typeId < 0) // def. achievement + { + if ($npcId = DB::World()->selectCell('SELECT Sender FROM achievement_reward WHERE ID = ?d', -$this->typeId)) + { + $infobox[] = Lang::mail('sender').Lang::main('colon').'[npc='.$npcId.']'; + $this->extendGlobalIds(TYPE_NPC, $npcId); + } + } + else if ($mlr = DB::World()->selectRow('SELECT * FROM mail_level_reward WHERE mailTemplateId = ?d', $this->typeId)) // level rewards + { + if ($mlr['level']) + $infobox[] = Lang::game('level').Lang::main('colon').$mlr['level']; + + if ($r = Lang::getRaceString($mlr['raceMask'], $rId, $_, false)) + { + $infobox[] = Lang::game('races').Lang::main('colon').$r; + $this->extendGlobalIds(TYPE_RACE, $rId); + } + + $infobox[] = Lang::mail('sender').Lang::main('colon').'[npc='.$mlr['senderEntry'].']'; + $this->extendGlobalIds(TYPE_NPC, $mlr['senderEntry']); + } + else // achievement or quest + { + if ($q = DB::Aowow()->selectRow('SELECT id, rewardMailDelay FROM ?_quests WHERE rewardMailTemplateId = ?d', $this->typeId)) + { + if ($npcId= DB::World()->selectCell('SELECT RewardMailSenderEntry FROM quest_mail_sender WHERE QuestId = ?d', $q['id'])) + { + $infobox[] = Lang::mail('sender').Lang::main('colon').'[npc='.$npcId.']'; + $this->extendGlobalIds(TYPE_NPC, $npcId); + } + else if ($npcId = DB::Aowow()->selectCell('SELECT typeId FROM ?_quests_startend WHERE questId = ?d AND type = ?d AND method & ?d', $q['id'], TYPE_NPC, 0x2)) + { + $infobox[] = Lang::mail('sender').Lang::main('colon').'[npc='.$npcId.']'; + $this->extendGlobalIds(TYPE_NPC, $npcId); + } + + if ($q['rewardMailDelay'] > 0) + $infobox[] = Lang::mail('delay').Lang::main('colon').''.Util::formatTime($q['rewardMailDelay'] * 1000); + } + else if ($npcId = DB::World()->selectCell('SELECT Sender FROM achievement_reward WHERE MailTemplateId = ?d', $this->typeId)) + { + $infobox[] = Lang::mail('sender').Lang::main('colon').'[npc='.$npcId.']'; + $this->extendGlobalIds(TYPE_NPC, $npcId); + } + } + + /****************/ + /* Main Content */ + /****************/ + + $this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : ''; + $this->redButtons = array( + BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId], + BUTTON_WOWHEAD => false + ); + + $this->extraText = Util::parseHtmlText($this->subject->getField('text', true), true); + + + /**************/ + /* Extra Tabs */ + /**************/ + + // tab: attachment + if ($itemId = $this->subject->getField('attachment')) + { + $attachment = new ItemList(array(['id', $itemId])); + if (!$attachment->error) + { + $this->extendGlobalData($attachment->getJsGlobals()); + $this->lvTabs[] = [ItemList::$brickFile, array( + 'data' => array_values($attachment->getListviewData()), + 'name' => Lang::mail('attachment'), + 'id' => 'attachment' + )]; + } + } + + + if ($this->typeId < 0 || // used by: achievement + ($acvId = DB::World()->selectCell('SELECT ID FROM achievement_reward WHERE MailTemplateId = ?d', $this->typeId))) + { + $ubAchievements = new AchievementList(array(['id', $this->typeId < 0 ? -$this->typeId : $acvId])); + if (!$ubAchievements->error) + { + $this->extendGlobalData($ubAchievements->getJsGlobals()); + $this->lvTabs[] = [AchievementList::$brickFile, array( + 'data' => array_values($ubAchievements->getListviewData()), + 'id' => 'used-by-achievement' + )]; + } + } + else if ($npcId = DB::World()->selectCell('SELECT ID FROM achievement_reward WHERE MailTemplateId = ?d', $this->typeId)) + { + $infobox[] = '[Sender]: [npc='.$npcId.']'; + $this->extendGlobalIds(TYPE_NPC, $npcId); + } + + else // used by: quest + { + $ubQuests = new QuestList(array(['rewardMailTemplateId', $this->typeId])); + if (!$ubQuests->error) + { + $this->extendGlobalData($ubQuests->getJsGlobals()); + $this->lvTabs[] = [QuestList::$brickFile, array( + 'data' => array_values($ubQuests->getListviewData()), + 'id' => 'used-by-quest' + )]; + } + } + } + + protected function generateTitle() + { + array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('mail'))); + } + + protected function generatePath() { } +} + +?> diff --git a/pages/mails.php b/pages/mails.php new file mode 100644 index 00000000..9644a55d --- /dev/null +++ b/pages/mails.php @@ -0,0 +1,46 @@ +name = Util::ucFirst(Lang::game('mails')); + } + + protected function generateContent() + { + $tabData = []; + $mails = new MailList(); + if (!$mails->error) + $tabData['data'] = array_values($mails->getListviewData()); + + $this->extendGlobalData($mails->getJsGlobals()); + + $this->lvTabs[] = ['mail', $tabData, 'mail']; + } + + protected function generateTitle() + { + array_unshift($this->title, $this->name); + } + + protected function generatePath() { } +} + +?> diff --git a/pages/quest.php b/pages/quest.php index b7b5e2c4..7b498657 100644 --- a/pages/quest.php +++ b/pages/quest.php @@ -1226,10 +1226,11 @@ class QuestPage extends GenericPage if ($rmtId = $this->subject->getField('rewardMailTemplateId')) { $delay = $this->subject->getField('rewardMailDelay'); - $letter = DB::Aowow()->selectRow('SELECT * FROM ?_mailtemplate WHERE id = ?d', $rmtId); + $letter = DB::Aowow()->selectRow('SELECT * FROM ?_mails WHERE id = ?d', $rmtId); $mail = array( - 'delay' => $delay ? sprintf(Lang::quest('mailIn'), Util::formatTime($delay * 1000)) : null, + 'id' => $rmtId, + 'delay' => $delay ? sprintf(Lang::mail('mailIn'), Util::formatTime($delay * 1000)) : null, 'sender' => null, 'attachments' => [], 'text' => $letter ? Util::parseHtmlText(Util::localizedString($letter, 'text')) : null, @@ -1245,7 +1246,7 @@ class QuestPage extends GenericPage $senderTypeId = $se['typeId']; if ($ti = CreatureList::getName($senderTypeId)) - $mail['sender'] = sprintf(Lang::quest('mailBy'), $senderTypeId, $ti); + $mail['sender'] = sprintf(Lang::mail('mailBy'), $senderTypeId, $ti); // while mail attachemnts are handled as loot, it has no variance. Always 100% chance, always one item. $mailLoot = new Loot(); diff --git a/setup/db_structure.sql b/setup/db_structure.sql index c201facc..d27143b6 100644 --- a/setup/db_structure.sql +++ b/setup/db_structure.sql @@ -1583,13 +1583,13 @@ CREATE TABLE `aowow_loot_link` ( /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table `aowow_mailtemplate` +-- Table structure for table `aowow_mails` -- -DROP TABLE IF EXISTS `aowow_mailtemplate`; +DROP TABLE IF EXISTS `aowow_mails`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `aowow_mailtemplate` ( +CREATE TABLE `aowow_mails` ( `id` smallint(5) unsigned NOT NULL, `subject_loc0` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, `subject_loc2` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, @@ -1597,12 +1597,12 @@ CREATE TABLE `aowow_mailtemplate` ( `subject_loc4` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, `subject_loc6` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, `subject_loc8` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, - `text_loc0` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, - `text_loc2` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, - `text_loc3` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, - `text_loc4` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, - `text_loc6` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, - `text_loc8` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc0` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc2` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc3` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc4` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc6` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc8` text COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/setup/tools/CLISetup.class.php b/setup/tools/CLISetup.class.php index 5991f827..25678a31 100644 --- a/setup/tools/CLISetup.class.php +++ b/setup/tools/CLISetup.class.php @@ -198,13 +198,13 @@ class CLISetup $dbc = new DBC($name, ['temporary' => self::$tmpDBC]); if ($dbc->error) { - CLI::write('SqlGen::generate() - required DBC '.$name.'.dbc not found!', CLI::LOG_ERROR); + CLI::write('CLISetup::loadDBC() - required DBC '.$name.'.dbc not found!', CLI::LOG_ERROR); return false; } if (!$dbc->readFile()) { - CLI::write('SqlGen::generate() - DBC '.$name.'.dbc could not be written to DB!', CLI::LOG_ERROR); + CLI::write('CLISetup::loadDBC() - DBC '.$name.'.dbc could not be written to DB!', CLI::LOG_ERROR); return false; } diff --git a/setup/tools/clisetup/firstrun.func.php b/setup/tools/clisetup/firstrun.func.php index d26a5513..ef305873 100644 --- a/setup/tools/clisetup/firstrun.func.php +++ b/setup/tools/clisetup/firstrun.func.php @@ -24,9 +24,9 @@ function firstrun() /****************/ $steps = array( - // clisetup/, params, test script result, introText, errorText + // clisetup, params, test function, introText, errorText ['dbconfig', null, 'testDB', 'Please enter your database credentials.', 'could not establish connection to:'], - ['siteconfig', null, 'testSelf', 'SITE_HOST and STATIC_HOST '.CLI::bold('must').' be set. Also enable FORCE_SSL if needed. You may also want to change other variables such as NAME, NAME_SHORT OR LOCALES.', 'could not access:'], + ['siteconfig', null, 'testSelf', 'SITE_HOST and STATIC_HOST '.CLI::bold('must').' be set. Also enable FORCE_SSL if needed. You may also want to change other variables such as NAME, NAME_SHORT or LOCALES.', 'could not access:'], // sql- and build- stuff here ['SqlGen::generate', 'achievementcategory', null, null, null], ['SqlGen::generate', 'achievementcriteria', null, null, null], @@ -37,7 +37,7 @@ function firstrun() ['SqlGen::generate', 'itemlimitcategory', null, null, null], ['SqlGen::generate', 'itemrandomproppoints', null, null, null], ['SqlGen::generate', 'lock', null, null, null], - ['SqlGen::generate', 'mailtemplate', null, null, null], + ['SqlGen::generate', 'mails', null, null, null], ['SqlGen::generate', 'scalingstatdistribution', null, null, null], ['SqlGen::generate', 'scalingstatvalues', null, null, null], ['SqlGen::generate', 'spellfocusobject', null, null, null], @@ -184,7 +184,7 @@ function firstrun() if ($resp == 301 || $resp == 302) { CLI::write('self test received status '.CLI::bold($resp).' (page moved) for '.$conf.', pointing to: '.$protocol.$host.$testFile, CLI::LOG_WARN); - $inp = ['x' => ['should '.CLI::bold($conf).' be set to '.CLI::bold($host).' and force_ssl be updated?', true, '/y|n/i']]; + $inp = ['x' => ['should '.CLI::bold($conf).' be set to '.CLI::bold($host).' and force_ssl be updated? (y/n)', true, '/y|n/i']]; if (!CLI::readInput($inp, true) || !$inp || strtolower($inp['x']) == 'n') $error[] = ' * could not access '.$protocol.$host.$testFile.' ['.$resp.']'; else diff --git a/setup/tools/filegen/simpleImg.func.php b/setup/tools/filegen/simpleImg.func.php index 63bce8dd..25221feb 100644 --- a/setup/tools/filegen/simpleImg.func.php +++ b/setup/tools/filegen/simpleImg.func.php @@ -217,7 +217,7 @@ if (!CLI) if (isset(FileGen::$cliOpts['loadingscreens'])) $groups[] = 11; - // filter by pasaed options + // filter by passed options if (!$groups) // by default do not generate loadingscreens unset($paths[11]); else @@ -373,8 +373,8 @@ if (!CLI) /* ready for some major bullshitery? well, here it comes anyway! the class-icon tile [idx: 4] isn't 64x64 but 63x64 .. the right side border is 1px short - so if we don't watch out, the icons start to shift over and show the borderi - also the icon border is displayced by 1px + so if we don't watch out, the icons start to shift over and show the border + also the icon border is displaced by 1px */ $from = array( 'x' => $borderOffset + 1 + ($tileSize - ($i == 4 ? 1 : 0)) * $x, diff --git a/setup/tools/sqlgen/mailtemplate.func.php b/setup/tools/sqlgen/mailtemplate.func.php index 833a19f8..cb5ad3b7 100644 --- a/setup/tools/sqlgen/mailtemplate.func.php +++ b/setup/tools/sqlgen/mailtemplate.func.php @@ -9,10 +9,52 @@ if (!CLI) SqlGen::register(new class extends SetupScript { - use TrDBCcopy; + protected $command = 'mails'; - protected $command = 'mailtemplate'; protected $dbcSourceFiles = ['mailtemplate']; + + public function generate(array $ids = []) : bool + { + DB::Aowow()->query('TRUNCATE aowow_mails'); + + // copy data over from dbc + DB::Aowow()->query('INSERT INTO ?_mails SELECT *, 0 FROM dbc_mailtemplate'); + + CLI::write('SqlGen::generate() - merging achievement_reward into aowow_mails'); + + $acvMail = DB::World()->select(' + SELECT + -ar.ID, + 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.Text, "") AS t0, IFNULL(arl2.Text, "") AS t2, IFNULL(arl3.Text, "") AS t3, IFNULL(arl4.Text, "") AS t4, IFNULL(arl6.Text, "") AS t6, IFNULL(arl8.Text, "") AS t8, + ItemID + FROM + achievement_reward ar + LEFT JOIN + achievement_reward_locale arl2 ON ar.ID = arl2.ID AND arl2.Locale = "frFR" + LEFT JOIN + achievement_reward_locale arl3 ON ar.ID = arl3.ID AND arl3.Locale = "deDE" + LEFT JOIN + achievement_reward_locale arl4 ON ar.ID = arl4.ID AND arl4.Locale = "zhCN" + LEFT JOIN + achievement_reward_locale arl6 ON ar.ID = arl6.ID AND arl6.Locale = "esES" + LEFT JOIN + achievement_reward_locale arl8 ON ar.ID = arl8.ID AND arl8.Locale = "ruRU" + WHERE + ar.MailTemplateID = 0 AND ar.Text <> "" + '); + + DB::Aowow()->query('INSERT INTO aowow_mails VALUES (?a)', array_values($acvMail)); + + CLI::write('SqlGen::generate() - merging mail_loot_template into aowow_mails'); + + // assume mails to only contain one single item, wich works for an unmodded installation + $mlt = DB::World()->selectCol('SELECT Entry AS ARRAY_KEY, Item FROM mail_loot_template'); + foreach ($mlt as $k => $v) + DB::Aowow()->query('UPDATE ?_mails SET attachment = ?d WHERE id = ?d', $v, $k); + + return true; + } }); ?> diff --git a/setup/tools/sqlgen/source.func.php b/setup/tools/sqlgen/source.func.php index f7eec211..3f51dea3 100644 --- a/setup/tools/sqlgen/source.func.php +++ b/setup/tools/sqlgen/source.func.php @@ -1070,7 +1070,7 @@ SqlGen::register(new class extends SetupScript continue; $effects = $tSpells[$spellId]; - $trainerId = $npc['entry'] > 200000 || $npc['qty'] > 1 ? null : $npc['entry']; + $trainerId = $npc['entry'] > 200000 || $npc['qty'] > 1 ? 0 : $npc['entry']; $triggered = false; for ($i = 1; $i <= 3; $i++) diff --git a/setup/updates/1581549222_01.sql b/setup/updates/1581549222_01.sql new file mode 100644 index 00000000..2bce6347 --- /dev/null +++ b/setup/updates/1581549222_01.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS `aowow_mailtemplate`; +DROP TABLE IF EXISTS `aowow_mails`; + +CREATE TABLE `aowow_mails` ( + `id` smallint(5) unsigned NOT NULL, + `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, + `subject_loc4` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, + `subject_loc6` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, + `subject_loc8` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc0` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc2` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc3` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc4` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc6` text COLLATE utf8mb4_unicode_ci NOT NULL, + `text_loc8` text COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +UPDATE aowow_dbversion SET `sql` = CONCAT(IFNULL(`sql`, ''), ' mails'); diff --git a/static/js/global.js b/static/js/global.js index 0d829a10..c79fa708 100644 --- a/static/js/global.js +++ b/static/js/global.js @@ -22647,7 +22647,8 @@ var g_types = { 29: 'icon', 501: 'emote', 502: 'enchantment', - 503: 'areatrigger' + 503: 'areatrigger', + 504: 'mail' }; // Items diff --git a/static/js/locale_dede.js b/static/js/locale_dede.js index 667db5d7..01033015 100644 --- a/static/js/locale_dede.js +++ b/static/js/locale_dede.js @@ -918,7 +918,8 @@ var mn_database = [ [, "Anderes"], [19,"Klänge","?sounds",mn_sounds], [31, "Icons", "?icons", mn_icons], - [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}] // aowow - custom + [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}], // aowow - custom + [103, 'Briefe', '?mails'] // aowow - custom ]; var mn_tools = [ [0,"Talentrechner","?talent",mn_talentCalc], @@ -3357,7 +3358,9 @@ var LANG = { 19: ["Klang", "Klang", "Klänge", "Klänge"], 29: ["Icon", "Icon", "Icons", "Icons"], 501: ["Emote", "Emote", "Emotes", "Emotes"], - 502: ["Verzauberung", "Verzauberung", "Verzauberungen", "Verzauberungen"] + 502: ["Verzauberung", "Verzauberung", "Verzauberungen", "Verzauberungen"], + 503: ["Areatrigger", "Areatrigger", "Areatrigger", "Areatrigger"], + 504: ["Brief", "Brief", "Briefe", "Briefe"] }, timeunitssg: ["Jahr", "Monat", "Woche", "Tag", "Stunde", "Minute", "Sekunde"], diff --git a/static/js/locale_enus.js b/static/js/locale_enus.js index c6fea9b4..2721f441 100644 --- a/static/js/locale_enus.js +++ b/static/js/locale_enus.js @@ -964,7 +964,8 @@ var mn_database = [ [, "Other"], [31, "Icons", "?icons", mn_icons], [19,"Sounds","?sounds",mn_sounds], - [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}] // aowow - custom + [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}], // aowow - custom + [103, 'Mails', '?mails'] // aowow - custom ]; var mn_tools = [ [0,"Talent Calculator","?talent",mn_talentCalc], @@ -3405,7 +3406,9 @@ var LANG = { 19: ["Sound", "sound", "Sounds", "sounds"], 29: ["Icon", "icon", "Icons", "icons"], 501: ["Emote", "emote", "Emotes", "emotes"], - 502: ["Enchantment", "enchantment", "Enchantments", "enchantments"] + 502: ["Enchantment", "enchantment", "Enchantments", "enchantments"], + 503: ["Areatrigger", "areatrigger", "Areatriggers", "areatriggers"], + 504: ["Mail", "mail", "Mails", "mails"] }, timeunitssg: ["year", "month", "week", "day", "hour", "minute", "second"], diff --git a/static/js/locale_eses.js b/static/js/locale_eses.js index 31338d61..d151340e 100644 --- a/static/js/locale_eses.js +++ b/static/js/locale_eses.js @@ -917,7 +917,9 @@ var mn_database = [ [6,"Zonas","?zones",mn_zones], [, "Otros"], [31, "Iconos", "?icons", mn_icons], - [19,"Sonidos","?sounds",mn_sounds] + [19,"Sonidos","?sounds",mn_sounds], + [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}], // aowow - custom + [103, 'Mails', '?mails'] // aowow - custom ]; var mn_tools = [ [0,"Calculadora de talentos","?talent",mn_talentCalc], @@ -3357,7 +3359,9 @@ var LANG = { 19: ["Sonido", "sonido", "Sonidos", "sonidos"], 29: ["Icono", "icono", "Iconos", "íconos"], 501: ["Emoción", "emoción", "Emociones", "emociones"], - 502: ["Encantamiento", "encantamiento", "Encantamientos", "encantamientos"] + 502: ["Encantamiento", "encantamiento", "Encantamientos", "encantamientos"], + 503: ["Areatrigger", "areatrigger", "Areatriggers", "areatriggers"], + 504: ["Mail", "mail", "Mails", "mails"] }, timeunitssg: ["año", "mes", "semana", "día", "hora", "minuto", "segundo"], diff --git a/static/js/locale_frfr.js b/static/js/locale_frfr.js index 48dd617e..d0a483df 100644 --- a/static/js/locale_frfr.js +++ b/static/js/locale_frfr.js @@ -917,7 +917,9 @@ var mn_database = [ [6,"Zones","?zones",mn_zones], [, "Autre"], [31, "Icônes", ":wowhead.com/icons", mn_icons], - [19,"Sons","?sounds", mn_sounds] + [19,"Sons","?sounds", mn_sounds], + [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}], // aowow - custom + [103, 'Mails', '?mails'] // aowow - custom ]; var mn_tools = [ [0,"Calculateur de talents","?talent",mn_talentCalc], @@ -3357,7 +3359,9 @@ var LANG = { 19: ["Son", "Son", "Sons", "Sons"], 29: ["Icône", "icône", "Icônes", "icônes"], 501: ["Emote", "emote", "Emotes", "emotes"], - 502: ["Enchantement", "enchantement", "Enchantements", "enchantements"] + 502: ["Enchantement", "enchantement", "Enchantements", "enchantements"], + 503: ["Areatrigger", "areatrigger", "Areatriggers", "areatriggers"], + 504: ["Mail", "mail", "Mails", "mails"] }, timeunitssg: ["année", "mois", "semaine", "jour", "heure", "minute", "seconde"], diff --git a/static/js/locale_ruru.js b/static/js/locale_ruru.js index 3081dcaf..8cd184d5 100644 --- a/static/js/locale_ruru.js +++ b/static/js/locale_ruru.js @@ -917,7 +917,9 @@ var mn_database = [ [6,"Местности","?zones",mn_zones], [, "Другое"], [31, "Иконки", ":wowhead.com/icons", mn_icons], - [19,"Звуки","?sounds",mn_sounds] + [19,"Звуки","?sounds",mn_sounds], + [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}], // aowow - custom + [103, 'Mails', '?mails'] // aowow - custom ]; var mn_tools = [ [0,"Расчёт талантов","?talent",mn_talentCalc], @@ -3357,7 +3359,9 @@ var LANG = { 19: ["Звук", "звук", "Звуки", "звуки"], 29: ["Иконка", "иконка", "Иконки", "иконки"], 501: ["Эмоция", "эмоция", "Эмоции", "эмоции"], - 502: ["Улучшение", "улучшение", "Улучшения", "улучшения"] + 502: ["Улучшение", "улучшение", "Улучшения", "улучшения"], + 503: ["Areatrigger", "areatrigger", "Areatriggers", "areatriggers"], + 504: ["Mail", "mail", "Mails", "mails"] }, timeunitssg: ["год", "месяц", "неделя", "день", "час", "минута", "секунда"], diff --git a/static/js/locale_zhcn.js b/static/js/locale_zhcn.js index c453253c..9aa7f046 100644 --- a/static/js/locale_zhcn.js +++ b/static/js/locale_zhcn.js @@ -610,7 +610,6 @@ var mn_spells = [ ]], [,"宠物"], [-6,"伙伴"], - [-5,""], [-5,"坐骑",,[ [1,"陆地坐骑"], [2,"飞行坐骑"], @@ -964,7 +963,9 @@ var mn_database = [ [6,"地区","?zones",mn_zones], [, "其他"], [31,"图标", "?icons", mn_icons], - [19,"声音","?sounds",mn_sounds] + [19,"声音","?sounds",mn_sounds], + [102, 'Areatrigger', '?areatriggers', mn_areatrigger, {requiredAccess: 1726}], // aowow - custom + [103, 'Mails', '?mails'] // aowow - custom ]; var mn_tools = [ [0,"天赋模拟器","?talent",mn_talentCalc], @@ -3405,7 +3406,9 @@ var LANG = { 19: ["声音", "音效", "声音", "声音"], 29: ["图标", "图标", "图标", "图标"], 501: ["表情", "表情", "表情", "表情"], - 502: ["附魔", "附魔", "附魔", "附魔"] + 502: ["附魔", "附魔", "附魔", "附魔"], + 503: ["Areatrigger", "areatrigger", "Areatriggers", "areatriggers"], + 504: ["Mail", "mail", "Mails", "mails"] }, timeunitssg: ["年", "月", "周", "天", "小时", "分钟", "秒"], diff --git a/template/bricks/mail.tpl.php b/template/bricks/mail.tpl.php index 8f7053f3..4e8cc3fe 100644 --- a/template/bricks/mail.tpl.php +++ b/template/bricks/mail.tpl.php @@ -3,7 +3,7 @@ if ($m = $this->mail): if (!isset($offset)) // in case we have multiple icons on the page (prominently quest-rewards) $offset = 0; - echo '

'.sprintf(Lang::quest('mailDelivery'), $m['sender'], $m['delay'])."

\n"; + echo '

'.sprintf(Lang::mail('mailDelivery'), $m['id'], $m['sender'], $m['delay'])."

\n"; if ($m['subject']): echo '
'.$m['subject']."
\n"; diff --git a/template/listviews/enchantment.tpl.php b/template/listviews/enchantment.tpl.php index 5b0a9b91..5d679b47 100644 --- a/template/listviews/enchantment.tpl.php +++ b/template/listviews/enchantment.tpl.php @@ -66,7 +66,7 @@ Listview.templates.enchantment = { if (!enchantment.spells) return null; // no spell - var spellId = $(enchantment.spells).first(); + var spellId = $(enchantment.spells).first()[0]; if (g_spells[spellId]) return g_spells[spellId]['name_' + Locale.getName()]; diff --git a/template/listviews/mail.tpl.php b/template/listviews/mail.tpl.php new file mode 100644 index 00000000..74acc7ec --- /dev/null +++ b/template/listviews/mail.tpl.php @@ -0,0 +1,97 @@ +Listview.templates.mail = { + sort: [1], + searchable: 1, + filtrable: 1, + + columns: [ + { + id: 'id', + name: 'ID', + width: '5%', + value: 'id', + compute: function(data, td) { + if (data.id) { + $WH.ae(td, $WH.ct(data.id)); + } + } + }, + { + id: 'subject', + name: LANG.subject, + type: 'text', + align: 'left', + value: 'subject', + compute: function(mail, td, tr) { + var wrapper = $WH.ce('div'); + + var a = $WH.ce('a'); + a.style.fontFamily = 'Verdana, sans-serif'; + a.href = this.getItemLink(mail); + if (!mail.subject){ + mail.subject = 'Untitled Mail' + a.className = 'q0'; + } + + $WH.ae(a, $WH.ct(mail.subject)); + $WH.ae(wrapper, a); + $WH.ae(td, wrapper); + }, + sortFunc: function(a, b, col) { + return $WH.strcmp(a.subject, b.subject); + }, + getVisibleText: function(mail) { + return mail.subject; + } + }, + { + id: 'body', + name: LANG.text, + type: 'text', + align: 'left', + value: 'body', + compute: function(mail, td, tr) { + td.innerText = mail.body; + }, + sortFunc: function(a, b, col) { + return $WH.strcmp(a.body, b.body); + }, + getVisibleText: function(mail) { + return mail.body; + } + }, + { + id: 'attachments', + name: 'Attachments', + type: 'text', + compute: function(mail, td) { + if (!mail.attachments.length) + return; + + mail.attachments.forEach(function(item, idx, arr) { + if (g_items && g_items[item]) { + i = Icon.create(g_items[item].icon, 0, false, '?item=' + item, 0, 0, false, false, true); + if (idx !== arr.length - 1) + i.style.paddingLeft = '5px'; + $WH.ae(td, i); + } + }); + }, + getVisibleText: function(mail) { + if (!mail.attachments.length) + return null; // no attachments + + var itemId = $(mail.attachments).first()[0]; + if (g_items && g_items[itemId]) + return g_items[itemId]['name_' + Locale.getName()]; + + return ''; // unk item + }, + sortFunc: function(a, b, col) { + return $WH.strcmp(this.getVisibleText(a), this.getVisibleText(b)); + } + } + ], + getItemLink: function(mail) { + return '?mail=' + mail.id; + } +} diff --git a/template/pages/detail-page-generic.tpl.php b/template/pages/detail-page-generic.tpl.php index 954f119d..13d7fb50 100644 --- a/template/pages/detail-page-generic.tpl.php +++ b/template/pages/detail-page-generic.tpl.php @@ -19,7 +19,7 @@ $this->brick('redButtons'); ?> - expansion) ? ' class="h1-icon">'.$this->name.'' : '>'.$this->name); ?> + expansion) ? ' class="h1-icon">'.Util::htmlEscape($this->name).'' : '>'.Util::htmlEscape($this->name)); ?> brick('article');