mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
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
This commit is contained in:
@@ -20,17 +20,11 @@ class AjaxAccount extends AjaxHandler
|
||||
'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
|
||||
// 'sessionKey' => ['filter' => FILTER_SANITIZE_NUMBER_INT]
|
||||
);
|
||||
protected $_get = array(
|
||||
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale']
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (is_numeric($this->_get['locale']))
|
||||
User::useLocale($this->_get['locale']);
|
||||
|
||||
if (!$this->params || !User::$id)
|
||||
return;
|
||||
|
||||
@@ -60,12 +54,12 @@ class AjaxAccount extends AjaxHandler
|
||||
// we don't get signaled whether an id should be added to or removed from either includes or excludes
|
||||
// so we throw everything into one table and toggle the mode if its already in here
|
||||
|
||||
$includes = DB::Aowow()->selectCol('SELECT typeId FROM ?_profiler_excludes WHERE type = ?d AND typeId IN (?a)', $type, $ids);
|
||||
$includes = DB::Aowow()->selectCol('SELECT `typeId` FROM ?_profiler_excludes WHERE `type` = ?d AND `typeId` IN (?a)', $type, $ids);
|
||||
|
||||
foreach ($ids as $typeId)
|
||||
DB::Aowow()->query('INSERT INTO ?_account_excludes (`userId`, `type`, `typeId`, `mode`) VALUES (?a) ON DUPLICATE KEY UPDATE mode = (mode ^ 0x3)', array(
|
||||
User::$id, $type, $typeId, in_array($typeId, $includes) ? 2 : 1
|
||||
));
|
||||
DB::Aowow()->query('INSERT INTO ?_account_excludes (`userId`, `type`, `typeId`, `mode`) VALUES (?a) ON DUPLICATE KEY UPDATE `mode` = (`mode` ^ 0x3)',
|
||||
[User::$id, $type, $typeId, in_array($typeId, $includes) ? 2 : 1]
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ class AjaxComment extends AjaxHandler
|
||||
if ($this->_get['rating'] < 0)
|
||||
$val *= -1;
|
||||
|
||||
if (User::getCurDailyVotes() <= 0)
|
||||
if (User::getCurrentDailyVotes() <= 0)
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('tooManyVotes')]);
|
||||
else if (!$target || $val != $this->_get['rating'])
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
|
||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
||||
class AjaxData extends AjaxHandler
|
||||
{
|
||||
protected $_get = array(
|
||||
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale' ],
|
||||
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFrom' ],
|
||||
't' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'],
|
||||
'catg' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
|
||||
'skill' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkSkill' ],
|
||||
@@ -18,8 +18,8 @@ class AjaxData extends AjaxHandler
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
if (is_numeric($this->_get['locale']))
|
||||
User::useLocale($this->_get['locale']);
|
||||
if ($this->_get['locale']?->validate())
|
||||
Lang::load($this->_get['locale']);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleData';
|
||||
@@ -103,7 +103,7 @@ class AjaxData extends AjaxHandler
|
||||
case 'pets':
|
||||
case 'zones':
|
||||
if (!Util::loadStaticFile($set, $result, true) && Cfg::get('DEBUG'))
|
||||
$result .= "alert('could not fetch static data: ".$set." for locale: ".User::$localeString."');";
|
||||
$result .= "alert('could not fetch static data: ".$set." for locale: ".Lang::getLocale()->json()."');";
|
||||
|
||||
$result .= "\n\n";
|
||||
break;
|
||||
@@ -118,7 +118,7 @@ class AjaxData extends AjaxHandler
|
||||
|
||||
protected static function checkSkill(string $val) : array
|
||||
{
|
||||
return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val));
|
||||
return array_intersect(array_merge(SKILLS_TRADE_PRIMARY, [SKILL_FIRST_AID, SKILL_COOKING, SKILL_FISHING]), explode(',', $val));
|
||||
}
|
||||
|
||||
protected static function checkCallback(string $val) : bool
|
||||
|
||||
@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
|
||||
class AjaxLocale extends AjaxHandler
|
||||
{
|
||||
protected $_get = array(
|
||||
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale']
|
||||
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFrom']
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
@@ -23,8 +23,11 @@ class AjaxLocale extends AjaxHandler
|
||||
*/
|
||||
protected function handleLocale() : string
|
||||
{
|
||||
User::setLocale($this->_get['locale']);
|
||||
User::save();
|
||||
if ($this->_get['locale']?->validate())
|
||||
{
|
||||
User::$preferedLoc = $this->_get['locale'];
|
||||
User::save(true);
|
||||
}
|
||||
|
||||
return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '.';
|
||||
}
|
||||
|
||||
@@ -654,10 +654,10 @@ class AjaxProfile extends AjaxHandler
|
||||
{
|
||||
// get and apply inventory
|
||||
$gItems[$iId] = array(
|
||||
'name_'.User::$localeString => $phItems->getField('name', true),
|
||||
'quality' => $phItems->getField('quality'),
|
||||
'icon' => $phItems->getField('iconString'),
|
||||
'jsonequip' => $data[$iId]
|
||||
'name_'.Lang::getLocale()->json() => $phItems->getField('name', true),
|
||||
'quality' => $phItems->getField('quality'),
|
||||
'icon' => $phItems->getField('iconString'),
|
||||
'jsonequip' => $data[$iId]
|
||||
);
|
||||
$profile['inventory'][$slot] = [$iId, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
@@ -682,10 +682,10 @@ class AjaxProfile extends AjaxHandler
|
||||
{
|
||||
// get and apply inventory
|
||||
$gItems[$i['item']] = array(
|
||||
'name_'.User::$localeString => $itemz->getField('name', true),
|
||||
'quality' => $itemz->getField('quality'),
|
||||
'icon' => $itemz->getField('iconString'),
|
||||
'jsonequip' => $data[$i['item']]
|
||||
'name_'.Lang::getLocale()->json() => $itemz->getField('name', true),
|
||||
'quality' => $itemz->getField('quality'),
|
||||
'icon' => $itemz->getField('iconString'),
|
||||
'jsonequip' => $data[$i['item']]
|
||||
);
|
||||
$profile['inventory'][$i['slot']] = [$i['item'], $i['subItem'], $i['permEnchant'], $i['tempEnchant'], $i['gem1'], $i['gem2'], $i['gem3'], $i['gem4']];
|
||||
}
|
||||
@@ -719,7 +719,7 @@ class AjaxProfile extends AjaxHandler
|
||||
// }
|
||||
// }
|
||||
|
||||
// $buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', modifier:".Util::toJSON($mods)."});\n";
|
||||
// $buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', callback:".Util::toJSON($mods)."});\n";
|
||||
// }
|
||||
// $buff .= "\n";
|
||||
// }
|
||||
|
||||
@@ -1479,7 +1479,7 @@ abstract class Filter
|
||||
private function genericString($field, $value, $strFlags)
|
||||
{
|
||||
if ($strFlags & STR_LOCALIZED)
|
||||
$field .= '_loc'.User::$localeId;
|
||||
$field .= '_loc'.Lang::getLocale()->value;
|
||||
|
||||
return $this->modularizeString([$field], (string)$value, $strFlags & STR_MATCH_EXACT, $strFlags & STR_ALLOW_SHORT);
|
||||
}
|
||||
|
||||
@@ -139,21 +139,6 @@ define('U_GROUP_MODERATOR', (U_GROUP_ADMIN|U_GROUP_MOD|U_GROUP_B
|
||||
define('U_GROUP_COMMENTS_MODERATOR', (U_GROUP_MODERATOR|U_GROUP_LOCALIZER));
|
||||
define('U_GROUP_PREMIUM_PERMISSIONS', (U_GROUP_PREMIUM|U_GROUP_STAFF|U_GROUP_VIP));
|
||||
|
||||
// Locales
|
||||
define('LOCALE_EN', 0); // enGB, enUS
|
||||
define('LOCALE_KR', 1); // koKR [aowwo unused]
|
||||
define('LOCALE_FR', 2); // frFR
|
||||
define('LOCALE_DE', 3); // deDE
|
||||
define('LOCALE_CN', 4); // zhCN, enCN
|
||||
define('LOCALE_TW', 5); // zhTW, enTW [aowow unused]
|
||||
define('LOCALE_ES', 6); // esES
|
||||
define('LOCALE_MX', 7); // esMX [aowow unused]
|
||||
define('LOCALE_RU', 8); // ruRU
|
||||
define('LOCALE_JP', 9); // jaJP [aowow & 335 unused]
|
||||
define('LOCALE_PT', 10); // ptPT, ptBR [aowow unused]
|
||||
define('LOCALE_IT', 11); // itIT [aowow & 335 unused]
|
||||
define('LOCALE_MASK_ALL', 0b000101011101);
|
||||
|
||||
// red buttons on the top of the page
|
||||
define('BUTTON_WOWHEAD', 0);
|
||||
define('BUTTON_UPGRADE', 1);
|
||||
@@ -330,7 +315,6 @@ define('GUIDE_CU_NO_RATING', 0x200);
|
||||
|
||||
define('MAX_LEVEL', 80);
|
||||
define('MAX_SKILL', 450);
|
||||
define('MAX_LOCALES', 16); // technical limitation, 6 in use here
|
||||
define('WOW_BUILD', 12340);
|
||||
|
||||
// Loot handles
|
||||
|
||||
@@ -220,7 +220,7 @@ class Game
|
||||
$pages = [];
|
||||
while ($ptId)
|
||||
{
|
||||
if ($row = DB::World()->selectRow('SELECT ptl.Text AS Text_loc?d, pt.* FROM page_text pt LEFT JOIN page_text_locale ptl ON pt.ID = ptl.ID AND locale = ? WHERE pt.ID = ?d', User::$localeId, User::$localeString, $ptId))
|
||||
if ($row = DB::World()->selectRow('SELECT ptl.Text AS Text_loc?d, pt.* FROM page_text pt LEFT JOIN page_text_locale ptl ON pt.ID = ptl.ID AND locale = ? WHERE pt.ID = ?d', Lang::getLocale()->value, Lang::getLocale()->json(), $ptId))
|
||||
{
|
||||
$ptId = $row['NextPageID'];
|
||||
$pages[] = Util::parseHtmlText(Util::localizedString($row, 'Text'));
|
||||
@@ -392,28 +392,20 @@ class Game
|
||||
$quotes = [];
|
||||
$soundIds = [];
|
||||
|
||||
$quoteSrc = DB::World()->select('
|
||||
SELECT
|
||||
ct.GroupID AS ARRAY_KEY, ct.ID as ARRAY_KEY2,
|
||||
ct.`Type` AS `talkType`,
|
||||
ct.TextRange AS `range`,
|
||||
IFNULL(bct.`LanguageID`, ct.`Language`) AS lang,
|
||||
IFNULL(NULLIF(bct.Text, ""), IFNULL(NULLIF(bct.Text1, ""), IFNULL(ct.`Text`, ""))) AS text_loc0,
|
||||
{IFNULL(NULLIF(bctl.Text, ""), IFNULL(NULLIF(bctl.Text1, ""), IFNULL(ctl.Text, ""))) AS text_loc?d,}
|
||||
IF(bct.SoundEntriesID > 0, bct.SoundEntriesID, ct.Sound) AS soundId
|
||||
FROM
|
||||
creature_text ct
|
||||
{LEFT JOIN
|
||||
creature_text_locale ctl ON ct.CreatureID = ctl.CreatureID AND ct.GroupID = ctl.GroupID AND ct.ID = ctl.ID AND ctl.Locale = ?}
|
||||
LEFT JOIN
|
||||
broadcast_text bct ON ct.BroadcastTextId = bct.ID
|
||||
{LEFT JOIN
|
||||
broadcast_text_locale bctl ON ct.BroadcastTextId = bctl.ID AND bctl.locale = ?}
|
||||
WHERE
|
||||
ct.CreatureID = ?d',
|
||||
User::$localeId ?: DBSIMPLE_SKIP,
|
||||
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
|
||||
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
|
||||
$quoteSrc = DB::World()->select(
|
||||
'SELECT ct.`GroupID` AS ARRAY_KEY, ct.`ID` AS ARRAY_KEY2, ct.`Type` AS "talkType", ct.TextRange AS "range",
|
||||
IFNULL(bct.`LanguageID`, ct.`Language`) AS "lang",
|
||||
IFNULL(NULLIF(bct.`Text`, ""), IFNULL(NULLIF(bct.`Text1`, ""), IFNULL(ct.`Text`, ""))) AS "text_loc0",
|
||||
{ IFNULL(NULLIF(bctl.`Text`, ""), IFNULL(NULLIF(bctl.`Text1`, ""), IFNULL(ctl.`Text`, ""))) AS text_loc?d, }
|
||||
IF(bct.`SoundEntriesID` > 0, bct.`SoundEntriesID`, ct.`Sound`) AS "soundId"
|
||||
FROM creature_text ct
|
||||
{ LEFT JOIN creature_text_locale ctl ON ct.`CreatureID` = ctl.`CreatureID` AND ct.`GroupID` = ctl.`GroupID` AND ct.`ID` = ctl.`ID` AND ctl.`Locale` = ? }
|
||||
LEFT JOIN broadcast_text bct ON ct.`BroadcastTextId` = bct.`ID`
|
||||
{ LEFT JOIN broadcast_text_locale bctl ON ct.`BroadcastTextId` = bctl.`ID` AND bctl.`locale` = ? }
|
||||
WHERE ct.`CreatureID` = ?d',
|
||||
Lang::getLocale()->value ?: DBSIMPLE_SKIP,
|
||||
Lang::getLocale()->value ? Lang::getLocale()->json() : DBSIMPLE_SKIP,
|
||||
Lang::getLocale()->value ? Lang::getLocale()->json() : DBSIMPLE_SKIP,
|
||||
$creatureId
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
mb_internal_encoding('UTF-8');
|
||||
mysqli_report(MYSQLI_REPORT_ERROR);
|
||||
|
||||
define('AOWOW_REVISION', 39);
|
||||
define('AOWOW_REVISION', 40);
|
||||
define('OS_WIN', substr(PHP_OS, 0, 3) == 'WIN'); // OS_WIN as per compile info of php
|
||||
define('CLI', PHP_SAPI === 'cli');
|
||||
define('CLI_HAS_E', CLI && // WIN10 and later usually support ANSI escape sequences
|
||||
@@ -11,25 +11,30 @@ define('CLI_HAS_E', CLI && // WIN10 and later u
|
||||
|
||||
|
||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'/*, 'gmp'*/];
|
||||
$badExt = ['Intl']; // Intl contains its own class Locale. What? Namespaces? Never heard of those!
|
||||
$error = '';
|
||||
if ($ext = array_filter($reqExt, function($x) { return !extension_loaded($x); }))
|
||||
if ($ext = array_filter($reqExt, fn($x) => !extension_loaded($x)))
|
||||
$error .= 'Required Extension <b>'.implode(', ', $ext)."</b> was not found. Please check if it should exist, using \"<i>php -m</i>\"\n\n";
|
||||
|
||||
if (version_compare(PHP_VERSION, '8.0.0') < 0)
|
||||
$error .= 'PHP Version <b>8.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
|
||||
if ($ext = array_filter($badExt, fn($x) => extension_loaded($x)))
|
||||
$error .= 'Loaded Extension <b>'.implode(', ', $ext)."</b> is incompatible and must be disabled.\n\n";
|
||||
|
||||
if (version_compare(PHP_VERSION, '8.2.0') < 0)
|
||||
$error .= 'PHP Version <b>8.2</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
|
||||
|
||||
if ($error)
|
||||
die(CLI ? strip_tags($error) : $error);
|
||||
|
||||
|
||||
require_once 'includes/defines.php';
|
||||
require_once 'includes/locale.class.php';
|
||||
require_once 'includes/stats.class.php'; // Game entity statistics conversion
|
||||
require_once 'includes/libs/DbSimple/Generic.php'; // Libraray: http://en.dklab.ru/lib/DbSimple (using variant: https://github.com/ivan1986/DbSimple/tree/master)
|
||||
require_once 'includes/utilities.php'; // helper functions
|
||||
require_once 'includes/config.class.php'; // Config holder
|
||||
require_once 'includes/game.php'; // game related data & functions
|
||||
require_once 'includes/profiler.class.php';
|
||||
require_once 'includes/user.class.php';
|
||||
require_once 'includes/profiler.class.php'; // Profiler feature
|
||||
require_once 'includes/user.class.php'; // Session handling
|
||||
require_once 'includes/markup.class.php'; // manipulate markup text
|
||||
require_once 'includes/database.class.php'; // wrap DBSimple
|
||||
require_once 'includes/community.class.php'; // handle comments, screenshots and videos
|
||||
@@ -213,6 +218,12 @@ if (!CLI)
|
||||
if (User::init())
|
||||
User::save(); // save user-variables in session
|
||||
|
||||
// hard override locale for this call (should this be here..?)
|
||||
if (isset($_GET['locale']) && ($loc = Locale::tryFrom($_GET['locale'])))
|
||||
Lang::load($loc);
|
||||
else
|
||||
Lang::load(User::$preferedLoc);
|
||||
|
||||
// set up some logging (~10 queries will execute before we init the user and load the config)
|
||||
if (Cfg::get('DEBUG') >= CLI::LOG_INFO && User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
|
||||
{
|
||||
@@ -227,17 +238,6 @@ if (!CLI)
|
||||
DB::Characters($idx)->setLogger(['DB', 'profiler']);
|
||||
}
|
||||
|
||||
// hard-override locale for this call (should this be here..?)
|
||||
// all strings attached..
|
||||
if (isset($_GET['locale']))
|
||||
{
|
||||
$loc = intVal($_GET['locale']);
|
||||
if ($loc <= MAX_LOCALES && $loc >= 0 && (Cfg::get('LOCALES') & (1 << $loc)))
|
||||
User::useLocale($loc);
|
||||
}
|
||||
|
||||
Lang::load(User::$localeId);
|
||||
|
||||
// parse page-parameters .. sanitize before use!
|
||||
$str = explode('&', $_SERVER['QUERY_STRING'] ?? '', 2)[0];
|
||||
$_ = explode('=', $str, 2);
|
||||
@@ -245,6 +245,6 @@ if (!CLI)
|
||||
$pageParam = $_[1] ?? '';
|
||||
}
|
||||
else if (DB::isConnected(DB_AOWOW))
|
||||
Lang::load(LOCALE_EN);
|
||||
Lang::load(Locale::EN);
|
||||
|
||||
?>
|
||||
|
||||
209
includes/locale.class.php
Normal file
209
includes/locale.class.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
enum Locale : int
|
||||
{ // unused by TC WoW self
|
||||
case EN = 0; // enGB, enUS
|
||||
case KR = 1; // koKR ?
|
||||
case FR = 2; // frFR
|
||||
case DE = 3; // deDE
|
||||
case CN = 4; // zhCN, enCN
|
||||
case TW = 5; // zhTW, enTW x
|
||||
case ES = 6; // esES
|
||||
case MX = 7; // esMX x
|
||||
case RU = 8; // ruRU
|
||||
case JP = 9; // jaJP x x x
|
||||
case PT = 10; // ptPT, ptBR x ?
|
||||
case IT = 11; // itIT x x x
|
||||
|
||||
private const MASK_ALL = 0b000101011101; // technically supported locales
|
||||
|
||||
public function domain() : string // our subdomain / locale in web context
|
||||
{
|
||||
return match ($this)
|
||||
{
|
||||
self::EN => 'en',
|
||||
self::KR => 'kt',
|
||||
self::FR => 'fr',
|
||||
self::DE => 'de',
|
||||
self::CN => 'cn',
|
||||
self::TW => 'tw',
|
||||
self::ES => 'es',
|
||||
self::MX => 'mx',
|
||||
self::RU => 'ru',
|
||||
self::JP => 'jp',
|
||||
self::PT => 'pt',
|
||||
self::IT => 'it'
|
||||
};
|
||||
}
|
||||
|
||||
public function json() : string // internal usage / json string
|
||||
{
|
||||
return match ($this)
|
||||
{
|
||||
self::EN => 'enus',
|
||||
self::KR => 'kokr',
|
||||
self::FR => 'frfr',
|
||||
self::DE => 'dede',
|
||||
self::CN => 'zhcn',
|
||||
self::TW => 'zhtw',
|
||||
self::ES => 'eses',
|
||||
self::MX => 'esmx',
|
||||
self::RU => 'ruru',
|
||||
self::JP => 'jajp',
|
||||
self::PT => 'ptpt',
|
||||
self::IT => 'itit'
|
||||
};
|
||||
}
|
||||
|
||||
public function title() : string // localized language name
|
||||
{
|
||||
return match ($this)
|
||||
{
|
||||
self::EN => 'English',
|
||||
self::KR => '한국어',
|
||||
self::FR => 'Français',
|
||||
self::DE => 'Deutsch',
|
||||
self::CN => '简体中文',
|
||||
self::TW => '繁體中文',
|
||||
self::ES => 'Español',
|
||||
self::MX => 'Mexicano',
|
||||
self::RU => 'Русский',
|
||||
self::JP => '日本語',
|
||||
self::PT => 'Português',
|
||||
self::IT => 'Italiano'
|
||||
};
|
||||
}
|
||||
|
||||
public function gameDirs() : array // setup data source / wow client locale code
|
||||
{
|
||||
return match ($this)
|
||||
{
|
||||
self::EN => ['enGB', 'enUS', ''],
|
||||
self::KR => ['koKR'],
|
||||
self::FR => ['frFR'],
|
||||
self::DE => ['deDE'],
|
||||
self::CN => ['zhCN', 'enCN'],
|
||||
self::TW => ['zhTW', 'enTW'],
|
||||
self::ES => ['esES'],
|
||||
self::MX => ['esMX'],
|
||||
self::RU => ['ruRU'],
|
||||
self::JP => ['jaJP'],
|
||||
self::PT => ['ptPT', 'ptBR'],
|
||||
self::IT => ['itIT']
|
||||
};
|
||||
}
|
||||
|
||||
public function httpCode() : array // HTTP_ACCEPT_LANGUAGE
|
||||
{
|
||||
return match ($this)
|
||||
{
|
||||
self::EN => ['en', 'en-au', 'en-bz', 'en-ca', 'en-ie', 'en-jm', 'en-nz', 'en-ph', 'en-za', 'en-tt', 'en-gb', 'en-us', 'en-zw'],
|
||||
self::KR => ['ko', 'ko-kp', 'ko-kr'],
|
||||
self::FR => ['fr', 'fr-be', 'fr-ca', 'fr-fr', 'fr-lu', 'fr-mc', 'fr-ch'],
|
||||
self::DE => ['de', 'de-at', 'de-de', 'de-li', 'de-lu', 'de-ch'],
|
||||
self::CN => ['zh', 'zh-hk', 'zh-cn', 'zh-sg'],
|
||||
self::TW => ['tw', 'zh-tw'],
|
||||
self::ES => ['es', 'es-ar', 'es-bo', 'es-cl', 'es-co', 'es-cr', 'es-do', 'es-ec', 'es-sv', 'es-gt', 'es-hn', 'es-ni', 'es-pa', 'es-py', 'es-pe', 'es-pr', 'es-es', 'es-uy', 'es-ve'],
|
||||
self::MX => ['mx', 'es-mx'],
|
||||
self::RU => ['ru', 'ru-mo'],
|
||||
self::JP => ['ja'],
|
||||
self::PT => ['pt', 'pt-br'],
|
||||
self::IT => ['it', 'it-ch']
|
||||
};
|
||||
}
|
||||
|
||||
public function isLogographic() : bool
|
||||
{
|
||||
return $this == Locale::CN || $this == Locale::TW || $this == Locale::KR;
|
||||
}
|
||||
|
||||
public function validate() : ?self
|
||||
{
|
||||
return ($this->maskBit() & self::MASK_ALL & (Cfg::get('LOCALES') ?: 0xFFFF)) ? $this : null;
|
||||
}
|
||||
|
||||
public function maskBit() : int
|
||||
{
|
||||
return (1 << $this->value);
|
||||
}
|
||||
|
||||
public static function tryFromDomain(string $str) : ?self
|
||||
{
|
||||
foreach (self::cases() as $l)
|
||||
if ($l->validate() && $str == $l->domain())
|
||||
return $l;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function tryFromHttpAcceptLanguage(string $httpAccept) : ?self
|
||||
{
|
||||
if (!$httpAccept)
|
||||
return null;
|
||||
|
||||
$available = [];
|
||||
|
||||
// e.g.: de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
|
||||
foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $loc)
|
||||
if (preg_match('/([a-z\-]+)(?:\s*;\s*q\s*=\s*([\.\d]+))?/ui', $loc, $m, PREG_UNMATCHED_AS_NULL))
|
||||
$available[Util::lower($m[1])] = floatVal($m[2] ?? 1); // no quality set: assume 100%
|
||||
|
||||
arsort($available, SORT_NUMERIC); // highest quality on top
|
||||
|
||||
foreach ($available as $code => $_)
|
||||
foreach (self::cases() as $l)
|
||||
if ($l->validate() && in_array($code, $l->httpCode()))
|
||||
return $l;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getFallback() : self
|
||||
{
|
||||
foreach (Locale::cases() as $l)
|
||||
if ($l->validate())
|
||||
return $l;
|
||||
|
||||
// wow, you really fucked up your config mate!
|
||||
trigger_error('Locale::getFallback - there are no valid locales', E_USER_ERROR);
|
||||
return self::EN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The shape of things to come */
|
||||
class LocString
|
||||
{
|
||||
private WeakMap $store;
|
||||
|
||||
public function __construct(array $data, string $key = 'name', ?callable $callback = null)
|
||||
{
|
||||
$this->store = new WeakMap();
|
||||
|
||||
$callback ??= fn($x) => $x;
|
||||
|
||||
if (!array_filter($data, fn($v, $k) => $v && strstr($k, $key.'_loc'), ARRAY_FILTER_USE_BOTH))
|
||||
trigger_error('LocString - is entrirely empty', E_USER_WARNING);
|
||||
|
||||
foreach (Locale::cases() as $l)
|
||||
$this->store[$l] = (string)$callback($data[$key.'_loc'.$l->value] ?? '');
|
||||
}
|
||||
|
||||
public function __toString() : string
|
||||
{
|
||||
if ($str = $this->store[Lang::getLocale()])
|
||||
return $str;
|
||||
|
||||
foreach (Locale::cases() as $l) // desired loc not set, use any other
|
||||
if ($str = $this->store[$l])
|
||||
return Cfg::get('DEBUG') ? '['.$str.']' : $str;
|
||||
|
||||
return Cfg::get('DEBUG') ? '[LOCSTRING]' : '';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -918,16 +918,18 @@ class SmartAI
|
||||
$this->jsGlobals[Type::NPC][] = $e['param'][1];
|
||||
break;
|
||||
case SAI_EVENT_LINK: // 61 - Used to link together multiple events as a chain of events.
|
||||
$e['param'][10] = LANG::concat(DB::World()->selectCol('SELECT CONCAT("#[b]", id, "[/b]") FROM smart_scripts WHERE link = ?d AND entryorguid = ?d AND source_type = ?d', $this->itr['id'], $this->entry, $this->srcType), false);
|
||||
if ($links = DB::World()->selectCol('SELECT `id` FROM smart_scripts WHERE `link` = ?d AND `entryorguid` = ?d AND `source_type` = ?d', $this->itr['id'], $this->entry, $this->srcType))
|
||||
$e['param'][10] = LANG::concat($links, false, fn($x) => "#[b]".$x."[/b]");
|
||||
break;
|
||||
case SAI_EVENT_GOSSIP_SELECT: // 62 - On gossip clicked (gossip_menu_option335).
|
||||
$gmo = DB::World()->selectRow('SELECT gmo.OptionText AS text_loc0 {, gmol.OptionText AS text_loc?d}
|
||||
FROM gossip_menu_option gmo LEFT JOIN gossip_menu_option_locale gmol ON gmo.MenuID = gmol.MenuID AND gmo.OptionID = gmol.OptionID AND gmol.Locale = ?d
|
||||
WHERE gmo.MenuId = ?d AND gmo.OptionID = ?d',
|
||||
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
|
||||
User::$localeId,
|
||||
$e['param'][0],
|
||||
$e['param'][1]
|
||||
$gmo = DB::World()->selectRow(
|
||||
'SELECT gmo.`OptionText` AS "text_loc0" {, gmol.`OptionText` AS text_loc?d }
|
||||
FROM gossip_menu_option gmo
|
||||
LEFT JOIN gossip_menu_option_locale gmol ON gmo.`MenuID` = gmol.`MenuID` AND gmo.`OptionID` = gmol.`OptionID` AND gmol.`Locale` = ?d
|
||||
WHERE gmo.`MenuId` = ?d AND gmo.`OptionID` = ?d',
|
||||
Lang::getLocale() != Locale::EN ? Lang::getLocale()->json() : DBSIMPLE_SKIP,
|
||||
Lang::getLocale()->value,
|
||||
$e['param'][0], $e['param'][1]
|
||||
);
|
||||
|
||||
if ($gmo)
|
||||
@@ -941,11 +943,11 @@ class SmartAI
|
||||
break;
|
||||
case SAI_EVENT_DISTANCE_CREATURE: // 75 - On creature guid OR any instance of creature entry is within distance.
|
||||
if ($e['param'][0])
|
||||
$e['param'][10] = DB::World()->selectCell('SELECT id FROM creature WHERE guid = ?d', $e['param'][0]);
|
||||
$e['param'][10] = DB::World()->selectCell('SELECT `id` FROM creature WHERE `guid` = ?d', $e['param'][0]);
|
||||
// do not break;
|
||||
case SAI_EVENT_DISTANCE_GAMEOBJECT: // 76 - On gameobject guid OR any instance of gameobject entry is within distance.
|
||||
if ($e['param'][0] && !$e['param'][10])
|
||||
$e['param'][10] = DB::World()->selectCell('SELECT id FROM gameobject WHERE guid = ?d', $e['param'][0]);
|
||||
$e['param'][10] = DB::World()->selectCell('SELECT `id` FROM gameobject WHERE `guid` = ?d', $e['param'][0]);
|
||||
else if ($e['param'][1])
|
||||
$e['param'][10] = $e['param'][1];
|
||||
else if (!$e['param'][10])
|
||||
@@ -1244,7 +1246,7 @@ class SmartAI
|
||||
JOIN ?_taxinodes tn1 ON tp.startNodeId = tn1.id
|
||||
JOIN ?_taxinodes tn2 ON tp.endNodeId = tn2.id
|
||||
WHERE tp.id = ?d',
|
||||
User::$localeId, User::$localeId, User::$localeId, User::$localeId, $a['param'][0]
|
||||
Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, $a['param'][0]
|
||||
);
|
||||
$a['param'][6] = Util::localizedString($nodes, 'start');
|
||||
$a['param'][7] = Util::localizedString($nodes, 'end');
|
||||
|
||||
@@ -343,9 +343,9 @@ class AchievementListFilter extends Filter
|
||||
{
|
||||
$_ = [];
|
||||
if (isset($_v['ex']) && $_v['ex'] == 'on')
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'reward_loc'.User::$localeId, 'description_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'reward_loc'.Lang::getLocale()->value, 'description_loc'.Lang::getLocale()->value]);
|
||||
else
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
|
||||
|
||||
if ($_)
|
||||
$parts[] = $_;
|
||||
|
||||
@@ -353,9 +353,9 @@ class CreatureListFilter extends Filter
|
||||
{
|
||||
$_ = [];
|
||||
if (isset($_v['ex']) && $_v['ex'] == 'on')
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'subname_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'subname_loc'.Lang::getLocale()->value]);
|
||||
else
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
|
||||
|
||||
if ($_)
|
||||
$parts[] = $_;
|
||||
|
||||
@@ -13,7 +13,7 @@ class EnchantmentList extends BaseType
|
||||
public static $dataTable = '?_itemenchantment';
|
||||
|
||||
private $jsonStats = [];
|
||||
private $relSpells = [];
|
||||
private SpellList $relSpells;
|
||||
private $triggerIds = [];
|
||||
|
||||
protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie';
|
||||
@@ -26,6 +26,8 @@ class EnchantmentList extends BaseType
|
||||
{
|
||||
parent::__construct($conditions, $miscData);
|
||||
|
||||
$relSpells = [];
|
||||
|
||||
// post processing
|
||||
foreach ($this->iterate() as &$curTpl)
|
||||
{
|
||||
@@ -40,15 +42,15 @@ class EnchantmentList extends BaseType
|
||||
case ENCHANTMENT_TYPE_COMBAT_SPELL:
|
||||
$proc = -$this->getField('ppmRate') ?: ($this->getField('procChance') ?: $this->getField('amount'.$i));
|
||||
$curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_HIT, $curTpl['charges'], $proc];
|
||||
$this->relSpells[] = $curTpl['object'.$i];
|
||||
$relSpells[] = $curTpl['object'.$i];
|
||||
break;
|
||||
case ENCHANTMENT_TYPE_EQUIP_SPELL:
|
||||
$curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_EQUIP, $curTpl['charges'], 0];
|
||||
$this->relSpells[] = $curTpl['object'.$i];
|
||||
$relSpells[] = $curTpl['object'.$i];
|
||||
break;
|
||||
case ENCHANTMENT_TYPE_USE_SPELL:
|
||||
$curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_USE, $curTpl['charges'], 0];
|
||||
$this->relSpells[] = $curTpl['object'.$i];
|
||||
$relSpells[] = $curTpl['object'.$i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -56,8 +58,8 @@ class EnchantmentList extends BaseType
|
||||
$this->jsonStats[$this->id] = (new StatsContainer)->fromJson($curTpl, true);
|
||||
}
|
||||
|
||||
if ($this->relSpells)
|
||||
$this->relSpells = new SpellList(array(['id', $this->relSpells]));
|
||||
if ($relSpells)
|
||||
$this->relSpells = new SpellList(array(['id', $relSpells]));
|
||||
}
|
||||
|
||||
// use if you JUST need the name
|
||||
@@ -241,7 +243,7 @@ class EnchantmentListFilter extends Filter
|
||||
|
||||
//string
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
|
||||
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
|
||||
$parts[] = $_;
|
||||
|
||||
// type
|
||||
|
||||
@@ -180,7 +180,7 @@ class GameObjectListFilter extends Filter
|
||||
|
||||
// name
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
|
||||
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
|
||||
$parts[] = $_;
|
||||
|
||||
return $parts;
|
||||
|
||||
@@ -1935,7 +1935,7 @@ class ItemListFilter extends Filter
|
||||
104 => [FILTER_CR_STRING, 'description', STR_LOCALIZED ], // flavortext
|
||||
105 => [FILTER_CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 1 ], // dropsinnormal [heroicdungeon-any]
|
||||
106 => [FILTER_CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 2 ], // dropsinheroic [heroicdungeon-any]
|
||||
107 => [FILTER_CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.User::$localeId, $cr[2]]
|
||||
107 => [FILTER_CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.Lang::getLocale()->value, $cr[2]]
|
||||
109 => [FILTER_CR_CALLBACK, 'cbArmorBonus', null, null ], // armorbonus [op] [int]
|
||||
111 => [FILTER_CR_NUMERIC, 'requiredSkillRank', NUM_CAST_INT, true ], // reqskillrank
|
||||
113 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
|
||||
@@ -2122,7 +2122,7 @@ class ItemListFilter extends Filter
|
||||
|
||||
// name
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
|
||||
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
|
||||
$parts[] = $_;
|
||||
|
||||
// usable-by (not excluded by requiredClass && armor or weapons match mask from ?_classes)
|
||||
@@ -2277,7 +2277,7 @@ class ItemListFilter extends Filter
|
||||
$n = preg_replace(Filter::PATTERN_NAME, '', $cr[2]);
|
||||
$n = $this->transformString($n, false);
|
||||
|
||||
$randIds = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, ABS(`id`) AS `id`, name_loc?d, `name_loc0` FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', User::$localeId, User::$localeId, $n);
|
||||
$randIds = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, ABS(`id`) AS `id`, name_loc?d, `name_loc0` FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', Lang::getLocale()->value, Lang::getLocale()->value, $n);
|
||||
$tplIds = $randIds ? DB::World()->select('SELECT `entry`, `ench` FROM item_enchantment_template WHERE `ench` IN (?a)', array_column($randIds, 'id')) : [];
|
||||
foreach ($tplIds as &$set)
|
||||
{
|
||||
|
||||
@@ -211,7 +211,7 @@ class ItemsetListFilter extends Filter
|
||||
|
||||
// name [str]
|
||||
if (isset($_v['na']))
|
||||
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
|
||||
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
|
||||
$parts[] = $_;
|
||||
|
||||
// quality [enum]
|
||||
|
||||
@@ -498,9 +498,9 @@ class QuestListFilter extends Filter
|
||||
{
|
||||
$_ = [];
|
||||
if (isset($_v['ex']) && $_v['ex'] == 'on')
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'objectives_loc'.User::$localeId, 'details_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'objectives_loc'.Lang::getLocale()->value, 'details_loc'.Lang::getLocale()->value]);
|
||||
else
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
|
||||
|
||||
if ($_)
|
||||
$parts[] = $_;
|
||||
|
||||
@@ -1436,8 +1436,8 @@ class SpellList extends BaseType
|
||||
$this->charLevel = $level;
|
||||
|
||||
// step -1: already handled?
|
||||
if (isset($this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive]))
|
||||
return $this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive];
|
||||
if (isset($this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive]))
|
||||
return $this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive];
|
||||
|
||||
// step 0: get text
|
||||
$data = $this->getField($type, true);
|
||||
@@ -1543,7 +1543,7 @@ class SpellList extends BaseType
|
||||
$data = strtr($data, ["\r" => '', "\n" => '<br />']);
|
||||
|
||||
// cache result
|
||||
$this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive] = [$data, $relSpells, $this->scaling[$this->id]];
|
||||
$this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive] = [$data, $relSpells, $this->scaling[$this->id]];
|
||||
|
||||
return [$data, $relSpells, $this->scaling[$this->id]];
|
||||
}
|
||||
@@ -2451,9 +2451,9 @@ class SpellListFilter extends Filter
|
||||
{
|
||||
$_ = [];
|
||||
if (isset($_v['ex']) && $_v['ex'] == 'on')
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'buff_loc'.User::$localeId, 'description_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'buff_loc'.Lang::getLocale()->value, 'description_loc'.Lang::getLocale()->value]);
|
||||
else
|
||||
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
|
||||
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
|
||||
|
||||
if ($_)
|
||||
$parts[] = $_;
|
||||
|
||||
@@ -45,9 +45,13 @@ class TitleList extends BaseType
|
||||
unset($_curTpl['src3']);
|
||||
|
||||
// shorthand for more generic access
|
||||
foreach (Util::$localeStrings as $i => $str)
|
||||
if ($str)
|
||||
$_curTpl['name_loc'.$i] = trim(str_replace('%s', '', $_curTpl['male_loc'.$i]));
|
||||
// i don't see it being used anywhere..?
|
||||
/*
|
||||
foreach (Locale::cases() as $loc)
|
||||
if ($loc->validate())
|
||||
$_curTpl['name'] = new LocString($_curTpl, 'male', fn($x) => trim(str_replace('%s', '', $x)));
|
||||
// $_curTpl['name_loc'.$loc->value] = trim(str_replace('%s', '', $_curTpl['male_loc'.$loc->value]));
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,28 +6,34 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class User
|
||||
{
|
||||
public static $id = 0;
|
||||
public static $displayName = '';
|
||||
public static $banStatus = 0x0; // see ACC_BAN_* defines
|
||||
public static $groups = 0x0;
|
||||
public static $perms = 0;
|
||||
public static $localeId = 0;
|
||||
public static $localeString = 'enus';
|
||||
public static $avatar = 'inv_misc_questionmark';
|
||||
public static $dailyVotes = 0;
|
||||
public static int $id = 0;
|
||||
public static string $displayName = '';
|
||||
public static int $banStatus = 0x0; // see ACC_BAN_* defines
|
||||
public static int $groups = 0x0;
|
||||
public static int $perms = 0;
|
||||
public static string $avatar = 'inv_misc_questionmark';
|
||||
public static int $dailyVotes = 0;
|
||||
public static $ip = null;
|
||||
|
||||
private static $reputation = 0;
|
||||
private static $dataKey = '';
|
||||
private static $expires = false;
|
||||
private static $passHash = '';
|
||||
private static $excludeGroups = 1;
|
||||
private static $profiles = null;
|
||||
private static int $reputation = 0;
|
||||
private static string $dataKey = '';
|
||||
private static bool $expires = false;
|
||||
private static string $passHash = '';
|
||||
private static int $excludeGroups = 1;
|
||||
|
||||
public static Locale $preferedLoc;
|
||||
private static LocalProfileList $profiles;
|
||||
|
||||
public static function init()
|
||||
{
|
||||
self::setIP();
|
||||
self::setLocale();
|
||||
|
||||
if (isset($_SESSION['locale']) && $_SESSION['locale'] instanceof Locale)
|
||||
self::$preferedLoc = $_SESSION['locale']->validate() ?? Locale::getFallback();
|
||||
else if (!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]) && ($loc = Locale::tryFromHttpAcceptLanguage($_SERVER["HTTP_ACCEPT_LANGUAGE"])))
|
||||
self::$preferedLoc = $loc;
|
||||
else
|
||||
self::$preferedLoc = Locale::getFallback();
|
||||
|
||||
// session have a dataKey to access the JScripts (yes, also the anons)
|
||||
if (empty($_SESSION['dataKey']))
|
||||
@@ -39,12 +45,12 @@ class User
|
||||
return false;
|
||||
|
||||
// check IP bans
|
||||
if ($ipBan = DB::Aowow()->selectRow('SELECT count, unbanDate FROM ?_account_bannedips WHERE ip = ? AND type = 0', self::$ip))
|
||||
if ($ipBan = DB::Aowow()->selectRow('SELECT `count`, `unbanDate` FROM ?_account_bannedips WHERE `ip` = ? AND `type` = 0', self::$ip))
|
||||
{
|
||||
if ($ipBan['count'] > Cfg::get('ACC_FAILED_AUTH_COUNT') && $ipBan['unbanDate'] > time())
|
||||
return false;
|
||||
else if ($ipBan['unbanDate'] <= time())
|
||||
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE ip = ?', self::$ip);
|
||||
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE `ip` = ?', self::$ip);
|
||||
}
|
||||
|
||||
// try to restore session
|
||||
@@ -55,36 +61,39 @@ class User
|
||||
if (!empty($_SESSION['timeout']) && $_SESSION['timeout'] <= time())
|
||||
return false;
|
||||
|
||||
$query = DB::Aowow()->SelectRow('
|
||||
SELECT a.id, a.passHash, a.displayName, a.locale, a.userGroups, a.userPerms, a.allowExpire, BIT_OR(ab.typeMask) AS bans, IFNULL(SUM(r.amount), 0) as reputation, a.avatar, a.dailyVotes, a.excludeGroups
|
||||
$uData = DB::Aowow()->SelectRow(
|
||||
'SELECT a.`id`, a.`passHash`, a.`displayName`, a.`locale`, a.`userGroups`, a.`userPerms`, a.`allowExpire`, BIT_OR(ab.`typeMask`) AS "bans", IFNULL(SUM(r.`amount`), 0) AS "reputation", a.`avatar`, a.`dailyVotes`, a.`excludeGroups`
|
||||
FROM ?_account a
|
||||
LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP()
|
||||
LEFT JOIN ?_account_reputation r ON a.id = r.userId
|
||||
WHERE a.id = ?d
|
||||
GROUP BY a.id',
|
||||
LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP()
|
||||
LEFT JOIN ?_account_reputation r ON a.`id` = r.`userId`
|
||||
WHERE a.`id` = ?d
|
||||
GROUP BY a.`id`',
|
||||
$_SESSION['user']
|
||||
);
|
||||
|
||||
if (!$query)
|
||||
if (!$uData)
|
||||
return false;
|
||||
|
||||
if ($loc = Locale::tryFrom($uData['locale']))
|
||||
self::$preferedLoc = $loc;
|
||||
|
||||
// password changed, terminate session
|
||||
if (AUTH_MODE_SELF && $query['passHash'] != $_SESSION['hash'])
|
||||
if (AUTH_MODE_SELF && $uData['passHash'] != $_SESSION['hash'])
|
||||
{
|
||||
self::destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$id = intval($query['id']);
|
||||
self::$displayName = $query['displayName'];
|
||||
self::$passHash = $query['passHash'];
|
||||
self::$expires = (bool)$query['allowExpire'];
|
||||
self::$reputation = $query['reputation'];
|
||||
self::$banStatus = $query['bans'];
|
||||
self::$groups = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userGroups']);
|
||||
self::$perms = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userPerms']);
|
||||
self::$dailyVotes = $query['dailyVotes'];
|
||||
self::$excludeGroups = $query['excludeGroups'];
|
||||
self::$id = intVal($uData['id']);
|
||||
self::$displayName = $uData['displayName'];
|
||||
self::$passHash = $uData['passHash'];
|
||||
self::$expires = (bool)$uData['allowExpire'];
|
||||
self::$reputation = $uData['reputation'];
|
||||
self::$banStatus = $uData['bans'];
|
||||
self::$groups = $uData['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($uData['userGroups']);
|
||||
self::$perms = $uData['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($uData['userPerms']);
|
||||
self::$dailyVotes = $uData['dailyVotes'];
|
||||
self::$excludeGroups = $uData['excludeGroups'];
|
||||
|
||||
$conditions = array(
|
||||
[['cuFlags', PROFILER_CU_DELETED, '&'], 0],
|
||||
@@ -96,11 +105,8 @@ class User
|
||||
|
||||
self::$profiles = (new LocalProfileList($conditions));
|
||||
|
||||
if ($query['avatar'])
|
||||
self::$avatar = $query['avatar'];
|
||||
|
||||
if (self::$localeId != $query['locale']) // reset, if changed
|
||||
self::setLocale(intVal($query['locale']));
|
||||
if ($uData['avatar'])
|
||||
self::$avatar = $uData['avatar'];
|
||||
|
||||
// stuff, that updates on a daily basis goes here (if you keep you session alive indefinitly, the signin-handler doesn't do very much)
|
||||
// - conscutive visits
|
||||
@@ -115,10 +121,10 @@ class User
|
||||
// daily votes (we need to reset this one)
|
||||
self::$dailyVotes = self::getMaxDailyVotes();
|
||||
|
||||
DB::Aowow()->query('
|
||||
UPDATE ?_account
|
||||
SET dailyVotes = ?d, prevLogin = curLogin, curLogin = UNIX_TIMESTAMP(), prevIP = curIP, curIP = ?
|
||||
WHERE id = ?d',
|
||||
DB::Aowow()->query(
|
||||
'UPDATE ?_account
|
||||
SET `dailyVotes` = ?d, `prevLogin` = `curLogin`, `curLogin` = UNIX_TIMESTAMP(), `prevIP` = `curIP`, `curIP` = ?
|
||||
WHERE `id` = ?d',
|
||||
self::$dailyVotes,
|
||||
self::$ip,
|
||||
self::$id
|
||||
@@ -131,16 +137,16 @@ class User
|
||||
// increment consecutive visits (next day or first of new month and not more than 48h)
|
||||
// i bet my ass i forgott a corner case
|
||||
if ((date('j', $lastLogin) + 1 == date('j') || (date('j') == 1 && date('n', $lastLogin) != date('n'))) && (time() - $lastLogin) < 2 * DAY)
|
||||
DB::Aowow()->query('UPDATE ?_account SET consecutiveVisits = consecutiveVisits + 1 WHERE id = ?d', self::$id);
|
||||
DB::Aowow()->query('UPDATE ?_account SET `consecutiveVisits` = `consecutiveVisits` + 1 WHERE `id` = ?d', self::$id);
|
||||
else
|
||||
DB::Aowow()->query('UPDATE ?_account SET consecutiveVisits = 0 WHERE id = ?d', self::$id);
|
||||
DB::Aowow()->query('UPDATE ?_account SET `consecutiveVisits` = 0 WHERE `id` = ?d', self::$id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function setIP()
|
||||
private static function setIP() : void
|
||||
{
|
||||
$ipAddr = '';
|
||||
$method = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'];
|
||||
@@ -165,68 +171,32 @@ class User
|
||||
self::$ip = $ipAddr ?: null;
|
||||
}
|
||||
|
||||
/****************/
|
||||
/* set language */
|
||||
/****************/
|
||||
|
||||
// set and save
|
||||
public static function setLocale($set = -1)
|
||||
public static function save(bool $toDB = false)
|
||||
{
|
||||
$loc = LOCALE_EN;
|
||||
$_SESSION['user'] = self::$id;
|
||||
$_SESSION['hash'] = self::$passHash;
|
||||
$_SESSION['locale'] = self::$preferedLoc;
|
||||
$_SESSION['timeout'] = self::$expires ? time() + Cfg::get('SESSION_TIMEOUT_DELAY') : 0;
|
||||
// $_SESSION['dataKey'] does not depend on user login status and is set in User::init()
|
||||
|
||||
// get
|
||||
if ($set != -1 && isset(Util::$localeStrings[$set]))
|
||||
$loc = $set;
|
||||
else if (isset($_SESSION['locale']) && isset(Util::$localeStrings[$_SESSION['locale']]))
|
||||
$loc = $_SESSION['locale'];
|
||||
else if (!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
|
||||
{
|
||||
$loc = strtolower(substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2));
|
||||
switch ($loc) {
|
||||
case 'fr': $loc = LOCALE_FR; break;
|
||||
case 'de': $loc = LOCALE_DE; break;
|
||||
case 'zh': $loc = LOCALE_CN; break; // may cause issues in future with zh-tw
|
||||
case 'es': $loc = LOCALE_ES; break;
|
||||
case 'ru': $loc = LOCALE_RU; break;
|
||||
default: $loc = LOCALE_EN;
|
||||
}
|
||||
}
|
||||
|
||||
// check; pick first viable if failed
|
||||
$allowedLoc = Cfg::get('LOCALES');
|
||||
if ($allowedLoc && !($allowedLoc & (1 << $loc)))
|
||||
{
|
||||
foreach (Util::$localeStrings as $idx => $__)
|
||||
{
|
||||
if ($allowedLoc & (1 << $idx))
|
||||
{
|
||||
$loc = $idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set
|
||||
if (self::$id)
|
||||
DB::Aowow()->query('UPDATE ?_account SET locale = ? WHERE id = ?', $loc, self::$id);
|
||||
|
||||
self::useLocale($loc);
|
||||
if (self::$id && $toDB)
|
||||
DB::Aowow()->query('UPDATE ?_account SET `locale` = ? WHERE `id` = ?', self::$preferedLoc->value, self::$id);
|
||||
}
|
||||
|
||||
// only use once
|
||||
public static function useLocale($use)
|
||||
public static function destroy()
|
||||
{
|
||||
self::$localeId = isset(Util::$localeStrings[$use]) ? $use : LOCALE_EN;
|
||||
self::$localeString = self::localeString(self::$localeId);
|
||||
session_regenerate_id(true); // session itself is not destroyed; status changed => regenerate id
|
||||
session_unset();
|
||||
|
||||
$_SESSION['locale'] = self::$preferedLoc; // keep locale
|
||||
$_SESSION['dataKey'] = self::$dataKey; // keep dataKey
|
||||
|
||||
self::$id = 0;
|
||||
self::$displayName = '';
|
||||
self::$perms = 0;
|
||||
self::$groups = U_GROUP_NONE;
|
||||
}
|
||||
|
||||
private static function localeString($loc = -1)
|
||||
{
|
||||
if (!isset(Util::$localeStrings[$loc]))
|
||||
$loc = 0;
|
||||
|
||||
return Util::$localeStrings[$loc];
|
||||
}
|
||||
|
||||
/*******************/
|
||||
/* auth mechanisms */
|
||||
@@ -245,21 +215,21 @@ class User
|
||||
return AUTH_INTERNAL_ERR;
|
||||
|
||||
// handle login try limitation
|
||||
$ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip);
|
||||
$ip = DB::Aowow()->selectRow('SELECT `ip`, `count`, `unbanDate` FROM ?_account_bannedips WHERE `type` = 0 AND `ip` = ?', self::$ip);
|
||||
if (!$ip || $ip['unbanDate'] < time()) // no entry exists or time expired; set count to 1
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, Cfg::get('ACC_FAILED_AUTH_BLOCK'));
|
||||
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (`ip`, `type`, `count`, `unbanDate`) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, Cfg::get('ACC_FAILED_AUTH_BLOCK'));
|
||||
else // entry already exists; increment count
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ?', Cfg::get('ACC_FAILED_AUTH_BLOCK'), self::$ip);
|
||||
DB::Aowow()->query('UPDATE ?_account_bannedips SET `count` = `count` + 1, `unbanDate` = UNIX_TIMESTAMP() + ?d WHERE `ip` = ?', Cfg::get('ACC_FAILED_AUTH_BLOCK'), self::$ip);
|
||||
|
||||
if ($ip && $ip['count'] >= Cfg::get('ACC_FAILED_AUTH_COUNT') && $ip['unbanDate'] >= time())
|
||||
return AUTH_IPBANNED;
|
||||
|
||||
$query = DB::Aowow()->SelectRow('
|
||||
SELECT a.id, a.passHash, BIT_OR(ab.typeMask) AS bans, a.status
|
||||
$query = DB::Aowow()->SelectRow(
|
||||
'SELECT a.`id`, a.`passHash`, BIT_OR(ab.`typeMask`) AS "bans", a.`status`
|
||||
FROM ?_account a
|
||||
LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP()
|
||||
WHERE a.user = ?
|
||||
GROUP BY a.id',
|
||||
LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP()
|
||||
WHERE a.`user` = ?
|
||||
GROUP BY a.`id`',
|
||||
$name
|
||||
);
|
||||
if (!$query)
|
||||
@@ -270,7 +240,7 @@ class User
|
||||
return AUTH_WRONGPASS;
|
||||
|
||||
// successfull auth; clear bans for this IP
|
||||
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip);
|
||||
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE `type` = 0 AND `ip` = ?', self::$ip);
|
||||
|
||||
if ($query['bans'] & (ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return AUTH_BANNED;
|
||||
@@ -304,10 +274,19 @@ class User
|
||||
case AUTH_MODE_EXTERNAL:
|
||||
{
|
||||
if (!file_exists('config/extAuth.php'))
|
||||
{
|
||||
trigger_error('config/extAuth.php not found');
|
||||
return AUTH_INTERNAL_ERR;
|
||||
}
|
||||
|
||||
require 'config/extAuth.php';
|
||||
|
||||
if (!function_exists('extAuth'))
|
||||
{
|
||||
trigger_error('external auth function extAuth() not defined in config/extAuth.php');
|
||||
return AUTH_INTERNAL_ERR;
|
||||
}
|
||||
|
||||
$extGroup = -1;
|
||||
$result = extAuth($name, $pass, $extId, $extGroup);
|
||||
|
||||
@@ -335,27 +314,22 @@ class User
|
||||
return AUTH_OK;
|
||||
}
|
||||
|
||||
// create a linked account for our settings if nessecary
|
||||
private static function checkOrCreateInDB($extId, $name, $userGroup = -1)
|
||||
// create a linked account for our settings if necessary
|
||||
private static function checkOrCreateInDB(int $extId, string $name, int $userGroup = -1) : int
|
||||
{
|
||||
if (!intVal($extId))
|
||||
return 0;
|
||||
|
||||
$userGroup = intVal($userGroup);
|
||||
|
||||
if ($_ = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE extId = ?d', $extId))
|
||||
if ($_ = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `extId` = ?d', $extId))
|
||||
{
|
||||
if ($userGroup >= U_GROUP_NONE)
|
||||
DB::Aowow()->query('UPDATE ?_account SET userGroups = ?d WHERE extId = ?d', $userGroup, $extId);
|
||||
DB::Aowow()->query('UPDATE ?_account SET `userGroups` = ?d WHERE `extId` = ?d', $userGroup, $extId);
|
||||
return $_;
|
||||
}
|
||||
|
||||
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (extId, user, displayName, joinDate, prevIP, prevLogin, locale, status, userGroups) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)',
|
||||
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (`extId`, `user`, `displayName`, `joinDate`, `prevIP`, `prevLogin`, `locale`, `status`, `userGroups`) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)',
|
||||
$extId,
|
||||
$name,
|
||||
Util::ucFirst($name),
|
||||
isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '',
|
||||
User::$localeId,
|
||||
$_SERVER["REMOTE_ADDR"] ?? '',
|
||||
self::$preferedLoc->value,
|
||||
ACC_STATUS_OK,
|
||||
$userGroup >= U_GROUP_NONE ? $userGroup : U_GROUP_NONE
|
||||
);
|
||||
@@ -439,39 +413,17 @@ class User
|
||||
return $errCode == 0;
|
||||
}
|
||||
|
||||
public static function save()
|
||||
{
|
||||
$_SESSION['user'] = self::$id;
|
||||
$_SESSION['hash'] = self::$passHash;
|
||||
$_SESSION['locale'] = self::$localeId;
|
||||
$_SESSION['timeout'] = self::$expires ? time() + Cfg::get('SESSION_TIMEOUT_DELAY') : 0;
|
||||
// $_SESSION['dataKey'] does not depend on user login status and is set in User::init()
|
||||
}
|
||||
|
||||
public static function destroy()
|
||||
{
|
||||
session_regenerate_id(true); // session itself is not destroyed; status changed => regenerate id
|
||||
session_unset();
|
||||
|
||||
$_SESSION['locale'] = self::$localeId; // keep locale
|
||||
$_SESSION['dataKey'] = self::$dataKey; // keep dataKey
|
||||
|
||||
self::$id = 0;
|
||||
self::$displayName = '';
|
||||
self::$perms = 0;
|
||||
self::$groups = U_GROUP_NONE;
|
||||
}
|
||||
|
||||
/*********************/
|
||||
/* access management */
|
||||
/*********************/
|
||||
|
||||
public static function isInGroup($group)
|
||||
public static function isInGroup($group) : bool
|
||||
{
|
||||
return (self::$groups & $group) != 0;
|
||||
}
|
||||
|
||||
public static function canComment()
|
||||
public static function canComment() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -479,7 +431,7 @@ class User
|
||||
return self::$perms || self::$reputation >= Cfg::get('REP_REQ_COMMENT');
|
||||
}
|
||||
|
||||
public static function canReply()
|
||||
public static function canReply() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -487,7 +439,7 @@ class User
|
||||
return self::$perms || self::$reputation >= Cfg::get('REP_REQ_REPLY');
|
||||
}
|
||||
|
||||
public static function canUpvote()
|
||||
public static function canUpvote() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -495,7 +447,7 @@ class User
|
||||
return self::$perms || (self::$reputation >= Cfg::get('REP_REQ_UPVOTE') && self::$dailyVotes > 0);
|
||||
}
|
||||
|
||||
public static function canDownvote()
|
||||
public static function canDownvote() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_RATE | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -503,7 +455,7 @@ class User
|
||||
return self::$perms || (self::$reputation >= Cfg::get('REP_REQ_DOWNVOTE') && self::$dailyVotes > 0);
|
||||
}
|
||||
|
||||
public static function canSupervote()
|
||||
public static function canSupervote() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_RATE | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -511,7 +463,7 @@ class User
|
||||
return self::$reputation >= Cfg::get('REP_REQ_SUPERVOTE');
|
||||
}
|
||||
|
||||
public static function canUploadScreenshot()
|
||||
public static function canUploadScreenshot() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_SCREENSHOT | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -519,7 +471,7 @@ class User
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function canWriteGuide()
|
||||
public static function canWriteGuide() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_GUIDE | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -527,7 +479,7 @@ class User
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function canSuggestVideo()
|
||||
public static function canSuggestVideo() : bool
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_VIDEO | ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return false;
|
||||
@@ -535,27 +487,28 @@ class User
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function isPremium()
|
||||
public static function isPremium() : bool
|
||||
{
|
||||
return self::isInGroup(U_GROUP_PREMIUM) || self::$reputation >= Cfg::get('REP_REQ_PREMIUM');
|
||||
}
|
||||
|
||||
|
||||
/**************/
|
||||
/* js-related */
|
||||
/**************/
|
||||
|
||||
public static function decrementDailyVotes()
|
||||
public static function decrementDailyVotes() : void
|
||||
{
|
||||
self::$dailyVotes--;
|
||||
DB::Aowow()->query('UPDATE ?_account SET dailyVotes = ?d WHERE id = ?d', self::$dailyVotes, self::$id);
|
||||
DB::Aowow()->query('UPDATE ?_account SET `dailyVotes` = ?d WHERE `id` = ?d', self::$dailyVotes, self::$id);
|
||||
}
|
||||
|
||||
public static function getCurDailyVotes()
|
||||
public static function getCurrentDailyVotes() : int
|
||||
{
|
||||
return self::$dailyVotes;
|
||||
}
|
||||
|
||||
public static function getMaxDailyVotes()
|
||||
public static function getMaxDailyVotes() : int
|
||||
{
|
||||
if (!self::$id || self::$banStatus & (ACC_BAN_PERM | ACC_BAN_TEMP))
|
||||
return 0;
|
||||
@@ -563,12 +516,12 @@ class User
|
||||
return Cfg::get('USER_MAX_VOTES') + (self::$reputation >= Cfg::get('REP_REQ_VOTEMORE_BASE') ? 1 + intVal((self::$reputation - Cfg::get('REP_REQ_VOTEMORE_BASE')) / Cfg::get('REP_REQ_VOTEMORE_ADD')) : 0);
|
||||
}
|
||||
|
||||
public static function getReputation()
|
||||
public static function getReputation() : int
|
||||
{
|
||||
return self::$reputation;
|
||||
}
|
||||
|
||||
public static function getUserGlobals()
|
||||
public static function getUserGlobals() : array
|
||||
{
|
||||
$gUser = array(
|
||||
'id' => self::$id,
|
||||
@@ -613,34 +566,34 @@ class User
|
||||
return $gUser;
|
||||
}
|
||||
|
||||
public static function getWeightScales()
|
||||
public static function getWeightScales() : array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
$res = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, name FROM ?_account_weightscales WHERE userId = ?d', self::$id);
|
||||
$res = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `name` FROM ?_account_weightscales WHERE `userId` = ?d', self::$id);
|
||||
if (!$res)
|
||||
return $result;
|
||||
|
||||
$weights = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, `field` AS ARRAY_KEY2, val FROM ?_account_weightscale_data WHERE id IN (?a)', array_keys($res));
|
||||
$weights = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `field` AS ARRAY_KEY2, `val` FROM ?_account_weightscale_data WHERE `id` IN (?a)', array_keys($res));
|
||||
foreach ($weights as $id => $data)
|
||||
$result[] = array_merge(['name' => $res[$id], 'id' => $id], $data);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getProfilerExclusions()
|
||||
public static function getProfilerExclusions() : array
|
||||
{
|
||||
$result = [];
|
||||
$modes = [1 => 'excludes', 2 => 'includes'];
|
||||
foreach ($modes as $mode => $field)
|
||||
if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, typeId AS ARRAY_KEY2, typeId FROM ?_account_excludes WHERE mode = ?d AND userId = ?d', $mode, self::$id))
|
||||
if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, `typeId` AS ARRAY_KEY2, `typeId` FROM ?_account_excludes WHERE `mode` = ?d AND `userId` = ?d', $mode, self::$id))
|
||||
foreach ($ex as $type => $ids)
|
||||
$result[$field][$type] = array_values($ids);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getCharacters()
|
||||
public static function getCharacters() : array
|
||||
{
|
||||
if (!self::$profiles)
|
||||
return [];
|
||||
@@ -648,7 +601,7 @@ class User
|
||||
return self::$profiles->getJSGlobals(PROFILEINFO_CHARACTER);
|
||||
}
|
||||
|
||||
public static function getProfiles()
|
||||
public static function getProfiles() : array
|
||||
{
|
||||
if (!self::$profiles)
|
||||
return [];
|
||||
@@ -675,7 +628,7 @@ class User
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function getGuides()
|
||||
public static function getGuides() : array
|
||||
{
|
||||
$result = [];
|
||||
|
||||
@@ -689,17 +642,17 @@ class User
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function getCookies()
|
||||
public static function getCookies() : array
|
||||
{
|
||||
$data = [];
|
||||
|
||||
if (self::$id)
|
||||
$data = DB::Aowow()->selectCol('SELECT name AS ARRAY_KEY, data FROM ?_account_cookies WHERE userId = ?d', self::$id);
|
||||
$data = DB::Aowow()->selectCol('SELECT `name` AS ARRAY_KEY, `data` FROM ?_account_cookies WHERE `userId` = ?d', self::$id);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getFavorites()
|
||||
public static function getFavorites() : array
|
||||
{
|
||||
if (!self::$id)
|
||||
return [];
|
||||
|
||||
@@ -77,22 +77,6 @@ trait TrRequestData
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static function checkLocale(string $val) : int
|
||||
{
|
||||
if (preg_match('/^'.implode('|', array_keys(array_filter(Util::$localeStrings))).'$/', $val))
|
||||
return intVal($val);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static function checkDomain(string $val) : string
|
||||
{
|
||||
if (preg_match('/^'.implode('|', array_filter(Util::$subDomains)).'$/i', $val))
|
||||
return strtolower($val);
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private static function checkIdList(string $val) : array
|
||||
{
|
||||
if (preg_match('/^-?\d+(,-?\d+)*$/', $val))
|
||||
@@ -538,14 +522,6 @@ abstract class Util
|
||||
|
||||
private static $perfectGems = null;
|
||||
|
||||
public static $localeStrings = array( // zero-indexed
|
||||
'enus', null, 'frfr', 'dede', 'zhcn', null, 'eses', null, 'ruru'
|
||||
);
|
||||
|
||||
public static $subDomains = array(
|
||||
'en', null, 'fr', 'de', 'cn', null, 'es', null, 'ru'
|
||||
);
|
||||
|
||||
public static $regions = array(
|
||||
'us', 'eu', 'kr', 'tw', 'cn', 'dev'
|
||||
);
|
||||
@@ -919,19 +895,19 @@ abstract class Util
|
||||
$silent = true;
|
||||
|
||||
// default case: selected locale available
|
||||
if (!empty($data[$field.'_loc'.User::$localeId]))
|
||||
return $data[$field.'_loc'.User::$localeId];
|
||||
if (!empty($data[$field.'_loc'.Lang::getLocale()->value]))
|
||||
return $data[$field.'_loc'.Lang::getLocale()->value];
|
||||
|
||||
// locale not enUS; aowow-type localization available; add brackets if not silent
|
||||
else if (User::$localeId != LOCALE_EN && !empty($data[$field.'_loc0']))
|
||||
else if (Lang::getLocale() != Locale::EN && !empty($data[$field.'_loc0']))
|
||||
return $silent ? $data[$field.'_loc0'] : '['.$data[$field.'_loc0'].']';
|
||||
|
||||
// locale not enUS; TC localization; add brackets if not silent
|
||||
else if (User::$localeId != LOCALE_EN && !empty($data[$field]))
|
||||
else if (Lang::getLocale() != Locale::EN && !empty($data[$field]))
|
||||
return $silent ? $data[$field] : '['.$data[$field].']';
|
||||
|
||||
// locale enUS; TC localization; return normal
|
||||
else if (User::$localeId == LOCALE_EN && !empty($data[$field]))
|
||||
else if (Lang::getLocale() == Locale::EN && !empty($data[$field]))
|
||||
return $data[$field];
|
||||
|
||||
// nothing to find; be empty
|
||||
@@ -969,22 +945,6 @@ abstract class Util
|
||||
return Lang::item('ratingString', [$statId, $result, $level]);
|
||||
}
|
||||
|
||||
public static function powerUseLocale(string $domain = 'en') : void
|
||||
{
|
||||
foreach (Util::$subDomains as $k => $v)
|
||||
{
|
||||
if ($domain != $v)
|
||||
continue;
|
||||
|
||||
User::useLocale($k);
|
||||
Lang::load($k);
|
||||
return;
|
||||
}
|
||||
|
||||
User::useLocale(LOCALE_EN);
|
||||
Lang::load(LOCALE_EN);
|
||||
}
|
||||
|
||||
// default ucFirst doesn't convert UTF-8 chars
|
||||
public static function ucFirst($str)
|
||||
{
|
||||
@@ -1097,8 +1057,8 @@ abstract class Util
|
||||
$success = true;
|
||||
if ($localized)
|
||||
{
|
||||
if (file_exists('datasets/'.User::$localeString.'/'.$file))
|
||||
$result .= file_get_contents('datasets/'.User::$localeString.'/'.$file);
|
||||
if (file_exists('datasets/'.Lang::getLocale()->json().'/'.$file))
|
||||
$result .= file_get_contents('datasets/'.Lang::getLocale()->json().'/'.$file);
|
||||
else if (file_exists('datasets/enus/'.$file))
|
||||
$result .= file_get_contents('datasets/enus/'.$file);
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user