Files
aowow/pages/profile.php
Sarjuuk 398b93e9a7 Locale
* detatch from User and Util and move to its own enum class
 * added definitions for all locales the 12340 client could in theory have
 * this is incompatble with the Intl extension
 * version bump and php requirement bump
2025-02-27 16:25:23 +01:00

257 lines
11 KiB
PHP

<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 5: Profiler g_initPath()
// tabId 1: Tools g_initHeader()
class ProfilePage extends GenericPage
{
use TrProfiler;
protected $gDataKey = true;
protected $mode = CACHE_TYPE_PAGE;
protected $type = Type::PROFILE;
protected $tabId = 1;
protected $path = [1, 5, 1];
protected $tpl = 'profile';
protected $scripts = array(
[SC_JS_FILE, 'js/filters.js'],
[SC_JS_FILE, 'js/TalentCalc.js'],
[SC_JS_FILE, 'js/swfobject.js'],
[SC_JS_FILE, 'js/profile_all.js'],
[SC_JS_FILE, 'js/profile.js'],
[SC_JS_FILE, 'js/Profiler.js'],
[SC_CSS_FILE, 'css/talentcalc.css'],
[SC_CSS_FILE, 'css/Profiler.css']
);
protected $_get = array(
'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain'],
'new' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet']
);
private $isCustom = false;
private $profile = null;
private $subject = null;
private $rnItr = 0;
private $powerTpl = '$WowheadPower.registerProfile(%s, %d, %s);';
public function __construct($pageCall, $pageParam)
{
parent::__construct($pageCall, $pageParam);
if (!Cfg::get('PROFILER_ENABLE'))
$this->error();
$params = array_map('urldecode', explode('.', $pageParam));
if ($params[0])
$params[0] = Profiler::urlize($params[0]);
if (isset($params[1]))
$params[1] = Profiler::urlize($params[1], true);
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Lang::load($this->_get['domain']);
if (count($params) == 1 && intval($params[0]))
{
// redundancy much?
$this->subjectGUID = intval($params[0]);
$this->profile = intval($params[0]);
$this->isCustom = true; // until proven otherwise
$this->subject = new LocalProfileList(array(['id', intval($params[0])]));
if ($this->subject->error)
$this->notFound();
if (!$this->subject->isVisibleToUser())
$this->notFound();
if (!$this->subject->isCustom())
header('Location: '.$this->subject->getProfileUrl(), true, 302);
}
else if (count($params) == 3)
{
$this->getSubjectFromUrl($pageParam);
if (!$this->subjectName)
$this->notFound();
// names MUST be ucFirst. Since we don't expect partial matches, search this way
$this->profile = $params;
// pending rename
if (preg_match('/([^\-]+)-(\d+)/i', $this->subjectName, $m))
{
$this->subjectName = $m[1];
$this->rnItr = $m[2];
}
// 3 possibilities
// 1) already synced to aowow
if ($subject = DB::Aowow()->selectRow('SELECT id, realmGUID, cuFlags FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID IS NOT NULL AND name = ? AND renameItr = ?d', $this->realmId, Util::ucFirst($this->subjectName), $this->rnItr))
{
$this->subjectGUID = $subject['id'];
if ($subject['cuFlags'] & PROFILER_CU_NEEDS_RESYNC)
{
$this->handleIncompleteData($params, $subject['realmGUID']);
return;
}
$this->subject = new LocalProfileList(array(['id', $subject['id']]));
if ($this->subject->error)
$this->notFound();
}
// 2) not yet synced but exists on realm (and not a gm character)
else if (!$this->rnItr && ($char = DB::Characters($this->realmId)->selectRow('SELECT c.guid AS realmGUID, c.name, c.race, c.class, c.level, c.gender, c.at_login, g.guildid AS guildGUID, IFNULL(g.name, "") AS guildName, IFNULL(gm.rank, 0) AS guildRank FROM characters c LEFT JOIN guild_member gm ON gm.guid = c.guid LEFT JOIN guild g ON g.guildid = gm.guildid WHERE c.name = ? AND level <= ?d AND (extra_flags & ?d) = 0', Util::ucFirst($this->subjectName), MAX_LEVEL, Profiler::CHAR_GMFLAGS)))
{
$char['realm'] = $this->realmId;
$char['cuFlags'] = PROFILER_CU_NEEDS_RESYNC;
if ($char['at_login'] & 0x1)
$char['renameItr'] = DB::Aowow()->selectCell('SELECT MAX(renameItr) FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID IS NOT NULL AND name = ?', $this->realmId, $char['name']);
if ($char['guildGUID'])
{
// create empty guild if nessecary to satisfy foreign keys
$char['guild'] = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_guild WHERE realm = ?d AND realmGUID = ?d', $this->realmId, $char['guildGUID']);
if (!$char['guild'])
$char['guild'] = DB::Aowow()->query('INSERT INTO ?_profiler_guild (realm, realmGUID, cuFlags, name) VALUES (?d, ?d, ?d, ?)', $this->realmId, $char['guildGUID'], PROFILER_CU_NEEDS_RESYNC, $char['guildName']);
}
unset($char['guildGUID']);
unset($char['guildName']);
unset($char['at_login']);
// create entry from realm with enough basic info to disply tooltips
DB::Aowow()->query('REPLACE INTO ?_profiler_profiles (?#) VALUES (?a)', array_keys($char), array_values($char));
$this->subjectGUID = DB::Aowow()->selectCell('SELECT id FROM ?_profiler_profiles WHERE realm = ?d AND realmGUID = ?d', $this->realmId, $char['realmGUID']);
$this->handleIncompleteData($params, $char['realmGUID']);
}
// 3) does not exist at all
else
$this->notFound();
}
else if (($params && $params[0]) || !$this->_get['new'])
$this->notFound();
else if ($this->_get['new'])
$this->mode = CACHE_TYPE_NONE;
}
protected function generateContent()
{
if ($this->doResync)
return;
// + .titles ?
$this->addScript([SC_JS_FILE, '?data=enchants.gems.glyphs.itemsets.pets.pet-talents.quick-excludes.realms.statistics.weight-presets.achievements']);
// as demanded by the raid activity tracker
$bossIds = array(
/* Halion */
/* ruby */ 39863,
/* Valanar, Lana'thel, Saurfang, Festergut, Deathwisper, Marrowgar, Putricide, Rotface, Sindragosa, Valithria, Lich King */
/* icc */ 37970, 37955, 37813, 36626, 36855, 36612, 36678, 36627, 36853, 36789, 36597,
/* Jaraxxus, Anub'arak */
/* toc */ 34780, 34564,
/* Onyxia */
/* ony */ 10184,
/* Flame Levi, Ignis, Razorscale, XT-002, Kologarn, Auriaya, Freya, Hodir, Mimiron, Thorim, Vezaxx, Yogg, Algalon */
/* uld */ 33113, 33118, 33186, 33293, 32930, 33515, 32906, 32845, 33350, 32864, 33271, 33288, 32871,
/* Anub, Faerlina, Maexxna, Noth, Heigan, Loatheb, Razuvious, Gothik, Patchwerk, Grobbulus, Gluth, Thaddius, Sapphiron, Kel'Thuzad */
/* nax */ 15956, 15953, 15952, 15954, 15936, 16011, 16061, 16060, 16028, 15931, 15932, 15928, 15989, 15990
);
$this->extendGlobalIds(Type::NPC, ...$bossIds);
// dummy title from dungeon encounter
foreach (Lang::profiler('encounterNames') as $id => $name)
$this->extendGlobalData([Type::NPC => [$id => ['name_'.Lang::getLocale()->json() => $name]]]);
}
protected function generatePath()
{
}
protected function generateTitle()
{
array_unshift($this->title, Util::ucFirst(Lang::game('profile')));
}
protected function generateTooltip()
{
$id = $this->profile;
if (!$this->isCustom)
$id = "'".$this->profile[0].'.'.urlencode($this->profile[1]).'.'.urlencode($this->profile[2])."'";
$power = new StdClass();
if ($this->subject && !$this->subject->error && $this->subject->isVisibleToUser())
{
$n = $this->subject->getField('name');
$l = $this->subject->getField('level');
$r = $this->subject->getField('race');
$c = $this->subject->getField('class');
$g = $this->subject->getField('gender');
if ($this->isCustom)
$n .= Lang::profiler('customProfile');
else if ($_ = $this->subject->getField('title'))
if ($title = (new TitleList(array(['id', $_])))->getField($g ? 'female' : 'male', true))
$n = sprintf($title, $n);
$power->{'name_'.Lang::getLocale()->json()} = $n;
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
$power->icon = '$$WH.g_getProfileIcon('.$r.', '.$c.', '.$g.', '.$l.', \''.$this->subject->getIcon().'\')';
}
return sprintf($this->powerTpl, $id, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
public function display(string $override = ''): never
{
if ($this->mode != CACHE_TYPE_TOOLTIP)
parent::display($override);
// do not cache profile tooltips
header(MIME_TYPE_JSON);
die($this->generateTooltip());
}
public function notFound(string $title = '', string $msg = '') : never
{
parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'profile'));
}
private function handleIncompleteData($params, $guid)
{
if ($this->mode == CACHE_TYPE_TOOLTIP) // enable tooltip display with basic data we just added
{
$this->subject = new LocalProfileList(array(['id', $this->subjectGUID]), ['sv' => $params[1]]);
if ($this->subject->error)
$this->notFound();
$this->profile = $params;
}
else // display empty page and queue status
{
$this->mode = CACHE_TYPE_NONE;
// queue full fetch
if ($newId = Profiler::scheduleResync(Type::PROFILE, $this->realmId, $guid))
{
$this->doResync = ['profile', $newId];
$this->initialSync();
}
else // todo: base info should have been created in __construct .. why are we here..?
header('Location: ?profiles='.$params[0].'.'.$params[1].'&filter=na='.Util::ucFirst($this->subjectName).';ex=on');
}
}
}
?>