'_searchCharClass', self::MOD_RACE => '_searchCharRace', self::MOD_TITLE => '_searchTitle', self::MOD_WORLDEVENT => '_searchWorldEvent', self::MOD_CURRENCY => '_searchCurrency', self::MOD_ITEMSET => '_searchItemset', self::MOD_ITEM => '_searchItem', self::MOD_ABILITY => '_searchAbility', self::MOD_TALENT => '_searchTalent', self::MOD_GLYPH => '_searchGlyph', self::MOD_PROFICIENCY => '_searchProficiency', self::MOD_PROFESSION => '_searchProfession', self::MOD_COMPANION => '_searchCompanion', self::MOD_MOUNT => '_searchMount', self::MOD_CREATURE => '_searchCreature', self::MOD_QUEST => '_searchQuest', self::MOD_ACHIEVEMENT => '_searchAchievement', self::MOD_STATISTIC => '_searchStatistic', self::MOD_ZONE => '_searchZone', self::MOD_OBJECT => '_searchObject', self::MOD_FACTION => '_searchFaction', self::MOD_SKILL => '_searchSkill', self::MOD_PET => '_searchPet', self::MOD_CREATURE_ABILITY => '_searchCreatureAbility', self::MOD_SPELL => '_searchSpell', self::MOD_EMOTE => '_searchEmote', self::MOD_ENCHANTMENT => '_searchEnchantment', self::MOD_SOUND => '_searchSound' ); private array $jsgStore = []; private array $resultStore = []; private array $included = []; private array $excluded = []; private array $cndBase = ['AND']; private bool $idSearch = false; public array $invalid = []; public function __construct(private string $query, private int $moduleMask = -1, private int $maxResults = 500, private array $extraCnd = [], private array $extraOpts = []) { $this->tokenizeQuery(); $this->cndBase[] = $this->maxResults; // Exclude internal wow stuff if (!User::isInGroup(U_GROUP_EMPLOYEE)) $this->cndBase[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0]; } private function tokenizeQuery() : void { if (!$this->query) return; if (Util::checkNumeric($this->query, NUM_CAST_INT)) { $this->idSearch = true; $this->included[] = $this->query; return; } foreach (explode(' ', $this->query) as $raw) { $clean = str_replace(['\\', '%'], '', $raw); if (!$clean === '') continue; if ($clean[0] == '-') { if (mb_strlen($clean) < 4 && !Lang::getLocale()->isLogographic()) $this->invalid[] = mb_substr($raw, 1); else $this->excluded[] = mb_substr(str_replace('_', '\\_', $clean), 1); } else { if (mb_strlen($clean) < 3 && !Lang::getLocale()->isLogographic()) $this->invalid[] = $raw; else $this->included[] = str_replace('_', '\\_', $clean); } } } private function createLookup(array $fields = []) : array { if ($this->idSearch && $this->included) return ['id', $this->included]; if (!$this->included && !$this->excluded) return []; // default to name-field if (!$fields) $fields[] = 'name_loc'.Lang::getLocale()->value; $qry = []; foreach ($fields as $f) { $sub = []; foreach ($this->included as $i) $sub[] = [$f, '%'.$i.'%']; foreach ($this->excluded as $x) $sub[] = [$f, '%'.$x.'%', '!']; // single cnd? if (count($sub) > 1) array_unshift($sub, 'AND'); else $sub = $sub[0]; $qry[] = $sub; } // single cnd? if (count($qry) > 1) array_unshift($qry, 'OR'); else $qry = $qry[0]; return $qry; } public function canPerform() : bool { // has valid search terms or weights and selected modules return (($this->included || $this->extraOpts)) && $this->moduleMask; } public function perform() : \Generator { $shared = []; foreach (self::MODULES as $idx => $ref) { if (!($this->moduleMask & (1 << $idx))) continue; $this->resultStore[$idx] ??= $this->$ref($shared); if (!$this->resultStore[$idx]) continue; yield $idx => $this->resultStore[$idx]; } } public function getJSGlobals() : array { return $this->jsgStore; } /******************/ /* Search Modules */ /******************/ private function _searchCharClass() : ?array // 0 Classes: $moduleMask & 0x00000001 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $classes = new CharClassList($cnd, ['calcTotal' => true]); $data = $classes->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = ['data' => $data]; if ($classes->getMatches() > $this->maxResults) { // $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_', $classes->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, CharClassList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::CHR_CLASS, $classes->getMatches(), [], [], 'Class']; foreach ($classes->iterate() as $id => $__) { $result[$id] = $classes->getField('name', true); $osInfo[2][$id] = 'class_'.strToLower($classes->getField('fileString')); } return [$result, ...$osInfo]; } return null; } private function _searchCharRace() : ?array // 1 Races: $moduleMask & 0x00000002 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $races = new CharRaceList($cnd, ['calcTotal' => true]); $data = $races->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = ['data' => $data]; if ($races->getMatches() > $this->maxResults) { // $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_', $races->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, CharRaceList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::CHR_RACE, $races->getMatches(), [], [], 'Race']; foreach ($races->iterate() as $id => $__) { $result[$id] = $races->getField('name', true); $osInfo[2][$id] = 'race_'.strToLower($races->getField('fileString')).'_male'; } return [$result, ...$osInfo]; } return null; } private function _searchTitle() : ?array // 2 Titles: $moduleMask & 0x00000004 { $cnd = array_merge($this->cndBase, [$this->createLookup(['male_loc'.Lang::getLocale()->value, 'female_loc'.Lang::getLocale()->value])]); $titles = new TitleList($cnd, ['calcTotal' => true]); $data = $titles->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = ['data' => $data]; if ($titles->getMatches() > $this->maxResults) { // $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_', $titles->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, TitleList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::TITLE, $titles->getMatches(), [], [], 'Title']; foreach ($titles->iterate() as $id => $__) { $result[$id] = $titles->getField('male', true); $osInfo[2][$id] = $titles->getField('side'); } return [$result, ...$osInfo]; } return null; } private function _searchWorldEvent() : ?array // 3 World Events: $moduleMask & 0x00000008 { $cnd = array_merge($this->cndBase, array( array( 'OR', $this->createLookup(['h.name_loc'.Lang::getLocale()->value]), ['AND', $this->createLookup(['e.description']), ['e.holidayId', 0]] ) )); $wEvents = new WorldEventList($cnd, ['calcTotal' => true]); $data = $wEvents->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $wEvents->getJSGlobals()); // as allways: dates are updated in postCache-step $lvData = ['data' => $data]; if ($wEvents->getMatches() > $this->maxResults) { // $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_', $wEvents->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, WorldEventList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::WORLDEVENT, $wEvents->getMatches(), [], [], 'World Event']; foreach ($wEvents->iterate() as $id => $__) $result[$id] = $wEvents->getField('name', true); return [$result, ...$osInfo]; } return null; } private function _searchCurrency() : ?array // 4 Currencies $moduleMask & 0x0000010 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $money = new CurrencyList($cnd, ['calcTotal' => true]); $data = $money->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = ['data' => $data]; if ($money->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_currenciesfound', $money->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, CurrencyList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::CURRENCY, $money->getMatches(), [], [], 'Currency']; foreach ($money->iterate() as $id => $__) { $result[$id] = $money->getField('name', true); $osInfo[2][$id] = $money->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchItemset(array &$shared) : ?array// 5 Itemsets $moduleMask & 0x0000020 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $sets = new ItemsetList($cnd, ['calcTotal' => true]); $data = $sets->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $sets->getJSGlobals(GLOBALINFO_SELF)); $lvData = ['data' => $data]; if ($sets->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_itemsetsfound', $sets->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?itemsets&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?itemsets&filter=na='.urlencode($this->query).'\')'; return [$lvData, ItemsetList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::ITEMSET, $sets->getMatches(), [], [], 'Item Set']; foreach ($sets->iterate() as $id => $__) { $result[$id] = $sets->getField('name', true); $osInfo[3][$id] = $sets->getField('quality'); } return [$result, ...$osInfo]; } if ($this->moduleMask & self::TYPE_JSON) { $shared['pcsToSet'] = $sets->pieceToSet; foreach ($data as &$d) unset($d['quality'], $d['heroic']); return array_values($data); } return null; } private function _searchItem(array &$shared) : ?array // 6 Items $moduleMask & 0x0000040 { $miscData = ['calcTotal' => true]; $lookup = $this->createLookup(); if ($this->moduleMask & self::TYPE_JSON) { if (!empty($shared['pcsToSet'])) { $cnd = [['i.id', array_keys($shared['pcsToSet'])], Cfg::get('SQL_LIMIT_NONE')]; $miscData = ['pcsToSet' => $shared['pcsToSet']]; } else { $cnd = $this->cndBase; $cnd[] = ['i.class', [ITEM_CLASS_WEAPON, ITEM_CLASS_GEM, ITEM_CLASS_ARMOR]]; $cnd[] = $lookup; if ($this->extraOpts) $miscData['extraOpts'] = $this->extraOpts; if ($this->extraCnd) $cnd = array_merge($cnd, $this->extraCnd); } } else $cnd = array_merge($this->cndBase, [$lookup]); $items = new ItemList($cnd, $miscData); $data = $items->getListviewData($this->moduleMask & self::TYPE_JSON ? (ITEMINFO_SUBITEMS | ITEMINFO_JSON) : 0); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $items->getJSGlobals()); $lvData = ['data' => $data]; if ($items->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_itemsfound', $items->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?items&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?items&filter=na='.urlencode($this->query).'\')'; return [$lvData, ItemList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::ITEM, $items->getMatches(), [], [], 'Item']; foreach ($items->iterate() as $id => $__) { $result[$id] = $items->getField('name', true); $osInfo[2][$id] = $items->getField('iconString'); $osInfo[3][$id] = $items->getField('quality'); } return [$result, ...$osInfo]; } if ($this->moduleMask & self::TYPE_JSON) { foreach ($data as &$d) if (!empty($d['subitems'])) foreach ($d['subitems'] as &$si) $si['enchantment'] = implode(', ', $si['enchantment']); return array_values($data); } return null; } private function _searchAbility() : ?array // 7 Abilities (Player + Pet) $moduleMask & 0x0000080 { $cnd = array_merge($this->cndBase, array( // hmm, inclued classMounts..? ['s.typeCat', [7, -2, -3, -4]], [['s.cuFlags', (SPELL_CU_TRIGGERED | SPELL_CU_TALENT), '&'], 0], [['s.attributes0', 0x80, '&'], 0], $this->createLookup() )); $abilities = new SpellList($cnd, ['calcTotal' => true]); $data = $abilities->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $abilities->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); $vis = ['level', 'schools']; if ($abilities->hasSetFields('reagent1', 'reagent2', 'reagent3', 'reagent4', 'reagent5', 'reagent6', 'reagent7', 'reagent8')) $vis[] = 'reagents'; if ($abilities->hasSetFields('reqclass')) $vis[] = 'classes'; // i'd love to set 'singleclass', but do i want to walk through all abilities to see if each mask contains at most 1 class? $lvData = array( 'data' => $data, 'id' => 'abilities', 'name' => '$LANG.tab_abilities', 'visibleCols' => $vis ); if ($abilities->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_abilitiesfound', $abilities->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=7&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=7&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $abilities->getMatches(), [], [], 'Ability']; foreach ($abilities->iterate() as $id => $__) { $result[$id] = $abilities->getField('name', true); $osInfo[2][$id] = $abilities->getField('iconString'); $osInfo[3][$id] = $abilities->ranks[$id]; } return [$result, ...$osInfo]; } return null; } private function _searchTalent() : ?array // 8 Talents (Player + Pet) $moduleMask & 0x0000100 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', [-7, -2]], $this->createLookup() )); $talents = new SpellList($cnd, ['calcTotal' => true]); $data = $talents->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $talents->getJSGlobals()); $vis = ['level', 'singleclass', 'schools']; if ($talents->hasSetFields('reagent1', 'reagent2', 'reagent3', 'reagent4', 'reagent5', 'reagent6', 'reagent7', 'reagent8')) $vis[] = 'reagents'; $lvData = array( 'data' => $data, 'id' => 'talents', 'name' => '$LANG.tab_talents', 'visibleCols' => $vis ); if ($talents->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_talentsfound', $talents->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=-2&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=-2&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $talents->getMatches(), [], [], 'Talent']; foreach ($talents->iterate() as $id => $__) { $result[$id] = $talents->getField('name', true); $osInfo[2][$id] = $talents->getField('iconString'); $osInfo[3][$id] = $talents->ranks[$id]; } return [$result, ...$osInfo]; } return null; } private function _searchGlyph() : ?array // 9 Glyphs $moduleMask & 0x0000200 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', -13], $this->createLookup() )); $glyphs = new SpellList($cnd, ['calcTotal' => true]); $data = $glyphs->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $glyphs->getJSGlobals()); $lvData = array( 'data' => $data, 'id' => 'glyphs', 'name' => '$LANG.tab_glyphs', 'visibleCols' => ['singleclass', 'glyphtype'] ); if ($glyphs->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_glyphsfound', $glyphs->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=-13&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=-13&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $glyphs->getMatches(), [], [], 'Glyph']; foreach ($glyphs->iterate() as $id => $__) { $result[$id] = $glyphs->getField('name', true); $osInfo[2][$id] = $glyphs->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchProficiency() : ?array // 10 Proficiencies $moduleMask & 0x0000400 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', -11], $this->createLookup() )); $prof = new SpellList($cnd, ['calcTotal' => true]); $data = $prof->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $prof->getJSGlobals()); $lvData = array( 'data' => $data, 'id' => 'proficiencies', 'name' => '$LANG.tab_proficiencies', 'visibleCols' => ['classes'] ); if ($prof->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_spellsfound', $prof->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=-11&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=-11&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $prof->getMatches(), [], [], 'Proficiency']; foreach ($prof->iterate() as $id => $__) { $result[$id] = $prof->getField('name', true); $osInfo[2][$id] = $prof->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchProfession() : ?array // 11 Professions (Primary + Secondary) $moduleMask & 0x0000800 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', [9, 11]], $this->createLookup() )); $prof = new SpellList($cnd, ['calcTotal' => true]); $data = $prof->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $prof->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); $lvData = array( 'data' => $data, 'id' => 'professions', 'name' => '$LANG.tab_professions', 'visibleCols' => ['source', 'reagents'] ); if ($prof->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_professionfound', $prof->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=11&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=11&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $prof->getMatches(), [], [], 'Profession']; foreach ($prof->iterate() as $id => $__) { $result[$id] = $prof->getField('name', true); $osInfo[2][$id] = $prof->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchCompanion() : ?array // 12 Companions $moduleMask & 0x0001000 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', -6], $this->createLookup() )); $vPets = new SpellList($cnd, ['calcTotal' => true]); $data = $vPets->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $vPets->getJSGlobals()); $lvData = array( 'data' => $data, 'id' => 'companions', 'name' => '$LANG.tab_companions', 'visibleCols' => ['reagents'] ); if ($vPets->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_companionsfound', $vPets->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=-6&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=-6&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $vPets->getMatches(), [], [], 'Companion']; foreach ($vPets->iterate() as $id => $__) { $result[$id] = $vPets->getField('name', true); $osInfo[2][$id] = $vPets->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchMount() : ?array // 13 Mounts $moduleMask & 0x0002000 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', -5], $this->createLookup() )); $mounts = new SpellList($cnd, ['calcTotal' => true]); $data = $mounts->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $mounts->getJSGlobals()); $lvData = array( 'data' => $data, 'id' => 'mounts', 'name' => '$LANG.tab_mounts', ); if ($mounts->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_mountsfound', $mounts->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=-5&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=-5&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $mounts->getMatches(), [], [], 'Mount']; foreach ($mounts->iterate() as $id => $__) { $result[$id] = $mounts->getField('name', true); $osInfo[2][$id] = $mounts->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchCreature() : ?array // 14 NPCs $moduleMask & 0x0004000 { $cnd = array_merge($this->cndBase, array( [['flagsExtra', 0x80], 0], // exclude trigger creatures [['cuFlags', NPC_CU_DIFFICULTY_DUMMY, '&'], 0], // exclude difficulty entries $this->createLookup() )); $npcs = new CreatureList($cnd, ['calcTotal' => true]); $data = $npcs->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = array( 'data' => $data, 'id' => 'npcs', 'name' => '$LANG.tab_npcs', ); if ($npcs->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_npcsfound', $npcs->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?npcs&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?npcs&filter=na='.urlencode($this->query).'\')'; return [$lvData, CreatureList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::NPC, $npcs->getMatches(), [], [], 'NPC']; foreach ($npcs->iterate() as $id => $__) { $result[$id] = $npcs->getField('name', true); if ($npcs->isBoss()) $osInfo[2][$id] = 1; } return [$result, ...$osInfo]; } return null; } private function _searchQuest() : ?array // 15 Quests $moduleMask & 0x0008000 { $cnd = array_merge($this->cndBase, array( [['flags', CUSTOM_UNAVAILABLE | CUSTOM_DISABLED, '&'], 0], $this->createLookup() )); $quests = new QuestList($cnd, ['calcTotal' => true]); $data = $quests->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $quests->getJSGlobals()); $lvData = ['data' => $data]; if ($quests->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_questsfound', $quests->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?quests&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?quests&filter=na='.urlencode($this->query).'\')'; return [$lvData, QuestList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::QUEST, $quests->getMatches(), [], [], 'Quest']; foreach ($quests->iterate() as $id => $__) { $result[$id] = $quests->getField('name', true); $osInfo[2][$id] = $data[$id]['side']; // why recalculate if already set } return [$result, ...$osInfo]; } return null; } private function _searchAchievement() : ?array // 16 Achievements $moduleMask & 0x0010000 { $cnd = array_merge($this->cndBase, array( [['flags', ACHIEVEMENT_FLAG_COUNTER, '&'], 0], // not a statistic $this->createLookup() )); $acvs = new AchievementList($cnd, ['calcTotal' => true]); $data = $acvs->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $acvs->getJSGlobals()); $lvData = array( 'data' => $data, 'visibleCols' => ['category'] ); if ($acvs->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_achievementsfound', $acvs->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?achievements&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?achievements&filter=na='.urlencode($this->query).'\')'; return [$lvData, AchievementList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::ACHIEVEMENT, $acvs->getMatches(), [], [], 'Achievement']; foreach ($acvs->iterate() as $id => $__) { $result[$id] = $acvs->getField('name', true); $osInfo[2][$id] = $acvs->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchStatistic() : ?array // 17 Statistics $moduleMask & 0x0020000 { $cnd = array_merge($this->cndBase, array( ['flags', ACHIEVEMENT_FLAG_COUNTER, '&'], // is a statistic $this->createLookup() )); $stats = new AchievementList($cnd, ['calcTotal' => true]); $data = $stats->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $stats->getJSGlobals(GLOBALINFO_SELF)); $lvData = array( 'data' => $data, 'visibleCols' => ['category'], 'hiddenCols' => ['side', 'points', 'rewards'], 'name' => '$LANG.tab_statistics', 'id' => 'statistics' ); if ($stats->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_statisticsfound', $stats->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?achievements=1&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?achievements=1&filter=na='.urlencode($this->query).'\')'; return [$lvData, AchievementList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::ACHIEVEMENT, $stats->getMatches(), [], [], 'Statistic']; foreach ($stats->iterate() as $id => $__) { $result[$id] = $stats->getField('name', true); $osInfo[2][$id] = $stats->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchZone() : ?array // 18 Zones $moduleMask & 0x0040000 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $zones = new ZoneList($cnd, ['calcTotal' => true]); $data = $zones->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $zones->getJSGlobals()); $lvData = ['data' => $data]; if ($zones->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_zonesfound', $zones->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?achievements&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?achievements&filter=na='.urlencode($this->query).'\')'; return [$lvData, ZoneList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::ZONE, $zones->getMatches(), [], [], 'Zone']; foreach ($zones->iterate() as $id => $__) $result[$id] = $zones->getField('name', true); return [$result, ...$osInfo]; } return null; } private function _searchObject() : ?array // 19 Objects $moduleMask & 0x0080000 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $objects = new GameObjectList($cnd, ['calcTotal' => true]); $data = $objects->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $objects->getJSGlobals()); $lvData = ['data' => $data]; if ($objects->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_objectsfound', $objects->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?objects&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?objects&filter=na='.urlencode($this->query).'\')'; return [$lvData, GameObjectList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::OBJECT, $objects->getMatches(), [], [], 'Object']; foreach ($objects->iterate() as $id => $__) $result[$id] = $objects->getField('name', true); return [$result, ...$osInfo]; } return null; } private function _searchFaction() : ?array // 20 Factions $moduleMask & 0x0100000 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $factions = new FactionList($cnd, ['calcTotal' => true]); $data = $factions->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = ['data' => $data]; if ($factions->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_factionsfound', $factions->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, FactionList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::FACTION, $factions->getMatches(), [], [], 'Faction']; foreach ($factions->iterate() as $id => $__) $result[$id] = $factions->getField('name', true); return [$result, ...$osInfo]; } return null; } private function _searchSkill() : ?array // 21 Skills $moduleMask & 0x0200000 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $skills = new SkillList($cnd, ['calcTotal' => true]); $data = $skills->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = ['data' => $data]; if ($skills->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_skillsfound', $skills->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, SkillList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SKILL, $skills->getMatches(), [], [], 'Skill']; foreach ($skills->iterate() as $id => $__) { $result[$id] = $skills->getField('name', true); $osInfo[2][$id] = $skills->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchPet() : ?array // 22 Pets $moduleMask & 0x0400000 { $cnd = array_merge($this->cndBase, [$this->createLookup()]); $pets = new PetList($cnd, ['calcTotal' => true]); $data = $pets->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { $lvData = array( 'data' => $data, 'computeDataFunc' => '$_' ); if ($pets->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_petsfound', $pets->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, PetList::$brickFile, 'petFoodCol']; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::PET, $pets->getMatches(), [], [], 'Pet']; foreach ($pets->iterate() as $id => $__) { $result[$id] = $pets->getField('name', true); $osInfo[2][$id] = $pets->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchCreatureAbility() : ?array // 23 NPCAbilities $moduleMask & 0x0800000 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', -8], $this->createLookup() )); $npcAbilities = new SpellList($cnd, ['calcTotal' => true]); $data = $npcAbilities->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $npcAbilities->getJSGlobals()); $lvData = array( 'data' => $data, 'id' => 'npc-abilities', 'name' => '$LANG.tab_npcabilities', 'visibleCols' => ['level'], 'hiddenCols' => ['skill'] ); if ($npcAbilities->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_spellsfound', $npcAbilities->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=-8&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=-8&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $npcAbilities->getMatches(), [], [], 'Spell']; foreach ($npcAbilities->iterate() as $id => $__) { $result[$id] = $npcAbilities->getField('name', true); $osInfo[2][$id] = $npcAbilities->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchSpell() : ?array // 24 Spells (Misc + GM + triggered abilities) $moduleMask & 0x1000000 { $cnd = array_merge($this->cndBase, array( ['s.typeCat', -8, '!'], [ 'OR', ['s.typeCat', [0, -9]], ['s.cuFlags', SPELL_CU_TRIGGERED, '&'], ['s.attributes0', 0x80, '&'] ], $this->createLookup() )); $misc = new SpellList($cnd, ['calcTotal' => true]); $data = $misc->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $misc->getJSGlobals(GLOBALINFO_SELF | GLOBALINFO_RELATED)); $lvData = array( 'data' => $data, 'name' => '$LANG.tab_uncategorizedspells', 'visibleCols' => ['level'], 'hiddenCols' => ['skill'] ); if ($misc->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_spellsfound', $misc->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } if (isset($lvData['note'])) $lvData['note'] .= ' + LANG.dash + $WH.sprintf(LANG.lvnote_filterresults, \'?spells=0&filter=na='.urlencode($this->query).'\')'; else $lvData['note'] = '$$WH.sprintf(LANG.lvnote_filterresults, \'?spells=0&filter=na='.urlencode($this->query).'\')'; return [$lvData, SpellList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SPELL, $misc->getMatches(), [], [], 'Spell']; foreach ($misc->iterate() as $id => $__) { $result[$id] = $misc->getField('name', true); $osInfo[2][$id] = $misc->getField('iconString'); } return [$result, ...$osInfo]; } return null; } private function _searchEmote() : ?array // 25 Emotes $moduleMask & 0x2000000 { $cnd = array_merge($this->cndBase, [$this->createLookup(['cmd', 'meToExt_loc'.Lang::getLocale()->value, 'meToNone_loc'.Lang::getLocale()->value, 'extToMe_loc'.Lang::getLocale()->value, 'extToExt_loc'.Lang::getLocale()->value, 'extToNone_loc'.Lang::getLocale()->value])]); $emote = new EmoteList($cnd, ['calcTotal' => true]); $data = $emote->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $emote->getJSGlobals()); $lvData = array( 'data' => $data, 'name' => Util::ucFirst(Lang::game('emotes')) ); if ($emote->getMatches() > $this->maxResults) { // $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_emotesfound', $emote->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, EmoteList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::EMOTE, $emote->getMatches(), [], [], 'Emote']; foreach ($emote->iterate() as $id => $__) $result[$id] = $emote->getField('name', true); return [$result, ...$osInfo]; } return null; } private function _searchEnchantment() : ?array // 26 Enchantments $moduleMask & 0x4000000 { $cnd = array_merge($this->cndBase, [$this->createLookup(['name_loc'.Lang::getLocale()->value])]); $enchantment = new EnchantmentList($cnd, ['calcTotal' => true]); $data = $enchantment->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $enchantment->getJSGlobals()); $lvData = array( 'data' => $data, 'name' => Util::ucFirst(Lang::game('enchantments')) ); if (array_filter(array_column($data, 'spells'))) $lvData['visibleCols'] = ['trigger']; if (!$enchantment->hasSetFields('skillLine')) $lvData['hiddenCols'] = ['skill']; if ($enchantment->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_enchantmentsfound', $enchantment->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, EnchantmentList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::ENCHANTMENT, $enchantment->getMatches(), [], [], 'Enchantment']; foreach ($enchantment->iterate() as $id => $__) $result[$id] = $enchantment->getField('name', true); return [$result, ...$osInfo]; } return null; } private function _searchSound() : ?array // 27 Sounds $moduleMask & 0x8000000 { $cnd = array_merge($this->cndBase, [$this->createLookup(['name'])]); $sounds = new SoundList($cnd, ['calcTotal' => true]); $data = $sounds->getListviewData(); if (!$data) return []; if ($this->moduleMask & self::TYPE_REGULAR) { Util::mergeJsGlobals($this->jsgStore, $sounds->getJSGlobals()); $lvData = array( 'data' => $data, ); if ($sounds->getMatches() > $this->maxResults) { $lvData['note'] = sprintf(Util::$tryNarrowingString, 'LANG.lvnote_soundsfound', $sounds->getMatches(), $this->maxResults); $lvData['_truncated'] = 1; } return [$lvData, SoundList::$brickFile]; } if ($this->moduleMask & self::TYPE_OPEN) { $result = []; $osInfo = [Type::SOUND, $sounds->getMatches(), [], [], 'Sound']; foreach ($sounds->iterate() as $id => $__) $result[$id] = $sounds->getField('name', true); return [$result, ...$osInfo]; } return null; } }