From 0cf9069eb1fd71803f18f0194a715f12f414badf Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Wed, 13 Aug 2025 21:23:09 +0200 Subject: [PATCH] Template/Update (Part 35) * convert dbtype 'icon' * improve on IconlistFilter --- endpoints/icon/icon.php | 158 ++++++++++++++++++++++++++++++++ endpoints/icons/icons.php | 109 ++++++++++++++++++++++ includes/dbtypes/icon.class.php | 120 ++++++++++-------------- pages/icon.php | 120 ------------------------ pages/icons.php | 96 ------------------- template/pages/icon.tpl.php | 13 ++- template/pages/icons.tpl.php | 32 ++++--- 7 files changed, 344 insertions(+), 304 deletions(-) create mode 100644 endpoints/icon/icon.php create mode 100644 endpoints/icons/icons.php delete mode 100644 pages/icon.php delete mode 100644 pages/icons.php diff --git a/endpoints/icon/icon.php b/endpoints/icon/icon.php new file mode 100644 index 00000000..2a67b53e --- /dev/null +++ b/endpoints/icon/icon.php @@ -0,0 +1,158 @@ +typeId = intVal($id); + $this->contribute = Type::getClassAttrib($this->type, 'contribute') ?? CONTRIBUTE_NONE; + } + + protected function generate() : void + { + $this->subject = new IconList(array(['id', $this->typeId])); + if ($this->subject->error) + $this->generateNotFound(Lang::game('icon'), Lang::icon('notFound')); + + $this->extendGlobalData($this->subject->getJSGlobals()); + + $this->h1 = $this->subject->getField('name'); + $this->icon = $this->subject->getField('name', true, true); + + $this->gPageInfo += array( + 'type' => $this->type, + 'typeId' => $this->typeId, + 'name' => $this->h1 + ); + + + /*************/ + /* Menu Path */ + /*************/ + + $cats = [1 => 'nItems', 2 => 'nSpells', 3 => 'nAchievements', 6 => 'nCurrencies', 9 => 'nPets'/* , 11 => '' */]; + $crumb = ''; + foreach ($cats as $cat => $field) + { + if (!$this->subject->getField($field)) + continue; + + if ($crumb) + { + $crumb = 0; + break; + } + + $crumb = $cat; + } + + if ($crumb) + $this->breadcrumb[] = $crumb; + + + /**************/ + /* Page Title */ + /**************/ + + array_unshift($this->title, $this->h1, Util::ucFirst(Lang::game('icon'))); + + + /****************/ + /* Main Content */ + /****************/ + + $this->redButtons = array( + BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId], + BUTTON_WOWHEAD => false + ); + + + /**************/ + /* Extra Tabs */ + /**************/ + + $this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"], 'tabsRelated', true); + + // used by: spell + $ubSpells = new SpellList(array(['iconId', $this->typeId])); + if (!$ubSpells->error) + { + $this->extendGlobalData($ubSpells->getJsGlobals(GLOBALINFO_RELATED | GLOBALINFO_SELF)); + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $ubSpells->getListviewData(), + 'id' => 'used-by-spell' + ), SpellList::$brickFile)); + } + + // used by: item + $ubItems = new ItemList(array(['iconId', $this->typeId])); + if (!$ubItems->error) + { + $this->extendGlobalData($ubItems->getJsGlobals()); + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $ubItems->getListviewData(), + 'id' => 'used-by-item' + ), ItemList::$brickFile)); + } + + // used by: achievement + $ubAchievements = new AchievementList(array(['iconId', $this->typeId])); + if (!$ubAchievements->error) + { + $this->extendGlobalData($ubAchievements->getJsGlobals()); + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $ubAchievements->getListviewData(), + 'id' => 'used-by-achievement' + ), AchievementList::$brickFile)); + } + + // used by: currency + $ubCurrencies = new CurrencyList(array(['iconId', $this->typeId])); + if (!$ubCurrencies->error) + { + $this->extendGlobalData($ubCurrencies->getJsGlobals()); + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $ubCurrencies->getListviewData(), + 'id' => 'used-by-currency' + ), CurrencyList::$brickFile)); + } + + // used by: hunter pet + $ubPets = new PetList(array(['iconId', $this->typeId])); + if (!$ubPets->error) + { + $this->extendGlobalData($ubPets->getJsGlobals()); + $this->lvTabs->addListviewTab(new Listview(array( + 'data' => $ubPets->getListviewData(), + 'id' => 'used-by-pet' + ), PetList::$brickFile)); + } + + parent::generate(); + } +} + +?> diff --git a/endpoints/icons/icons.php b/endpoints/icons/icons.php new file mode 100644 index 00000000..7613240e --- /dev/null +++ b/endpoints/icons/icons.php @@ -0,0 +1,109 @@ + ['filter' => FILTER_VALIDATE_REGEXP, 'options' => ['regexp' => Filter::PATTERN_PARAM]] + ); + protected array $validCats = [0, 1, 2, 3]; + + public function __construct(string $pageParam) + { + $this->getCategoryFromUrl($pageParam); + + parent::__construct($pageParam); + + $this->subCat = $pageParam !== '' ? '='.$pageParam : ''; + $this->filter = new IconListFilter($this->_get['filter'] ?? '', ['parentCats' => $this->category]); + $this->filterError = $this->filter->error; + } + + protected function generate() : void + { + $this->h1 = Util::ucWords(Lang::game('icons')); + + $conditions = [600]; // LIMIT 600 - fits better onto the grid + if (!User::isInGroup(U_GROUP_EMPLOYEE)) + $conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0]; + + $this->filter->evalCriteria(); + + if ($_ = $this->filter->getConditions()) + $conditions[] = $_; + + $this->filterError = $this->filter->error; // maybe the evalX() caused something + + + /**************/ + /* Page Title */ + /**************/ + + $title = $this->h1; + $setCr = $this->filter->getSetCriteria(1, 2, 3, 6, 9, 11); + if (count($setCr) == 1) + $title = match ($setCr[0]) + { + 1 => Util::ucFirst(Lang::game('item')), + 2 => Util::ucFirst(Lang::game('spell')), + 3 => Util::ucFirst(Lang::game('achievement')), + 6 => Util::ucFirst(Lang::game('currency')), + 9 => Util::ucFirst(Lang::game('pet')), + 11 => Util::ucFirst(Lang::game('class')), + } . ' ' . $this->h1; + + array_unshift($this->title, $title); + + + /*************/ + /* Menu Path */ + /*************/ + + if (count($setCr) == 1) + $this->breadcrumb[] = $setCr[0]; + + + /****************/ + /* Main Content */ + /****************/ + + $this->redButtons[BUTTON_WOWHEAD] = true; + if ($fiQuery = $this->filter->buildGETParam()) + $this->wowheadLink .= '&filter='.$fiQuery; + + $icons = new IconList($conditions, ['calcTotal' => true]); + + $tabData['data'] = $icons->getListviewData(); + $this->extendGlobalData($icons->getJSGlobals()); + + if ($icons->getMatches() > $conditions[0]) // LIMIT + { + $tabData['note'] = sprintf(Util::$tryFilteringEntityString, $icons->getMatches(), 'LANG.types[29][3]', $conditions[0]); + $tabData['_truncated'] = 1; + } + + $this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"]); + + $this->lvTabs->addListviewTab(new Listview($tabData, IconList::$brickFile)); + + parent::generate(); + } +} + +?> diff --git a/includes/dbtypes/icon.class.php b/includes/dbtypes/icon.class.php index 0ec46b4e..c324847f 100644 --- a/includes/dbtypes/icon.class.php +++ b/includes/dbtypes/icon.class.php @@ -101,7 +101,7 @@ class IconList extends DBTypeList class IconListFilter extends Filter { - private array $totalUses = []; + private array $iconTotals = []; private array $criterion2field = array( 1 => '?_items', // items [num] 2 => '?_spell', // spells [num] @@ -119,13 +119,13 @@ class IconListFilter extends Filter protected string $type = 'icons'; protected static array $genericFilter = array( - 1 => [parent::CR_CALLBACK, 'cbUseAny' ], // items [num] - 2 => [parent::CR_CALLBACK, 'cbUseAny' ], // spells [num] - 3 => [parent::CR_CALLBACK, 'cbUseAny' ], // achievements [num] - 6 => [parent::CR_CALLBACK, 'cbUseAny' ], // currencies [num] - 9 => [parent::CR_CALLBACK, 'cbUseAny' ], // hunterpets [num] - 11 => [parent::CR_NYI_PH, null, 0], // classes [num] - 13 => [parent::CR_CALLBACK, 'cbUseAll' ] // used [num] + 1 => [parent::CR_CALLBACK, 'cbUsedBy' ], // items [num] + 2 => [parent::CR_CALLBACK, 'cbUsedBy' ], // spells [num] + 3 => [parent::CR_CALLBACK, 'cbUsedBy' ], // achievements [num] + 6 => [parent::CR_CALLBACK, 'cbUsedBy' ], // currencies [num] + 9 => [parent::CR_CALLBACK, 'cbUsedBy' ], // hunterpets [num] + 11 => [parent::CR_NYI_PH, null, 0 ], // classes [num] + 13 => [parent::CR_CALLBACK, 'cbUsedBy', true] // used [num] ); protected static array $inputFields = array( @@ -138,35 +138,6 @@ class IconListFilter extends Filter public array $extraOpts = []; - private function _getCnd(string $op, int $val, string $tbl) : ?array - { - switch ($op) - { - case '>': - case '>=': - case '=': - $ids = DB::Aowow()->selectCol('SELECT `iconId` AS ARRAY_KEY, COUNT(*) AS "n" FROM ?# GROUP BY `iconId` HAVING n '.$op.' '.$val, $tbl); - return $ids ? ['id', array_keys($ids)] : [1]; - case '<=': - if ($val) - $op = '>'; - break; - case '<': - if ($val) - $op = '>='; - break; - case '!=': - if ($val) - $op = '='; - break; - default: - return null; - } - - $ids = DB::Aowow()->selectCol('SELECT `iconId` AS ARRAY_KEY, COUNT(*) AS "n" FROM ?# GROUP BY `iconId` HAVING n '.$op.' '.$val, $tbl); - return $ids ? ['id', array_keys($ids), '!'] : [1]; - } - protected function createSQLForValues() : array { $parts = []; @@ -180,47 +151,54 @@ class IconListFilter extends Filter return $parts; } - protected function cbUseAny(int $cr, int $crs, string $crv) : ?array + protected function cbUsedBy(int $cr, int $crs, string $crv, ?bool $all = false) : ?array { - if (Util::checkNumeric($crv, NUM_CAST_INT) && $this->int2Op($crs)) - return $this->_getCnd($crs, $crv, $this->criterion2field[$cr]); - - return null; - } - - protected function cbUseAll(int $cr, int $crs, string $crv) : ?array - { - if (!Util::checkNumeric($crv, NUM_CAST_INT) || !$this->int2Op($crs)) + if (!Util::checkNumeric($crv, NUM_CAST_INT) || ![$filter, $negate] = $this->int2Filter($crs, $crv)) return null; - if (!$this->totalUses) - { - foreach ($this->criterion2field as $tbl) - { - if (!$tbl) - continue; + $total = $this->prepareIconTotals($all ? 0 : $cr); - $res = DB::Aowow()->selectCol('SELECT `iconId` AS ARRAY_KEY, COUNT(*) AS "n" FROM ?# GROUP BY `iconId`', $tbl); - Util::arraySumByKey($this->totalUses, $res); - } - } + $ids = array_filter($total, $filter); - if ($crs == '=') - $crs = '=='; - - $op = $crs; - if ($crs == '<=' && $crv) - $op = '>'; - else if ($crs == '<' && $crv) - $op = '>='; - else if ($crs == '!=' && $crv) - $op = '=='; - $ids = array_filter($this->totalUses, fn($x) => eval('return '.$x.' '.$op.' '.$crv.';')); - - if ($crs != $op) + if ($negate) return $ids ? ['id', array_keys($ids), '!'] : [1]; else - return $ids ? ['id', array_keys($ids)] : ['id', array_keys($this->totalUses), '!']; + return $ids ? ['id', array_keys($ids)] : ['id', array_keys($total), '!']; + } + + private function int2Filter(mixed $op, int $y) : ?array + { + return match ($op) { + 1 => [fn($x) => $x > $y, false], + 2 => [fn($x) => $x >= $y, false], + 3 => [fn($x) => $x == $y, false], + 4 => [fn($x) => $x > $y, true], + 5 => [fn($x) => $x >= $y, true], + 6 => [fn($x) => $x == $y, true], + default => null + }; + } + + private function prepareIconTotals(int $forCr = 0) : array + { + foreach ($this->criterion2field as $cr => $tbl) + { + if (!$tbl || isset($this->iconTotals[$cr]) || ($forCr && $forCr != $cr)) + continue; + + $this->iconTotals[$cr] = DB::Aowow()->selectCol('SELECT `iconId` AS ARRAY_KEY, COUNT(*) AS "n" FROM ?# GROUP BY `iconId`', $tbl); + } + + if ($forCr) + return $this->iconTotals[$forCr]; + + if (!isset($this->iconTotals['all'])) + { + $this->iconTotals['all'] = []; + Util::arraySumByKey($this->iconTotals['all'], ...$this->iconTotals); + } + + return $this->iconTotals['all']; } } diff --git a/pages/icon.php b/pages/icon.php deleted file mode 100644 index cb56cc95..00000000 --- a/pages/icon.php +++ /dev/null @@ -1,120 +0,0 @@ -typeId = intVal($id); - - $this->subject = new IconList(array(['id', $this->typeId])); - if ($this->subject->error) - $this->notFound(Lang::game('icon'), Lang::icon('notFound')); - - $this->extendGlobalData($this->subject->getJSGlobals()); - - $this->name = $this->subject->getField('name'); - $this->icon = $this->subject->getField('name', true, true); - } - - protected function generateContent() - { - /****************/ - /* Main Content */ - /****************/ - - $this->redButtons = array( - BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId], - BUTTON_WOWHEAD => false - ); - - - /**************/ - /* Extra Tabs */ - /**************/ - - // used by: spell - $ubSpells = new SpellList(array(['iconId', $this->typeId])); - if (!$ubSpells->error) - { - $this->extendGlobalData($ubSpells->getJsGlobals(GLOBALINFO_RELATED | GLOBALINFO_SELF)); - $this->lvTabs[] = [SpellList::$brickFile, array( - 'data' => array_values($ubSpells->getListviewData()), - 'id' => 'used-by-spell' - )]; - } - - // used by: item - $ubItems = new ItemList(array(['iconId', $this->typeId])); - if (!$ubItems->error) - { - $this->extendGlobalData($ubItems->getJsGlobals()); - $this->lvTabs[] = [ItemList::$brickFile, array( - 'data' => array_values($ubItems->getListviewData()), - 'id' => 'used-by-item' - )]; - } - - // used by: achievement - $ubAchievements = new AchievementList(array(['iconId', $this->typeId])); - if (!$ubAchievements->error) - { - $this->extendGlobalData($ubAchievements->getJsGlobals()); - $this->lvTabs[] = [AchievementList::$brickFile, array( - 'data' => array_values($ubAchievements->getListviewData()), - 'id' => 'used-by-achievement' - )]; - } - - // used by: currency - $ubCurrencies = new CurrencyList(array(['iconId', $this->typeId])); - if (!$ubCurrencies->error) - { - $this->extendGlobalData($ubCurrencies->getJsGlobals()); - $this->lvTabs[] = [CurrencyList::$brickFile, array( - 'data' => array_values($ubCurrencies->getListviewData()), - 'id' => 'used-by-currency' - )]; - } - - // used by: hunter pet - $ubPets = new PetList(array(['iconId', $this->typeId])); - if (!$ubPets->error) - { - $this->extendGlobalData($ubPets->getJsGlobals()); - $this->lvTabs[] = [PetList::$brickFile, array( - 'data' => array_values($ubPets->getListviewData()), - 'id' => 'used-by-pet' - )]; - } - } - - protected function generateTitle() - { - array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('icon'))); - } - - protected function generatePath() { } -} - -?> diff --git a/pages/icons.php b/pages/icons.php deleted file mode 100644 index 52e9d218..00000000 --- a/pages/icons.php +++ /dev/null @@ -1,96 +0,0 @@ - ['filter' => FILTER_UNSAFE_RAW]]; - - public function __construct($pageCall) - { - parent::__construct($pageCall); - - $this->filterObj = new IconListFilter($this->_get['filter'] ?? ''); - - $this->name = Util::ucFirst(Lang::game('icons')); - } - - protected function generateContent() - { - $tabData = array( - 'data' => [], - ); - - $sqlLimit = 600; // fits better onto the grid - - $conditions = [$sqlLimit]; - - if (!User::isInGroup(U_GROUP_EMPLOYEE)) - $conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0]; - - $this->filterObj->evalCriteria(); - - if ($_ = $this->filterObj->getConditions()) - $conditions[] = $_; - - $icons = new IconList($conditions, ['calcTotal' => true]); - - $tabData['data'] = array_values($icons->getListviewData()); - $this->extendGlobalData($icons->getJSGlobals()); - - if ($icons->getMatches() > $sqlLimit) - { - $tabData['note'] = sprintf(Util::$tryFilteringEntityString, $icons->getMatches(), 'LANG.types[29][3]', $sqlLimit); - $tabData['_truncated'] = 1; - } - - if ($this->filterObj->error) - $tabData['_errors'] = 1; - - $this->lvTabs[] = [IconList::$brickFile, $tabData]; - } - - protected function generateTitle() - { - $title = $this->name; - $setCr = $this->filterObj->getSetCriteria(1, 2, 3, 6, 9, 11); - if (count($setCr) == 1) - { - $title = match($setCr[0]) - { - 1 => Util::ucFirst(Lang::game('item')), - 2 => Util::ucFirst(Lang::game('spell')), - 3 => Util::ucFirst(Lang::game('achievement')), - 6 => Util::ucFirst(Lang::game('currency')), - 9 => Util::ucFirst(Lang::game('pet')), - 11 => Util::ucFirst(Lang::game('class')) - } . ' ' . $title; - } - - array_unshift($this->title, $title); - } - - protected function generatePath() - { - $setCr = $this->filterObj->getSetCriteria(1, 2, 3, 6, 9, 11); - if (count($setCr) == 1) - $this->path[] = $setCr[0]; - } -} - -?> diff --git a/template/pages/icon.tpl.php b/template/pages/icon.tpl.php index 727c1ade..5ec5f25a 100644 --- a/template/pages/icon.tpl.php +++ b/template/pages/icon.tpl.php @@ -1,7 +1,10 @@ - +brick('header'); ?> + use \Aowow\Lang; + $this->brick('header'); +?>
@@ -19,20 +22,20 @@ $this->brick('redButtons'); ?> -

name; ?>

+

h1; ?>

brick('article'); + $this->brick('markup', ['markup' => $this->article]); ?>

brick('lvTabs', ['relTabs' => true]); + $this->brick('lvTabs'); $this->brick('contribute'); ?> diff --git a/template/pages/icons.tpl.php b/template/pages/icons.tpl.php index 11f6c9c9..2ab62c48 100644 --- a/template/pages/icons.tpl.php +++ b/template/pages/icons.tpl.php @@ -1,10 +1,11 @@ - - brick('header'); -$f = $this->filterObj->values // shorthand -?> + namespace Aowow\Template; + use \Aowow\Lang; + +$this->brick('header'); +$f = $this->filter->values; // shorthand +?>
@@ -12,17 +13,24 @@ $f = $this->filterObj->values // shorthand brick('announcement'); -$this->brick('pageTemplate', ['fiQuery' => $this->filterObj->query, 'fiMenuItem' => [101]]); +$this->brick('pageTemplate', ['fiQuery' => $this->filter->query, 'fiMenuItem' => [31]]); ?> - -
+
+
+brick('headIcons'); + +$this->brick('redButtons'); +?> +

h1; ?>

+
- + @@ -31,7 +39,7 @@ $this->brick('pageTemplate', ['fiQuery' => $this->filterObj->query, 'fiMenuItem'
- /> /> + /> />
@@ -45,7 +53,7 @@ $this->brick('pageTemplate', ['fiQuery' => $this->filterObj->query, 'fiMenuItem'
-brick('filter'); ?> +renderFilter(12); ?> brick('lvTabs'); ?>
ucFirst(Lang::main('name')).Lang::main('colon'); ?> - +
 /> />