* access class property in screenshot/comment-admin by function. Aowow is compatible with PHP 5.5 again
 * changed line-endings across the board from \r\n to \n
This commit is contained in:
Sarjuuk
2017-02-24 18:36:46 +01:00
parent 83cc16107e
commit da59440106
33 changed files with 6717 additions and 6717 deletions

BIN
README.md

Binary file not shown.

24
aowow
View File

@@ -1,12 +1,12 @@
<?php
require 'includes/shared.php';
if (!CLI)
die("this script must be run from CLI\n");
if (CLI && getcwd().DIRECTORY_SEPARATOR.'aowow' != __FILE__)
die("this script must be run from root directory\n");
else
require 'setup/setup.php';
?>
<?php
require 'includes/shared.php';
if (!CLI)
die("this script must be run from CLI\n");
if (CLI && getcwd().DIRECTORY_SEPARATOR.'aowow' != __FILE__)
die("this script must be run from root directory\n");
else
require 'setup/setup.php';
?>

View File

@@ -1,104 +1,104 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxAccount extends AjaxHandler
{
protected $validParams = ['exclude', 'weightscales'];
protected $_post = array(
// 'groups' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'save' => [FILTER_SANITIZE_NUMBER_INT, null],
'delete' => [FILTER_SANITIZE_NUMBER_INT, null],
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'name' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkName']],
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkScale']],
);
protected $_get = array(
'locale' => [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;
// select handler
if ($this->params[0] == 'exclude')
$this->handler = 'handleExclude';
else if ($this->params[0] == 'weightscales')
$this->handler = 'handleWeightscales';
}
protected function handleExclude()
{
// profiler completion exclude handler
// $this->_post['groups'] = bitMask of excludeGroupIds when using .. excludeGroups .. duh
// should probably occur in g_user.excludegroups (dont forget to also set g_users.settings = {})
return '';
}
protected function handleWeightscales()
{
if ($this->_post['save'])
{
if (!$this->_post['scale'])
return 0;
$id = 0;
if ($id = $this->_post['id'])
{
if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_account_weightscales WHERE userId = ?d AND id = ?d', User::$id, $id))
return 0;
DB::Aowow()->query('UPDATE ?_account_weightscales SET `name` = ? WHERE id = ?d', $this->_post['name'], $id);
}
else
{
$nScales = DB::Aowow()->selectCell('SELECT COUNT(id) FROM ?_account_weightscales WHERE userId = ?d', User::$id);
if ($nScales >= 5) // more or less hard-defined in LANG.message_weightscalesaveerror
return 0;
$id = DB::Aowow()->query('INSERT INTO ?_account_weightscales (`userId`, `name`) VALUES (?d, ?)', User::$id, $this->_post['name']);
}
DB::Aowow()->query('DELETE FROM ?_account_weightscale_data WHERE id = ?d', $id);
foreach (explode(',', $this->_post['scale']) as $s)
{
list($k, $v) = explode(':', $s);
if (!in_array($k, Util::$weightScales) || $v < 1)
continue;
DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $id, $k, $v);
}
return $id;
}
else if ($this->_post['delete'] && $this->_post['id'])
DB::Aowow()->query('DELETE FROM ?_account_weightscales WHERE id = ?d AND userId = ?d', $this->_post['id'], User::$id);
else
return 0;
}
protected function checkScale($val)
{
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
return $val;
return null;
}
protected function checkName($val)
{
$var = trim(urldecode($val));
return filter_var($var, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
}
}
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxAccount extends AjaxHandler
{
protected $validParams = ['exclude', 'weightscales'];
protected $_post = array(
// 'groups' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'save' => [FILTER_SANITIZE_NUMBER_INT, null],
'delete' => [FILTER_SANITIZE_NUMBER_INT, null],
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'name' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkName']],
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAccount::checkScale']],
);
protected $_get = array(
'locale' => [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;
// select handler
if ($this->params[0] == 'exclude')
$this->handler = 'handleExclude';
else if ($this->params[0] == 'weightscales')
$this->handler = 'handleWeightscales';
}
protected function handleExclude()
{
// profiler completion exclude handler
// $this->_post['groups'] = bitMask of excludeGroupIds when using .. excludeGroups .. duh
// should probably occur in g_user.excludegroups (dont forget to also set g_users.settings = {})
return '';
}
protected function handleWeightscales()
{
if ($this->_post['save'])
{
if (!$this->_post['scale'])
return 0;
$id = 0;
if ($id = $this->_post['id'])
{
if (!DB::Aowow()->selectCell('SELECT 1 FROM ?_account_weightscales WHERE userId = ?d AND id = ?d', User::$id, $id))
return 0;
DB::Aowow()->query('UPDATE ?_account_weightscales SET `name` = ? WHERE id = ?d', $this->_post['name'], $id);
}
else
{
$nScales = DB::Aowow()->selectCell('SELECT COUNT(id) FROM ?_account_weightscales WHERE userId = ?d', User::$id);
if ($nScales >= 5) // more or less hard-defined in LANG.message_weightscalesaveerror
return 0;
$id = DB::Aowow()->query('INSERT INTO ?_account_weightscales (`userId`, `name`) VALUES (?d, ?)', User::$id, $this->_post['name']);
}
DB::Aowow()->query('DELETE FROM ?_account_weightscale_data WHERE id = ?d', $id);
foreach (explode(',', $this->_post['scale']) as $s)
{
list($k, $v) = explode(':', $s);
if (!in_array($k, Util::$weightScales) || $v < 1)
continue;
DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $id, $k, $v);
}
return $id;
}
else if ($this->_post['delete'] && $this->_post['id'])
DB::Aowow()->query('DELETE FROM ?_account_weightscales WHERE id = ?d AND userId = ?d', $this->_post['id'], User::$id);
else
return 0;
}
protected function checkScale($val)
{
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
return $val;
return null;
}
protected function checkName($val)
{
$var = trim(urldecode($val));
return filter_var($var, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
}
}

View File

@@ -1,446 +1,446 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxAdmin extends AjaxHandler
{
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets'];
protected $_get = array(
'action' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
'id' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkId']],
'key' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
'all' => [FILTER_UNSAFE_RAW, null],
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'user' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkUser']],
'val' => [FILTER_UNSAFE_RAW, null]
);
protected $_post = array(
'alt' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkScale']],
'__icon' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
);
public function __construct(array $params)
{
parent::__construct($params);
// requires 'action' parameter in any case
if (!$this->_get['action'] || !$this->params)
return;
if ($this->params[0] == 'screenshots')
{
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT))
return;
if ($this->_get['action'] == 'list')
$this->handler = 'ssList';
else if ($this->_get['action'] == 'manage')
$this->handler = 'ssManage';
else if ($this->_get['action'] == 'editalt')
$this->handler = 'ssEditAlt';
else if ($this->_get['action'] == 'approve')
$this->handler = 'ssApprove';
else if ($this->_get['action'] == 'sticky')
$this->handler = 'ssSticky';
else if ($this->_get['action'] == 'delete')
$this->handler = 'ssDelete';
else if ($this->_get['action'] == 'relocate')
$this->handler = 'ssRelocate';
}
else if ($this->params[0] == 'siteconfig')
{
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
return;
if ($this->_get['action'] == 'add')
$this->handler = 'confAdd';
else if ($this->_get['action'] == 'remove')
$this->handler = 'confRemove';
else if ($this->_get['action'] == 'update')
$this->handler = 'confUpdate';
}
else if ($this->params[0] == 'weight-presets')
{
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN | U_GROUP_BUREAU))
return;
if ($this->_get['action'] == 'save')
$this->handler = 'wtSave';
}
}
// get all => null (optional)
// evaled response .. UNK
protected function ssList()
{
// ssm_screenshotPages
// ssm_numPagesFound
$pages = CommunityContent::getScreenshotPagesForManager($this->_get['all'], $nPages);
$buff = 'ssm_screenshotPages = '.Util::toJSON($pages).";\n";
$buff .= 'ssm_numPagesFound = '.$nPages.';';
return $buff;
}
// get: [type => type, typeId => typeId] || [user => username]
// evaled response .. UNK
protected function ssManage()
{
$res = [];
if ($this->_get['type'] && $this->_get['type'] && $this->_get['typeid'] && $this->_get['typeid'])
$res = CommunityContent::getScreenshotsForManager($this->_get['type'], $this->_get['typeid']);
else if ($this->_get['user'])
if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', $this->_get['user']))
$res = CommunityContent::getScreenshotsForManager(0, 0, $uId);
return 'ssm_screenshotData = '.Util::toJSON($res);
}
// get: id => SSid
// resp: ''
protected function ssEditAlt()
{
// doesn't need to be htmlEscaped, ths javascript does that
if ($this->_get['id'] && $this->_post['alt'] !== null)
DB::Aowow()->query('UPDATE ?_screenshots SET caption = ? WHERE id = ?d', trim($this->_post['alt']), $this->_get['id'][0]);
return '';
}
// get: id => comma-separated SSids
// resp: ''
protected function ssApprove()
{
if (!$this->_get['id'])
return '';
// create resized and thumb version of screenshot
$resized = [772, 618];
$thumb = [150, 150];
$path = 'static/uploads/screenshots/%s/%d.jpg';
foreach ($this->_get['id'] as $id)
{
// must not be already approved
if ($_ = DB::Aowow()->selectRow('SELECT userIdOwner, date, type, typeId FROM ?_screenshots WHERE (status & ?d) = 0 AND id = ?d', CC_FLAG_APPROVED, $id))
{
// should also error-log
if (!file_exists(sprintf($path, 'pending', $id)))
continue;
$srcImg = imagecreatefromjpeg(sprintf($path, 'pending', $id));
$srcW = imagesx($srcImg);
$srcH = imagesy($srcImg);
// write thumb
$scale = min(1.0, min($thumb[0] / $srcW, $thumb[1] / $srcH));
$destW = $srcW * $scale;
$destH = $srcH * $scale;
$destImg = imagecreatetruecolor($destW, $destH);
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
imagejpeg($destImg, sprintf($path, 'thumb', $id), 100);
// write resized (only if required)
if ($srcW > $resized[0] || $srcH > $resized[1])
{
$scale = min(1.0, min($resized[0] / $srcW, $resized[1] / $srcH));
$destW = $srcW * $scale;
$destH = $srcH * $scale;
$destImg = imagecreatetruecolor($destW, $destH);
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
imagejpeg($destImg, sprintf($path, 'resized', $id), 100);
}
imagedestroy($srcImg);
// move screenshot from pending to normal
rename(sprintf($path, 'pending', $id), sprintf($path, 'normal', $id));
// set as approved in DB and gain rep (once!)
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdApprove = ?d WHERE id = ?d', CC_FLAG_APPROVED, User::$id, $id);
Util::gainSiteReputation($_['userIdOwner'], SITEREP_ACTION_UPLOAD, ['id' => $id, 'what' => 1, 'date' => $_['date']]);
// flag DB entry as having screenshots
if (Util::$typeClasses[$_['type']] && ($tbl = (new Util::$typeClasses[$_['type']])::$dataTable))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $_['typeId']);
}
}
return '';
}
// get: id => comma-separated SSids
// resp: ''
protected function ssSticky()
{
if (!$this->_get['id'])
return '';
// approve soon to be sticky screenshots
$this->ssApprove();
// this one is a bit strange: as far as i've seen, the only thing a 'sticky' screenshot does is show up in the infobox
// this also means, that only one screenshot per page should be sticky
// so, handle it one by one and the last one affecting one particular type/typId-key gets the cake
foreach ($this->_get['id'] as $id)
{
// reset all others
DB::Aowow()->query('UPDATE ?_screenshots a, ?_screenshots b SET a.status = a.status & ~?d WHERE a.type = b.type AND a.typeId = b.typeId AND a.id <> b.id AND b.id = ?d', CC_FLAG_STICKY, $id);
// toggle sticky status
DB::Aowow()->query('UPDATE ?_screenshots SET `status` = IF(`status` & ?d, `status` & ~?d, `status` | ?d) WHERE id = ?d AND `status` & ?d', CC_FLAG_STICKY, CC_FLAG_STICKY, CC_FLAG_STICKY, $id, CC_FLAG_APPROVED);
}
return '';
}
// get: id => comma-separated SSids
// resp: ''
// 2 steps: 1) remove from sight, 2) remove from disk
protected function ssDelete()
{
if (!$this->_get['id'])
return '';
$path = 'static/uploads/screenshots/%s/%d.jpg';
foreach ($this->_get['id'] as $id)
{
// irrevocably remove already deleted files
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_screenshots WHERE status & ?d AND id = ?d', CC_FLAG_DELETED, $id))
{
DB::Aowow()->query('DELETE FROM ?_screenshots WHERE id = ?d', $id);
if (file_exists(sprintf($path, 'pending', $id)))
unlink(sprintf($path, 'pending', $id));
continue;
}
// move pending or normal to pending
if (file_exists(sprintf($path, 'normal', $id)))
rename(sprintf($path, 'normal', $id), sprintf($path, 'pending', $id));
// remove resized and thumb
if (file_exists(sprintf($path, 'thumb', $id)))
unlink(sprintf($path, 'thumb', $id));
if (file_exists(sprintf($path, 'resized', $id)))
unlink(sprintf($path, 'resized', $id));
}
// flag as deleted if not aready
$oldEntries = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, GROUP_CONCAT(typeId) FROM ?_screenshots WHERE id IN (?a) GROUP BY `type`', $this->_get['id']);
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdDelete = ?d WHERE id IN (?a)', CC_FLAG_DELETED, User::$id, $this->_get['id']);
// deflag db entry as having screenshots
foreach ($oldEntries as $type => $typeIds)
{
$typeIds = explode(',', $typeIds);
$toUnflag = DB::Aowow()->selectCol('SELECT typeId AS ARRAY_KEY, IF(BIT_OR(`status`) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `type` = ?d AND typeId IN (?a) GROUP BY typeId HAVING hasMore = 0', CC_FLAG_APPROVED, $type, $typeIds);
if ($toUnflag && Util::$typeClasses[$type] && ($tbl = (new Util::$typeClasses[$type](null))::$dataTable))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id IN (?a)', CUSTOM_HAS_SCREENSHOT, array_keys($toUnflag));
}
return '';
}
// get: id => ssId, typeid => typeId (but not type..?)
// resp: ''
protected function ssRelocate()
{
if (!$this->_get['id'] || !$this->_get['typeid'])
return '';
$id = $this->_get['id'][0];
list($type, $oldTypeId) = array_values(DB::Aowow()->selectRow('SELECT type, typeId FROM ?_screenshots WHERE id = ?d', $id));
$typeId = (int)$this->_get['typeid'];
$tc = new Util::$typeClasses[$type]([['id', $typeId]]);
if (!$tc->error)
{
// move screenshot
DB::Aowow()->query('UPDATE ?_screenshots SET typeId = ?d WHERE id = ?d', $typeId, $id);
// flag target as having screenshot
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $typeId);
// deflag source for having had screenshots (maybe)
$ssInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~status) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `status`& ?d AND `type` = ?d AND typeId = ?d', CC_FLAG_DELETED, CC_FLAG_APPROVED, $type, $oldTypeId);
if($ssInfo || !$ssInfo['hasMore'])
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $oldTypeId);
}
return '';
}
protected function confAdd()
{
$key = $this->_get['key'];
$val = $this->_get['val'];
if ($key === null)
return 'empty option name given';
if (!strlen($key))
return 'invalid chars in option name: [a-z 0-9 _ . -] are allowed';
if (ini_get($key) === false || ini_set($key, $val) === false)
return 'this configuration option cannot be set';
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_config WHERE `flags` & ?d AND `key` = ?', CON_FLAG_PHP, $key))
return 'this configuration option is already in use';
DB::Aowow()->query('INSERT IGNORE INTO ?_config (`key`, `value`, `flags`) VALUES (?, ?, ?d)', $key, $val, CON_FLAG_TYPE_STRING | CON_FLAG_PHP);
return '';
}
protected function confRemove()
{
if (!$this->_get['key'])
return 'invalid configuration option given';
if (DB::Aowow()->query('DELETE FROM ?_config WHERE `key` = ? AND (`flags` & ?d) = 0', $this->_get['key'], CON_FLAG_PERSISTENT))
return '';
else
return 'option name is either protected or was not found';
}
protected function confUpdate()
{
$key = trim($this->_get['key']);
$val = trim($this->_get['val']);
if (!strlen($key))
return 'empty option name given';
$flags = DB::Aowow()->selectCell('SELECT `flags` FROM ?_config WHERE `key` = ?', $key);
if (!$flags)
return 'configuration option not found';
if (!($flags & CON_FLAG_TYPE_STRING) && !strlen($val))
return 'empty value given';
else if ($flags & CON_FLAG_TYPE_INT && !preg_match('/^-?\d+$/i', $val))
return "value must be integer";
else if ($flags & CON_FLAG_TYPE_FLOAT && !preg_match('/^-?\d*(,|.)?\d+$/i', $val))
return "value must be float";
else if ($flags & CON_FLAG_TYPE_BOOL)
$val = (int)!!$val; // *snort* bwahahaa
DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $val, $key);
return '';
}
protected function wtSave()
{
if (!$this->_post['id'] || !$this->_post['__icon'])
return 3;
$writeFile = function($file, $content)
{
$success = false;
if ($handle = @fOpen($file, "w"))
{
if (fWrite($handle, $content))
$success = true;
fClose($handle);
}
else
die('me no file');
if ($success)
@chmod($file, Util::FILE_ACCESS);
return $success;
};
// save to db
DB::Aowow()->query('DELETE FROM ?_account_weightscale_data WHERE id = ?d', $this->_post['id']);
DB::Aowow()->query('UPDATE ?_account_weightscales SET `icon`= ? WHERE `id` = ?d', $this->_post['__icon'], $this->_post['id']);
foreach (explode(',', $this->_post['scale']) as $s)
{
list($k, $v) = explode(':', $s);
if (!in_array($k, Util::$weightScales) || $v < 1)
continue;
if (DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $this->_post['id'], $k, $v) === null)
return 1;
}
// write dataset
$wtPresets = [];
$scales = DB::Aowow()->select('SELECT id, name, icon, class FROM ?_account_weightscales WHERE userId = 0 ORDER BY class, id ASC');
foreach ($scales as $s)
{
$weights = DB::Aowow()->selectCol('SELECT field AS ARRAY_KEY, val FROM ?_account_weightscale_data WHERE id = ?d', $s['id']);
if (!$weights)
continue;
$wtPresets[$s['class']]['pve'][$s['name']] = array_merge(['__icon' => $s['icon']], $weights);
}
$toFile = "var wt_presets = ".Util::toJSON($wtPresets).";";
$file = 'datasets/weight-presets';
if (!$writeFile($file, $toFile))
return 2;
// all done
return 0;
}
protected function checkId($val)
{
// expecting id-list
if (preg_match('/\d+(,\d+)*/', $val))
return array_map('intVal', explode(',', $val));
return null;
}
protected function checkKey($val)
{
// expecting string
if (preg_match('/[^a-z0-9_\.\-]/i', $val))
return '';
return strtolower($val);
}
protected function checkUser($val)
{
$n = Util::lower(trim(urldecode($val)));
if (User::isValidName($n))
return $n;
return null;
}
protected function checkScale($val)
{
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
return $val;
return null;
}
}
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxAdmin extends AjaxHandler
{
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets'];
protected $_get = array(
'action' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
'id' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkId']],
'key' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
'all' => [FILTER_UNSAFE_RAW, null],
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'user' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkUser']],
'val' => [FILTER_UNSAFE_RAW, null]
);
protected $_post = array(
'alt' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
'scale' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkScale']],
'__icon' => [FILTER_CALLBACK, ['options' => 'AjaxAdmin::checkKey']],
);
public function __construct(array $params)
{
parent::__construct($params);
// requires 'action' parameter in any case
if (!$this->_get['action'] || !$this->params)
return;
if ($this->params[0] == 'screenshots')
{
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT))
return;
if ($this->_get['action'] == 'list')
$this->handler = 'ssList';
else if ($this->_get['action'] == 'manage')
$this->handler = 'ssManage';
else if ($this->_get['action'] == 'editalt')
$this->handler = 'ssEditAlt';
else if ($this->_get['action'] == 'approve')
$this->handler = 'ssApprove';
else if ($this->_get['action'] == 'sticky')
$this->handler = 'ssSticky';
else if ($this->_get['action'] == 'delete')
$this->handler = 'ssDelete';
else if ($this->_get['action'] == 'relocate')
$this->handler = 'ssRelocate';
}
else if ($this->params[0] == 'siteconfig')
{
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
return;
if ($this->_get['action'] == 'add')
$this->handler = 'confAdd';
else if ($this->_get['action'] == 'remove')
$this->handler = 'confRemove';
else if ($this->_get['action'] == 'update')
$this->handler = 'confUpdate';
}
else if ($this->params[0] == 'weight-presets')
{
if (!User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN | U_GROUP_BUREAU))
return;
if ($this->_get['action'] == 'save')
$this->handler = 'wtSave';
}
}
// get all => null (optional)
// evaled response .. UNK
protected function ssList()
{
// ssm_screenshotPages
// ssm_numPagesFound
$pages = CommunityContent::getScreenshotPagesForManager($this->_get['all'], $nPages);
$buff = 'ssm_screenshotPages = '.Util::toJSON($pages).";\n";
$buff .= 'ssm_numPagesFound = '.$nPages.';';
return $buff;
}
// get: [type => type, typeId => typeId] || [user => username]
// evaled response .. UNK
protected function ssManage()
{
$res = [];
if ($this->_get['type'] && $this->_get['type'] && $this->_get['typeid'] && $this->_get['typeid'])
$res = CommunityContent::getScreenshotsForManager($this->_get['type'], $this->_get['typeid']);
else if ($this->_get['user'])
if ($uId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE displayName = ?', $this->_get['user']))
$res = CommunityContent::getScreenshotsForManager(0, 0, $uId);
return 'ssm_screenshotData = '.Util::toJSON($res);
}
// get: id => SSid
// resp: ''
protected function ssEditAlt()
{
// doesn't need to be htmlEscaped, ths javascript does that
if ($this->_get['id'] && $this->_post['alt'] !== null)
DB::Aowow()->query('UPDATE ?_screenshots SET caption = ? WHERE id = ?d', trim($this->_post['alt']), $this->_get['id'][0]);
return '';
}
// get: id => comma-separated SSids
// resp: ''
protected function ssApprove()
{
if (!$this->_get['id'])
return '';
// create resized and thumb version of screenshot
$resized = [772, 618];
$thumb = [150, 150];
$path = 'static/uploads/screenshots/%s/%d.jpg';
foreach ($this->_get['id'] as $id)
{
// must not be already approved
if ($_ = DB::Aowow()->selectRow('SELECT userIdOwner, date, type, typeId FROM ?_screenshots WHERE (status & ?d) = 0 AND id = ?d', CC_FLAG_APPROVED, $id))
{
// should also error-log
if (!file_exists(sprintf($path, 'pending', $id)))
continue;
$srcImg = imagecreatefromjpeg(sprintf($path, 'pending', $id));
$srcW = imagesx($srcImg);
$srcH = imagesy($srcImg);
// write thumb
$scale = min(1.0, min($thumb[0] / $srcW, $thumb[1] / $srcH));
$destW = $srcW * $scale;
$destH = $srcH * $scale;
$destImg = imagecreatetruecolor($destW, $destH);
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
imagejpeg($destImg, sprintf($path, 'thumb', $id), 100);
// write resized (only if required)
if ($srcW > $resized[0] || $srcH > $resized[1])
{
$scale = min(1.0, min($resized[0] / $srcW, $resized[1] / $srcH));
$destW = $srcW * $scale;
$destH = $srcH * $scale;
$destImg = imagecreatetruecolor($destW, $destH);
imagefill($destImg, 0, 0, imagecolorallocate($destImg, 255, 255, 255));
imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $destW, $destH, $srcW, $srcH);
imagejpeg($destImg, sprintf($path, 'resized', $id), 100);
}
imagedestroy($srcImg);
// move screenshot from pending to normal
rename(sprintf($path, 'pending', $id), sprintf($path, 'normal', $id));
// set as approved in DB and gain rep (once!)
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdApprove = ?d WHERE id = ?d', CC_FLAG_APPROVED, User::$id, $id);
Util::gainSiteReputation($_['userIdOwner'], SITEREP_ACTION_UPLOAD, ['id' => $id, 'what' => 1, 'date' => $_['date']]);
// flag DB entry as having screenshots
if (Util::$typeClasses[$_['type']] && ($tbl = get_class_vars(Util::$typeClasses[$_['type'])['dataTable']))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $_['typeId']);
}
}
return '';
}
// get: id => comma-separated SSids
// resp: ''
protected function ssSticky()
{
if (!$this->_get['id'])
return '';
// approve soon to be sticky screenshots
$this->ssApprove();
// this one is a bit strange: as far as i've seen, the only thing a 'sticky' screenshot does is show up in the infobox
// this also means, that only one screenshot per page should be sticky
// so, handle it one by one and the last one affecting one particular type/typId-key gets the cake
foreach ($this->_get['id'] as $id)
{
// reset all others
DB::Aowow()->query('UPDATE ?_screenshots a, ?_screenshots b SET a.status = a.status & ~?d WHERE a.type = b.type AND a.typeId = b.typeId AND a.id <> b.id AND b.id = ?d', CC_FLAG_STICKY, $id);
// toggle sticky status
DB::Aowow()->query('UPDATE ?_screenshots SET `status` = IF(`status` & ?d, `status` & ~?d, `status` | ?d) WHERE id = ?d AND `status` & ?d', CC_FLAG_STICKY, CC_FLAG_STICKY, CC_FLAG_STICKY, $id, CC_FLAG_APPROVED);
}
return '';
}
// get: id => comma-separated SSids
// resp: ''
// 2 steps: 1) remove from sight, 2) remove from disk
protected function ssDelete()
{
if (!$this->_get['id'])
return '';
$path = 'static/uploads/screenshots/%s/%d.jpg';
foreach ($this->_get['id'] as $id)
{
// irrevocably remove already deleted files
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_screenshots WHERE status & ?d AND id = ?d', CC_FLAG_DELETED, $id))
{
DB::Aowow()->query('DELETE FROM ?_screenshots WHERE id = ?d', $id);
if (file_exists(sprintf($path, 'pending', $id)))
unlink(sprintf($path, 'pending', $id));
continue;
}
// move pending or normal to pending
if (file_exists(sprintf($path, 'normal', $id)))
rename(sprintf($path, 'normal', $id), sprintf($path, 'pending', $id));
// remove resized and thumb
if (file_exists(sprintf($path, 'thumb', $id)))
unlink(sprintf($path, 'thumb', $id));
if (file_exists(sprintf($path, 'resized', $id)))
unlink(sprintf($path, 'resized', $id));
}
// flag as deleted if not aready
$oldEntries = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, GROUP_CONCAT(typeId) FROM ?_screenshots WHERE id IN (?a) GROUP BY `type`', $this->_get['id']);
DB::Aowow()->query('UPDATE ?_screenshots SET status = ?d, userIdDelete = ?d WHERE id IN (?a)', CC_FLAG_DELETED, User::$id, $this->_get['id']);
// deflag db entry as having screenshots
foreach ($oldEntries as $type => $typeIds)
{
$typeIds = explode(',', $typeIds);
$toUnflag = DB::Aowow()->selectCol('SELECT typeId AS ARRAY_KEY, IF(BIT_OR(`status`) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `type` = ?d AND typeId IN (?a) GROUP BY typeId HAVING hasMore = 0', CC_FLAG_APPROVED, $type, $typeIds);
if ($toUnflag && Util::$typeClasses[$type] && ($tbl = get_class_vars(Util::$typeClasses[$type])['dataTable']))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id IN (?a)', CUSTOM_HAS_SCREENSHOT, array_keys($toUnflag));
}
return '';
}
// get: id => ssId, typeid => typeId (but not type..?)
// resp: ''
protected function ssRelocate()
{
if (!$this->_get['id'] || !$this->_get['typeid'])
return '';
$id = $this->_get['id'][0];
list($type, $oldTypeId) = array_values(DB::Aowow()->selectRow('SELECT type, typeId FROM ?_screenshots WHERE id = ?d', $id));
$typeId = (int)$this->_get['typeid'];
$tc = new Util::$typeClasses[$type]([['id', $typeId]]);
if (!$tc->error)
{
// move screenshot
DB::Aowow()->query('UPDATE ?_screenshots SET typeId = ?d WHERE id = ?d', $typeId, $id);
// flag target as having screenshot
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $typeId);
// deflag source for having had screenshots (maybe)
$ssInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~status) & ?d, 1, 0) AS hasMore FROM ?_screenshots WHERE `status`& ?d AND `type` = ?d AND typeId = ?d', CC_FLAG_DELETED, CC_FLAG_APPROVED, $type, $oldTypeId);
if($ssInfo || !$ssInfo['hasMore'])
DB::Aowow()->query('UPDATE '.$tc::$dataTable.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_SCREENSHOT, $oldTypeId);
}
return '';
}
protected function confAdd()
{
$key = $this->_get['key'];
$val = $this->_get['val'];
if ($key === null)
return 'empty option name given';
if (!strlen($key))
return 'invalid chars in option name: [a-z 0-9 _ . -] are allowed';
if (ini_get($key) === false || ini_set($key, $val) === false)
return 'this configuration option cannot be set';
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_config WHERE `flags` & ?d AND `key` = ?', CON_FLAG_PHP, $key))
return 'this configuration option is already in use';
DB::Aowow()->query('INSERT IGNORE INTO ?_config (`key`, `value`, `flags`) VALUES (?, ?, ?d)', $key, $val, CON_FLAG_TYPE_STRING | CON_FLAG_PHP);
return '';
}
protected function confRemove()
{
if (!$this->_get['key'])
return 'invalid configuration option given';
if (DB::Aowow()->query('DELETE FROM ?_config WHERE `key` = ? AND (`flags` & ?d) = 0', $this->_get['key'], CON_FLAG_PERSISTENT))
return '';
else
return 'option name is either protected or was not found';
}
protected function confUpdate()
{
$key = trim($this->_get['key']);
$val = trim($this->_get['val']);
if (!strlen($key))
return 'empty option name given';
$flags = DB::Aowow()->selectCell('SELECT `flags` FROM ?_config WHERE `key` = ?', $key);
if (!$flags)
return 'configuration option not found';
if (!($flags & CON_FLAG_TYPE_STRING) && !strlen($val))
return 'empty value given';
else if ($flags & CON_FLAG_TYPE_INT && !preg_match('/^-?\d+$/i', $val))
return "value must be integer";
else if ($flags & CON_FLAG_TYPE_FLOAT && !preg_match('/^-?\d*(,|.)?\d+$/i', $val))
return "value must be float";
else if ($flags & CON_FLAG_TYPE_BOOL)
$val = (int)!!$val; // *snort* bwahahaa
DB::Aowow()->query('UPDATE ?_config SET `value` = ? WHERE `key` = ?', $val, $key);
return '';
}
protected function wtSave()
{
if (!$this->_post['id'] || !$this->_post['__icon'])
return 3;
$writeFile = function($file, $content)
{
$success = false;
if ($handle = @fOpen($file, "w"))
{
if (fWrite($handle, $content))
$success = true;
fClose($handle);
}
else
die('me no file');
if ($success)
@chmod($file, Util::FILE_ACCESS);
return $success;
};
// save to db
DB::Aowow()->query('DELETE FROM ?_account_weightscale_data WHERE id = ?d', $this->_post['id']);
DB::Aowow()->query('UPDATE ?_account_weightscales SET `icon`= ? WHERE `id` = ?d', $this->_post['__icon'], $this->_post['id']);
foreach (explode(',', $this->_post['scale']) as $s)
{
list($k, $v) = explode(':', $s);
if (!in_array($k, Util::$weightScales) || $v < 1)
continue;
if (DB::Aowow()->query('INSERT INTO ?_account_weightscale_data VALUES (?d, ?, ?d)', $this->_post['id'], $k, $v) === null)
return 1;
}
// write dataset
$wtPresets = [];
$scales = DB::Aowow()->select('SELECT id, name, icon, class FROM ?_account_weightscales WHERE userId = 0 ORDER BY class, id ASC');
foreach ($scales as $s)
{
$weights = DB::Aowow()->selectCol('SELECT field AS ARRAY_KEY, val FROM ?_account_weightscale_data WHERE id = ?d', $s['id']);
if (!$weights)
continue;
$wtPresets[$s['class']]['pve'][$s['name']] = array_merge(['__icon' => $s['icon']], $weights);
}
$toFile = "var wt_presets = ".Util::toJSON($wtPresets).";";
$file = 'datasets/weight-presets';
if (!$writeFile($file, $toFile))
return 2;
// all done
return 0;
}
protected function checkId($val)
{
// expecting id-list
if (preg_match('/\d+(,\d+)*/', $val))
return array_map('intVal', explode(',', $val));
return null;
}
protected function checkKey($val)
{
// expecting string
if (preg_match('/[^a-z0-9_\.\-]/i', $val))
return '';
return strtolower($val);
}
protected function checkUser($val)
{
$n = Util::lower(trim(urldecode($val)));
if (User::isValidName($n))
return $n;
return null;
}
protected function checkScale($val)
{
if (preg_match('/^((\w+:\d+)(,\w+:\d+)*)$/', $val))
return $val;
return null;
}
}

View File

@@ -1,405 +1,405 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxComment extends AjaxHandler
{
const COMMENT_LENGTH_MIN = 10;
const COMMENT_LENGTH_MAX = 7500;
const REPLY_LENGTH_MIN = 15;
const REPLY_LENGTH_MAX = 600;
protected $_post = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxComment::checkId']],
'body' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
'commentbody' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
'response' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'reason' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'remove' => [FILTER_SANITIZE_NUMBER_INT, null],
'commentId' => [FILTER_SANITIZE_NUMBER_INT, null],
'replyId' => [FILTER_SANITIZE_NUMBER_INT, null],
// 'username' => [FILTER_SANITIZE_STRING, 0xC] // FILTER_FLAG_STRIP_LOW | *_HIGH
);
protected $_get = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'rating' => [FILTER_SANITIZE_NUMBER_INT, null]
);
public function __construct(array $params)
{
parent::__construct($params);
if (!$this->params || count($this->params) != 1)
return;
// note: return values must be formated as STRICT json!
// select handler
if ($this->params[0] == 'add')
$this->handler = 'handleCommentAdd';
else if ($this->params[0] == 'edit')
$this->handler = 'handleCommentEdit';
else if ($this->params[0] == 'delete')
$this->handler = 'handleCommentDelete';
else if ($this->params[0] == 'undelete')
$this->handler = 'handleCommentUndelete';
else if ($this->params[0] == 'rating') // up/down - distribution
$this->handler = 'handleCommentRating';
else if ($this->params[0] == 'vote') // up, down and remove
$this->handler = 'handleCommentVote';
else if ($this->params[0] == 'sticky') // toggle flag
$this->handler = 'handleCommentSticky';
else if ($this->params[0] == 'out-of-date') // toggle flag
$this->handler = 'handleCommentOutOfDate';
else if ($this->params[0] == 'show-replies')
$this->handler = 'handleCommentShowReplies';
else if ($this->params[0] == 'add-reply') // also returns all replies on success
$this->handler = 'handleReplyAdd';
else if ($this->params[0] == 'edit-reply') // also returns all replies on success
$this->handler = 'handleReplyEdit';
else if ($this->params[0] == 'detach-reply')
$this->handler = 'handleReplyDetach';
else if ($this->params[0] == 'delete-reply')
$this->handler = 'handleReplyDelete';
else if ($this->params[0] == 'flag-reply')
$this->handler = 'handleReplyFlag';
else if ($this->params[0] == 'upvote-reply')
$this->handler = 'handleReplyUpvote';
else if ($this->params[0] == 'downvote-reply')
$this->handler = 'handleReplyDownvote';
}
// i .. have problems believing, that everything uses nifty ajax while adding comments requires a brutal header(Loacation: <wherever>), yet, thats how it is
protected function handleCommentAdd()
{
if (!$this->_get['typeid'] || !$this->_get['type'] || !isset(Util::$typeStrings[$this->_get['type']]))
return; // whatever, we cant even send him back
// trim to max length
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['commentbody']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
$this->post['commentbody'] = mb_substr($this->_post['commentbody'], 0, (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
if (User::canComment() && !empty($this->_post['commentbody']) && mb_strlen($this->_post['commentbody']) >= self::COMMENT_LENGTH_MIN)
{
if ($postIdx = DB::Aowow()->query('INSERT INTO ?_comments (type, typeId, userId, roles, body, date) VALUES (?d, ?d, ?d, ?d, ?, UNIX_TIMESTAMP())', $this->_get['type'], $this->_get['typeid'], User::$id, User::$groups, $this->_post['commentbody']))
{
Util::gainSiteReputation(User::$id, SITEREP_ACTION_COMMENT, ['id' => $postIdx]);
// every comment starts with a rating of +1 and i guess the simplest thing to do is create a db-entry with the system as owner
DB::Aowow()->query('INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, 0, 1)', $postIdx);
// flag target with hasComment
if (Util::$typeClasses[$this->_get['type']] && ($tbl = (new Util::$typeClasses[$this->_get['type']](null))::$dataTable))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $this->_get['typeid']);
}
}
$this->doRedirect = true;
return '?'.Util::$typeStrings[$this->_get['type']].'='.$this->_get['typeid'].'#comments';
}
protected function handleCommentEdit()
{
if ((!User::canComment() && !User::isInGroup(U_GROUP_MODERATOR)) || !$this->_get['id'] || !$this->_post['body'])
return;
if (mb_strlen($this->_post['body']) < self::COMMENT_LENGTH_MIN)
return;
// trim to max length
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['body']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
$this->post['body'] = mb_substr($this->_post['body'], 0, (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
$update = array(
'body' => $this->_post['body'],
'editUserId' => User::$id,
'editDate' => time()
);
if (User::isInGroup(U_GROUP_MODERATOR))
{
$update['responseBody'] = !$this->_post['response'] ? '' : $this->_post['response'];
$update['responseUserId'] = !$this->_post['response'] ? 0 : User::$id;
$update['responseRoles'] = !$this->_post['response'] ? 0 : User::$groups;
}
DB::Aowow()->query('UPDATE ?_comments SET editCount = editCount + 1, ?a WHERE id = ?d', $update, $this->_get['id']);
}
protected function handleCommentDelete()
{
if (!$this->_post['id'] || !User::$id)
return;
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d, deleteUserId = ?d, deleteDate = UNIX_TIMESTAMP() WHERE id IN (?a){ AND userId = ?d}',
CC_FLAG_DELETED,
User::$id,
$this->_post['id'],
User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id
);
// deflag hasComment
if ($ok)
{
$coInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~b.flags) & ?d, 1, 0) as hasMore, b.type, b.typeId FROM ?_comments a JOIN ?_comments b ON a.type = b.type AND a.typeId = b.typeId WHERE a.id = ?d',
CC_FLAG_DELETED,
$this->_post['id']
);
if (!$coInfo['hasMore'] && Util::$typeClasses[$coInfo['type']] && ($tbl = (new Util::$typeClasses[$coInfo['type']](null))::$dataTable))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
}
}
protected function handleCommentUndelete()
{
if (!$this->_post['id'] || !User::$id)
return;
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id IN (?a){ AND userId = deleteUserId AND deleteUserId = ?d}',
CC_FLAG_DELETED,
$this->_post['id'],
User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id
);
// reflag hasComment
if ($ok)
{
$coInfo = DB::Aowow()->selectRow('SELECT type, typeId FROM ?_comments WHERE id = ?d', $this->_post['id']);
if (Util::$typeClasses[$coInfo['type']] && ($tbl = (new Util::$typeClasses[$coInfo['type']](null))::$dataTable))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
}
}
protected function handleCommentRating()
{
if (!$this->_get['id'])
return Util::toJSON(['success' => 0]);
if ($votes = DB::Aowow()->selectRow('SELECT 1 AS success, SUM(IF(value > 0, value, 0)) AS up, SUM(IF(value < 0, -value, 0)) AS down FROM ?_comments_rates WHERE commentId = ?d and userId <> 0 GROUP BY commentId', $this->_get['id']))
return Util::toJSON($votes);
else
return Util::toJSON(['success' => 1, 'up' => 0, 'down' => 0]);
}
protected function handleCommentVote()
{
if (!User::$id || !$this->_get['id'] || !$this->_get['rating'])
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
$target = DB::Aowow()->selectRow('SELECT c.userId AS owner, cr.value FROM ?_comments c LEFT JOIN ?_comments_rates cr ON cr.commentId = c.id AND cr.userId = ?d WHERE c.id = ?d', User::$id, $this->_get['id']);
$val = User::canSupervote() ? 2 : 1;
if ($this->_get['rating'] < 0)
$val *= -1;
if (User::getCurDailyVotes() <= 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')]);
else if (($val > 0 && !User::canUpvote()) || ($val < 0 && !User::canDownvote()))
return Util::toJSON(['error' => 1, 'message' => Lang::main('bannedRating')]);
$ok = false;
// old and new have same sign; undo vote (user may have gained/lost access to superVote in the meantime)
if ($target['value'] && ($target['value'] < 0) == ($val < 0))
$ok = DB::Aowow()->query('DELETE FROM ?_comments_rates WHERE commentId = ?d AND userId = ?d', $this->_get['id'], User::$id);
else // replace, because we may be overwriting an old, opposing vote
if ($ok = DB::Aowow()->query('REPLACE INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)', (int)$this->_get['id'], User::$id, $val))
User::decrementDailyVotes(); // do not refund retracted votes!
if (!$ok)
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
if ($val > 0) // gain rep
Util::gainSiteReputation($target['owner'], SITEREP_ACTION_UPVOTED, ['id' => $this->_get['id'], 'voterId' => User::$id]);
else if ($val < 0)
Util::gainSiteReputation($target['owner'], SITEREP_ACTION_DOWNVOTED, ['id' => $this->_get['id'], 'voterId' => User::$id]);
return Util::toJSON(['error' => 0]);
}
protected function handleCommentSticky()
{
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
return;
if ($this->_post['sticky'])
DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
else
DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
}
protected function handleCommentOutOfDate()
{
$this->contentType = 'text/plain';
if (!$this->_post['id'])
return 'The comment does not exist.';
$ok = false;
if (User::isInGroup(U_GROUP_MODERATOR)) // directly mark as outdated
{
if (!$this->_post['remove'])
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | 0x4 WHERE id = ?d', $this->_post['id'][0]);
else
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~0x4 WHERE id = ?d', $this->_post['id'][0]);
}
else if (User::$id && !$this->_post['reason'] || mb_strlen($this->_post['reason']) < self::REPLY_LENGTH_MIN)
return 'Your message is too short.';
else if (User::$id) // only report as outdated
{
$ok = DB::Aowow()->query(
'INSERT INTO ?_reports (userId, mode, reason, subject, ip, description, userAgent, appName) VALUES (?d, 1, 17, ?d, ?, "<automated comment report>", ?, ?)',
User::$id,
$this->_post['id'][0],
User::$ip,
$_SERVER['HTTP_USER_AGENT'],
get_browser(null, true)['browser']
);
}
if ($ok) // this one is very special; as in: completely retarded
return 'ok'; // the script expects the actual characters 'ok' not some string like "ok"
return Lang::main('genericError');
}
protected function handleCommentShowReplies()
{
return Util::toJSON(!$this->_get['id'] ? [] : CommunityContent::getCommentReplies($this->_get['id']));
}
protected function handleReplyAdd()
{
$this->contentType = 'text/plain';
if (!User::canComment())
return 'You are not allowed to reply.';
else if (!$this->_post['commentId'] || !DB::Aowow()->selectCell('SELECT 1 FROM ?_comments WHERE id = ?d', $this->_post['commentId']))
return Lang::main('genericError');
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
return 'Your reply has '.mb_strlen($this->_post['body']).' characters and must have at least '.self::REPLY_LENGTH_MIN.' and at most '.self::REPLY_LENGTH_MAX.'.';
else if (DB::Aowow()->query('INSERT INTO ?_comments (`userId`, `roles`, `body`, `date`, `replyTo`) VALUES (?d, ?d, ?, UNIX_TIMESTAMP(), ?d)', User::$id, User::$groups, $this->_post['body'], $this->_post['commentId']))
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
else
return Lang::main('genericError');
}
protected function handleReplyEdit()
{
$this->contentType = 'text/plain';
if (!User::canComment())
return 'You are not allowed to reply.';
else if (!$this->_post['replyId'] || !$this->_post['commentId'])
return Lang::main('genericError');
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
return 'Your reply has '.mb_strlen($this->_post['body']).' characters and must have at least '.self::REPLY_LENGTH_MIN.' and at most '.self::REPLY_LENGTH_MAX.'.';
if (DB::Aowow()->query('UPDATE ?_comments SET body = ?, editUserId = ?d, editDate = UNIX_TIMESTAMP(), editCount = editCount + 1 WHERE id = ?d AND replyTo = ?d{ AND userId = ?d}',
$this->_post['body'], User::$id, $this->_post['replyId'], $this->_post['commentId'], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id))
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
else
return Lang::main('genericError');
}
protected function handleReplyDetach()
{
if (!User::isInGroup(U_GROUP_MODERATOR) || !$this->_post['id'])
return;
DB::Aowow()->query('UPDATE ?_comments c1, ?_comments c2 SET c1.replyTo = 0, c1.type = c2.type, c1.typeId = c2.typeId WHERE c1.replyTo = c2.id AND c1.id = ?d', $this->_post['id'][0]);
}
protected function handleReplyDelete()
{
if (!User::$id || !$this->_post['id'])
return;
if (DB::Aowow()->query('DELETE FROM ?_comments WHERE id = ?d{ AND userId = ?d}', $this->_post['id'][0], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id))
DB::Aowow()->query('DELETE FROM ?_comments_rates WHERE commentId = ?d', $this->_post['id'][0]);
}
protected function handleReplyFlag()
{
if (!User::$id || !$this->_post['id'])
return;
DB::Aowow()->query(
'INSERT INTO ?_reports (userId, mode, reason, subject, ip, description, userAgent, appName) VALUES (?d, 1, 19, ?d, ?, "<automated commentreply report>", ?, ?)',
User::$id,
$this->_post['id'][0],
User::$ip,
$_SERVER['HTTP_USER_AGENT'],
get_browser(null, true)['browser']
);
}
protected function handleReplyUpvote()
{
if (!$this->_post['id'] || !User::canUpvote())
return;
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
if (!$owner)
return;
$ok = DB::Aowow()->query(
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
$this->_post['id'][0],
User::$id,
User::canSupervote() ? 2 : 1
);
if ($ok)
{
Util::gainSiteReputation($owner, SITEREP_ACTION_UPVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
User::decrementDailyVotes();
}
}
protected function handleReplyDownvote()
{
if (!$this->_post['id'] || !User::canDownvote())
return;
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
if (!$owner)
return;
$ok = DB::Aowow()->query(
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
$this->_post['id'][0],
User::$id,
User::canSupervote() ? -2 : -1
);
if ($ok)
{
Util::gainSiteReputation($owner, SITEREP_ACTION_DOWNVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
User::decrementDailyVotes();
}
}
protected function checkId($val)
{
// expecting id-list
if (preg_match('/\d+(,\d+)*/', $val))
return array_map('intVal', explode(',', $val));
return null;
}
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxComment extends AjaxHandler
{
const COMMENT_LENGTH_MIN = 10;
const COMMENT_LENGTH_MAX = 7500;
const REPLY_LENGTH_MIN = 15;
const REPLY_LENGTH_MAX = 600;
protected $_post = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxComment::checkId']],
'body' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
'commentbody' => [FILTER_UNSAFE_RAW, null],// escaped by json_encode
'response' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'reason' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'remove' => [FILTER_SANITIZE_NUMBER_INT, null],
'commentId' => [FILTER_SANITIZE_NUMBER_INT, null],
'replyId' => [FILTER_SANITIZE_NUMBER_INT, null],
// 'username' => [FILTER_SANITIZE_STRING, 0xC] // FILTER_FLAG_STRIP_LOW | *_HIGH
);
protected $_get = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'type' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'typeid' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']],
'rating' => [FILTER_SANITIZE_NUMBER_INT, null]
);
public function __construct(array $params)
{
parent::__construct($params);
if (!$this->params || count($this->params) != 1)
return;
// note: return values must be formated as STRICT json!
// select handler
if ($this->params[0] == 'add')
$this->handler = 'handleCommentAdd';
else if ($this->params[0] == 'edit')
$this->handler = 'handleCommentEdit';
else if ($this->params[0] == 'delete')
$this->handler = 'handleCommentDelete';
else if ($this->params[0] == 'undelete')
$this->handler = 'handleCommentUndelete';
else if ($this->params[0] == 'rating') // up/down - distribution
$this->handler = 'handleCommentRating';
else if ($this->params[0] == 'vote') // up, down and remove
$this->handler = 'handleCommentVote';
else if ($this->params[0] == 'sticky') // toggle flag
$this->handler = 'handleCommentSticky';
else if ($this->params[0] == 'out-of-date') // toggle flag
$this->handler = 'handleCommentOutOfDate';
else if ($this->params[0] == 'show-replies')
$this->handler = 'handleCommentShowReplies';
else if ($this->params[0] == 'add-reply') // also returns all replies on success
$this->handler = 'handleReplyAdd';
else if ($this->params[0] == 'edit-reply') // also returns all replies on success
$this->handler = 'handleReplyEdit';
else if ($this->params[0] == 'detach-reply')
$this->handler = 'handleReplyDetach';
else if ($this->params[0] == 'delete-reply')
$this->handler = 'handleReplyDelete';
else if ($this->params[0] == 'flag-reply')
$this->handler = 'handleReplyFlag';
else if ($this->params[0] == 'upvote-reply')
$this->handler = 'handleReplyUpvote';
else if ($this->params[0] == 'downvote-reply')
$this->handler = 'handleReplyDownvote';
}
// i .. have problems believing, that everything uses nifty ajax while adding comments requires a brutal header(Loacation: <wherever>), yet, thats how it is
protected function handleCommentAdd()
{
if (!$this->_get['typeid'] || !$this->_get['type'] || !isset(Util::$typeStrings[$this->_get['type']]))
return; // whatever, we cant even send him back
// trim to max length
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['commentbody']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
$this->post['commentbody'] = mb_substr($this->_post['commentbody'], 0, (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
if (User::canComment() && !empty($this->_post['commentbody']) && mb_strlen($this->_post['commentbody']) >= self::COMMENT_LENGTH_MIN)
{
if ($postIdx = DB::Aowow()->query('INSERT INTO ?_comments (type, typeId, userId, roles, body, date) VALUES (?d, ?d, ?d, ?d, ?, UNIX_TIMESTAMP())', $this->_get['type'], $this->_get['typeid'], User::$id, User::$groups, $this->_post['commentbody']))
{
Util::gainSiteReputation(User::$id, SITEREP_ACTION_COMMENT, ['id' => $postIdx]);
// every comment starts with a rating of +1 and i guess the simplest thing to do is create a db-entry with the system as owner
DB::Aowow()->query('INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, 0, 1)', $postIdx);
// flag target with hasComment
if (Util::$typeClasses[$this->_get['type']] && ($tbl = get_class_vars(Util::$typeClasses[$this->_get['type'])['dataTable']))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $this->_get['typeid']);
}
}
$this->doRedirect = true;
return '?'.Util::$typeStrings[$this->_get['type']].'='.$this->_get['typeid'].'#comments';
}
protected function handleCommentEdit()
{
if ((!User::canComment() && !User::isInGroup(U_GROUP_MODERATOR)) || !$this->_get['id'] || !$this->_post['body'])
return;
if (mb_strlen($this->_post['body']) < self::COMMENT_LENGTH_MIN)
return;
// trim to max length
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['body']) > (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
$this->post['body'] = mb_substr($this->_post['body'], 0, (self::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
$update = array(
'body' => $this->_post['body'],
'editUserId' => User::$id,
'editDate' => time()
);
if (User::isInGroup(U_GROUP_MODERATOR))
{
$update['responseBody'] = !$this->_post['response'] ? '' : $this->_post['response'];
$update['responseUserId'] = !$this->_post['response'] ? 0 : User::$id;
$update['responseRoles'] = !$this->_post['response'] ? 0 : User::$groups;
}
DB::Aowow()->query('UPDATE ?_comments SET editCount = editCount + 1, ?a WHERE id = ?d', $update, $this->_get['id']);
}
protected function handleCommentDelete()
{
if (!$this->_post['id'] || !User::$id)
return;
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d, deleteUserId = ?d, deleteDate = UNIX_TIMESTAMP() WHERE id IN (?a){ AND userId = ?d}',
CC_FLAG_DELETED,
User::$id,
$this->_post['id'],
User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id
);
// deflag hasComment
if ($ok)
{
$coInfo = DB::Aowow()->selectRow('SELECT IF(BIT_OR(~b.flags) & ?d, 1, 0) as hasMore, b.type, b.typeId FROM ?_comments a JOIN ?_comments b ON a.type = b.type AND a.typeId = b.typeId WHERE a.id = ?d',
CC_FLAG_DELETED,
$this->_post['id']
);
if (!$coInfo['hasMore'] && Util::$typeClasses[$coInfo['type']] && ($tbl = get_class_vars(Util::$typeClasses[$coInfo['type'])['dataTable']))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
}
}
protected function handleCommentUndelete()
{
if (!$this->_post['id'] || !User::$id)
return;
// in theory, there is a username passed alongside... lets just use the current user (see user.js)
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id IN (?a){ AND userId = deleteUserId AND deleteUserId = ?d}',
CC_FLAG_DELETED,
$this->_post['id'],
User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id
);
// reflag hasComment
if ($ok)
{
$coInfo = DB::Aowow()->selectRow('SELECT type, typeId FROM ?_comments WHERE id = ?d', $this->_post['id']);
if (Util::$typeClasses[$coInfo['type']] && ($tbl = (new get_class_vars(Util::$typeClasses[$coInfo['type'])['dataTable']))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
}
}
protected function handleCommentRating()
{
if (!$this->_get['id'])
return Util::toJSON(['success' => 0]);
if ($votes = DB::Aowow()->selectRow('SELECT 1 AS success, SUM(IF(value > 0, value, 0)) AS up, SUM(IF(value < 0, -value, 0)) AS down FROM ?_comments_rates WHERE commentId = ?d and userId <> 0 GROUP BY commentId', $this->_get['id']))
return Util::toJSON($votes);
else
return Util::toJSON(['success' => 1, 'up' => 0, 'down' => 0]);
}
protected function handleCommentVote()
{
if (!User::$id || !$this->_get['id'] || !$this->_get['rating'])
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
$target = DB::Aowow()->selectRow('SELECT c.userId AS owner, cr.value FROM ?_comments c LEFT JOIN ?_comments_rates cr ON cr.commentId = c.id AND cr.userId = ?d WHERE c.id = ?d', User::$id, $this->_get['id']);
$val = User::canSupervote() ? 2 : 1;
if ($this->_get['rating'] < 0)
$val *= -1;
if (User::getCurDailyVotes() <= 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')]);
else if (($val > 0 && !User::canUpvote()) || ($val < 0 && !User::canDownvote()))
return Util::toJSON(['error' => 1, 'message' => Lang::main('bannedRating')]);
$ok = false;
// old and new have same sign; undo vote (user may have gained/lost access to superVote in the meantime)
if ($target['value'] && ($target['value'] < 0) == ($val < 0))
$ok = DB::Aowow()->query('DELETE FROM ?_comments_rates WHERE commentId = ?d AND userId = ?d', $this->_get['id'], User::$id);
else // replace, because we may be overwriting an old, opposing vote
if ($ok = DB::Aowow()->query('REPLACE INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)', (int)$this->_get['id'], User::$id, $val))
User::decrementDailyVotes(); // do not refund retracted votes!
if (!$ok)
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
if ($val > 0) // gain rep
Util::gainSiteReputation($target['owner'], SITEREP_ACTION_UPVOTED, ['id' => $this->_get['id'], 'voterId' => User::$id]);
else if ($val < 0)
Util::gainSiteReputation($target['owner'], SITEREP_ACTION_DOWNVOTED, ['id' => $this->_get['id'], 'voterId' => User::$id]);
return Util::toJSON(['error' => 0]);
}
protected function handleCommentSticky()
{
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
return;
if ($this->_post['sticky'])
DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
else
DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_STICKY, $this->_post['id'][0]);
}
protected function handleCommentOutOfDate()
{
$this->contentType = 'text/plain';
if (!$this->_post['id'])
return 'The comment does not exist.';
$ok = false;
if (User::isInGroup(U_GROUP_MODERATOR)) // directly mark as outdated
{
if (!$this->_post['remove'])
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | 0x4 WHERE id = ?d', $this->_post['id'][0]);
else
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~0x4 WHERE id = ?d', $this->_post['id'][0]);
}
else if (User::$id && !$this->_post['reason'] || mb_strlen($this->_post['reason']) < self::REPLY_LENGTH_MIN)
return 'Your message is too short.';
else if (User::$id) // only report as outdated
{
$ok = DB::Aowow()->query(
'INSERT INTO ?_reports (userId, mode, reason, subject, ip, description, userAgent, appName) VALUES (?d, 1, 17, ?d, ?, "<automated comment report>", ?, ?)',
User::$id,
$this->_post['id'][0],
User::$ip,
$_SERVER['HTTP_USER_AGENT'],
get_browser(null, true)['browser']
);
}
if ($ok) // this one is very special; as in: completely retarded
return 'ok'; // the script expects the actual characters 'ok' not some string like "ok"
return Lang::main('genericError');
}
protected function handleCommentShowReplies()
{
return Util::toJSON(!$this->_get['id'] ? [] : CommunityContent::getCommentReplies($this->_get['id']));
}
protected function handleReplyAdd()
{
$this->contentType = 'text/plain';
if (!User::canComment())
return 'You are not allowed to reply.';
else if (!$this->_post['commentId'] || !DB::Aowow()->selectCell('SELECT 1 FROM ?_comments WHERE id = ?d', $this->_post['commentId']))
return Lang::main('genericError');
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
return 'Your reply has '.mb_strlen($this->_post['body']).' characters and must have at least '.self::REPLY_LENGTH_MIN.' and at most '.self::REPLY_LENGTH_MAX.'.';
else if (DB::Aowow()->query('INSERT INTO ?_comments (`userId`, `roles`, `body`, `date`, `replyTo`) VALUES (?d, ?d, ?, UNIX_TIMESTAMP(), ?d)', User::$id, User::$groups, $this->_post['body'], $this->_post['commentId']))
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
else
return Lang::main('genericError');
}
protected function handleReplyEdit()
{
$this->contentType = 'text/plain';
if (!User::canComment())
return 'You are not allowed to reply.';
else if (!$this->_post['replyId'] || !$this->_post['commentId'])
return Lang::main('genericError');
else if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
return 'Your reply has '.mb_strlen($this->_post['body']).' characters and must have at least '.self::REPLY_LENGTH_MIN.' and at most '.self::REPLY_LENGTH_MAX.'.';
if (DB::Aowow()->query('UPDATE ?_comments SET body = ?, editUserId = ?d, editDate = UNIX_TIMESTAMP(), editCount = editCount + 1 WHERE id = ?d AND replyTo = ?d{ AND userId = ?d}',
$this->_post['body'], User::$id, $this->_post['replyId'], $this->_post['commentId'], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id))
return Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
else
return Lang::main('genericError');
}
protected function handleReplyDetach()
{
if (!User::isInGroup(U_GROUP_MODERATOR) || !$this->_post['id'])
return;
DB::Aowow()->query('UPDATE ?_comments c1, ?_comments c2 SET c1.replyTo = 0, c1.type = c2.type, c1.typeId = c2.typeId WHERE c1.replyTo = c2.id AND c1.id = ?d', $this->_post['id'][0]);
}
protected function handleReplyDelete()
{
if (!User::$id || !$this->_post['id'])
return;
if (DB::Aowow()->query('DELETE FROM ?_comments WHERE id = ?d{ AND userId = ?d}', $this->_post['id'][0], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id))
DB::Aowow()->query('DELETE FROM ?_comments_rates WHERE commentId = ?d', $this->_post['id'][0]);
}
protected function handleReplyFlag()
{
if (!User::$id || !$this->_post['id'])
return;
DB::Aowow()->query(
'INSERT INTO ?_reports (userId, mode, reason, subject, ip, description, userAgent, appName) VALUES (?d, 1, 19, ?d, ?, "<automated commentreply report>", ?, ?)',
User::$id,
$this->_post['id'][0],
User::$ip,
$_SERVER['HTTP_USER_AGENT'],
get_browser(null, true)['browser']
);
}
protected function handleReplyUpvote()
{
if (!$this->_post['id'] || !User::canUpvote())
return;
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
if (!$owner)
return;
$ok = DB::Aowow()->query(
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
$this->_post['id'][0],
User::$id,
User::canSupervote() ? 2 : 1
);
if ($ok)
{
Util::gainSiteReputation($owner, SITEREP_ACTION_UPVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
User::decrementDailyVotes();
}
}
protected function handleReplyDownvote()
{
if (!$this->_post['id'] || !User::canDownvote())
return;
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
if (!$owner)
return;
$ok = DB::Aowow()->query(
'INSERT INTO ?_comments_rates (commentId, userId, value) VALUES (?d, ?d, ?d)',
$this->_post['id'][0],
User::$id,
User::canSupervote() ? -2 : -1
);
if ($ok)
{
Util::gainSiteReputation($owner, SITEREP_ACTION_DOWNVOTED, ['id' => $this->_post['id'][0], 'voterId' => User::$id]);
User::decrementDailyVotes();
}
}
protected function checkId($val)
{
// expecting id-list
if (preg_match('/\d+(,\d+)*/', $val))
return array_map('intVal', explode(',', $val));
return null;
}
}
?>

View File

@@ -1,100 +1,100 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxContactus extends AjaxHandler
{
protected $_post = array(
'mode' => [FILTER_SANITIZE_NUMBER_INT, null],
'reason' => [FILTER_SANITIZE_NUMBER_INT, null],
'ua' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'appname' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'page' => [FILTER_SANITIZE_URL, null],
'desc' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
'relatedurl' => [FILTER_SANITIZE_URL, null],
'email' => [FILTER_SANITIZE_EMAIL, null]
);
public function __construct(array $params)
{
parent::__construct($params);
// always this one
$this->handler = 'handleContactUs';
}
/* responses
0: success
1: captcha invalid
2: description too long
3: reason missing
7: already reported
$: prints response
*/
protected function handleContactUs()
{
$mode = $this->_post['mode'];
$rsn = $this->_post['reason'];
$ua = $this->_post['ua'];
$app = $this->_post['appname'];
$url = $this->_post['page'];
$desc = $this->_post['desc'];
$contexts = array(
[1, 2, 3, 4, 5, 6, 7, 8],
[15, 16, 17, 18, 19, 20],
[30, 31, 32, 33, 34, 35, 36, 37],
[45, 46, 47, 48],
[60, 61],
[45, 46, 47, 48],
[45, 46, 48]
);
if ($mode === null || $rsn === null || $ua === null || $app === null || $url === null)
return 'required field missing';
if (!isset($contexts[$mode]) || !in_array($rsn, $contexts[$mode]))
return 'mode invalid';
if (!$desc)
return 3;
if (mb_strlen($desc) > 500)
return 2;
if (!User::$id && !User::$ip)
return 'your ip could not be determined';
// check already reported
$field = User::$id ? 'userId' : 'ip';
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND ?# = ?', $mode, $rsn, $this->_post['id'], $field, User::$id ?: User::$ip))
return 7;
$update = array(
'userId' => User::$id,
'mode' => $mode,
'reason' => $rsn,
'ip' => User::$ip,
'description' => $desc,
'userAgent' => $ua,
'appName' => $app,
'url' => $url
);
if ($_ = $this->_post['id'])
$update['subject'] = $_;
if ($_ = $this->_post['relatedurl'])
$update['relatedurl'] = $_;
if ($_ = $this->_post['email'])
$update['email'] = $_;
if (DB::Aowow()->query('INSERT INTO ?_reports (?#) VALUES (?a)', array_keys($update), array_values($update)))
return 0;
return 'save to db unsuccessful';
}
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxContactus extends AjaxHandler
{
protected $_post = array(
'mode' => [FILTER_SANITIZE_NUMBER_INT, null],
'reason' => [FILTER_SANITIZE_NUMBER_INT, null],
'ua' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'appname' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'page' => [FILTER_SANITIZE_URL, null],
'desc' => [FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW],
'id' => [FILTER_SANITIZE_NUMBER_INT, null],
'relatedurl' => [FILTER_SANITIZE_URL, null],
'email' => [FILTER_SANITIZE_EMAIL, null]
);
public function __construct(array $params)
{
parent::__construct($params);
// always this one
$this->handler = 'handleContactUs';
}
/* responses
0: success
1: captcha invalid
2: description too long
3: reason missing
7: already reported
$: prints response
*/
protected function handleContactUs()
{
$mode = $this->_post['mode'];
$rsn = $this->_post['reason'];
$ua = $this->_post['ua'];
$app = $this->_post['appname'];
$url = $this->_post['page'];
$desc = $this->_post['desc'];
$contexts = array(
[1, 2, 3, 4, 5, 6, 7, 8],
[15, 16, 17, 18, 19, 20],
[30, 31, 32, 33, 34, 35, 36, 37],
[45, 46, 47, 48],
[60, 61],
[45, 46, 47, 48],
[45, 46, 48]
);
if ($mode === null || $rsn === null || $ua === null || $app === null || $url === null)
return 'required field missing';
if (!isset($contexts[$mode]) || !in_array($rsn, $contexts[$mode]))
return 'mode invalid';
if (!$desc)
return 3;
if (mb_strlen($desc) > 500)
return 2;
if (!User::$id && !User::$ip)
return 'your ip could not be determined';
// check already reported
$field = User::$id ? 'userId' : 'ip';
if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND ?# = ?', $mode, $rsn, $this->_post['id'], $field, User::$id ?: User::$ip))
return 7;
$update = array(
'userId' => User::$id,
'mode' => $mode,
'reason' => $rsn,
'ip' => User::$ip,
'description' => $desc,
'userAgent' => $ua,
'appName' => $app,
'url' => $url
);
if ($_ = $this->_post['id'])
$update['subject'] = $_;
if ($_ = $this->_post['relatedurl'])
$update['relatedurl'] = $_;
if ($_ = $this->_post['email'])
$update['email'] = $_;
if (DB::Aowow()->query('INSERT INTO ?_reports (?#) VALUES (?a)', array_keys($update), array_values($update)))
return 0;
return 'save to db unsuccessful';
}
}

View File

@@ -1,37 +1,37 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxCookie extends AjaxHandler
{
public function __construct(array $params)
{
// note that parent::__construct has to come after this
if (!$params || !User::$id)
return;
$this->_get = array(
this->params[0] => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
);
// NOW we know, what to expect and sanitize
parent::__construct($params);
// always this one
$this->handler = 'handleCookie';
}
/* responses
0: success
$: silent error
*/
protected function handleCookie()
{
if (User::$id && $this->params && $this->_get[$this->params[0]])
if (DB::Aowow()->query('REPLACE INTO ?_account_cookies VALUES (?d, ?, ?)', User::$id, $this->params[0], $this->_get[$this->params[0]]))
return 0;
return null;
}
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxCookie extends AjaxHandler
{
public function __construct(array $params)
{
// note that parent::__construct has to come after this
if (!$params || !User::$id)
return;
$this->_get = array(
this->params[0] => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
);
// NOW we know, what to expect and sanitize
parent::__construct($params);
// always this one
$this->handler = 'handleCookie';
}
/* responses
0: success
$: silent error
*/
protected function handleCookie()
{
if (User::$id && $this->params && $this->_get[$this->params[0]])
if (DB::Aowow()->query('REPLACE INTO ?_account_cookies VALUES (?d, ?, ?)', User::$id, $this->params[0], $this->_get[$this->params[0]]))
return 0;
return null;
}
}

View File

@@ -1,138 +1,138 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxData extends AjaxHandler
{
protected $_get = array(
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']],
't' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
'catg' => [FILTER_SANITIZE_NUMBER_INT, null],
'skill' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkSkill']],
'class' => [FILTER_SANITIZE_NUMBER_INT, null],
'callback' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkCallback']]
);
public function __construct(array $params)
{
parent::__construct($params);
if (is_numeric($this->_get['locale']))
User::useLocale($this->_get['locale']);
// always this one
$this->handler = 'handleData';
}
/* responses
<string>
*/
protected function handleData()
{
$result = '';
// different data can be strung together
foreach ($this->params as $set)
{
// requires valid token to hinder automated access
if ($set != 'item-scaling')
if (!$this->_get['t'] || empty($_SESSION['dataKey']) || $this->_get['t'] != $_SESSION['dataKey'])
continue;
switch ($set)
{
/* issue on no initial data:
when we loadOnDemand, the jScript tries to generate the catg-tree before it is initialized
it cant be initialized, without loading the data as empty catg are omitted
loading the data triggers the generation of the catg-tree
*/
case 'factions':
$result .= $this->loadProfilerData($set);
break;
case 'companions':
$result .= $this->loadProfilerData($set, '778');
break;
case 'mounts':
$result .= $this->loadProfilerData($set, '777');
break;
case 'quests':
// &partial: im not doing this right
// it expects a full quest dump on first lookup but will query subCats again if clicked..?
// for now omiting the detail clicks with empty results and just set catg update
$catg = $this->_get['catg'] ?: 'null';
if ($catg == 'null')
$result .= $this->loadProfilerData($set);
else if ($this->_get['callback'])
$result .= "\n\$WowheadProfiler.loadOnDemand('quests', ".$catg.");\n";
break;
case 'recipes':
if (!$this->_get['callback'] || !$this->_get['skill'])
break;
foreach ($this->_get['skill'] as $s)
Util::loadStaticFile('p-recipes-'.$s, $result, true);
Util::loadStaticFile('p-recipes-sec', $result, true);
$result .= "\n\$WowheadProfiler.loadOnDemand('recipes', null);\n";
break;
// locale independant
case 'quick-excludes': // generated per character in profiler
case 'zones':
case 'weight-presets':
case 'item-scaling':
case 'realms':
case 'statistics':
if (!Util::loadStaticFile($set, $result) && CFG_DEBUG)
$result .= "alert('could not fetch static data: ".$set."');";
$result .= "\n\n";
break;
// localized
case 'talents':
if ($_ = $this->_get['class'])
$set .= "-".$_;
case 'pet-talents':
case 'glyphs':
case 'gems':
case 'enchants':
case 'itemsets':
case 'pets':
if (!Util::loadStaticFile($set, $result, true) && CFG_DEBUG)
$result .= "alert('could not fetch static data: ".$set." for locale: ".User::$localeString."');";
$result .= "\n\n";
break;
default:
break;
}
}
return $result;
}
private function checkSkill($val)
{
return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val));
}
private function checkCallback($val)
{
return substr($val, 0, 29) == '$WowheadProfiler.loadOnDemand';
}
private function loadProfilerData($file, $catg = 'null')
{
$result = '';
if ($this->_get['callback'])
if (Util::loadStaticFile('p-'.$file, $result, true))
$result .= "\n\$WowheadProfiler.loadOnDemand('".$file."', ".$catg.");\n";
return $result;
}
}
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxData extends AjaxHandler
{
protected $_get = array(
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']],
't' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
'catg' => [FILTER_SANITIZE_NUMBER_INT, null],
'skill' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkSkill']],
'class' => [FILTER_SANITIZE_NUMBER_INT, null],
'callback' => [FILTER_CALLBACK, ['options' => 'AjaxData::checkCallback']]
);
public function __construct(array $params)
{
parent::__construct($params);
if (is_numeric($this->_get['locale']))
User::useLocale($this->_get['locale']);
// always this one
$this->handler = 'handleData';
}
/* responses
<string>
*/
protected function handleData()
{
$result = '';
// different data can be strung together
foreach ($this->params as $set)
{
// requires valid token to hinder automated access
if ($set != 'item-scaling')
if (!$this->_get['t'] || empty($_SESSION['dataKey']) || $this->_get['t'] != $_SESSION['dataKey'])
continue;
switch ($set)
{
/* issue on no initial data:
when we loadOnDemand, the jScript tries to generate the catg-tree before it is initialized
it cant be initialized, without loading the data as empty catg are omitted
loading the data triggers the generation of the catg-tree
*/
case 'factions':
$result .= $this->loadProfilerData($set);
break;
case 'companions':
$result .= $this->loadProfilerData($set, '778');
break;
case 'mounts':
$result .= $this->loadProfilerData($set, '777');
break;
case 'quests':
// &partial: im not doing this right
// it expects a full quest dump on first lookup but will query subCats again if clicked..?
// for now omiting the detail clicks with empty results and just set catg update
$catg = $this->_get['catg'] ?: 'null';
if ($catg == 'null')
$result .= $this->loadProfilerData($set);
else if ($this->_get['callback'])
$result .= "\n\$WowheadProfiler.loadOnDemand('quests', ".$catg.");\n";
break;
case 'recipes':
if (!$this->_get['callback'] || !$this->_get['skill'])
break;
foreach ($this->_get['skill'] as $s)
Util::loadStaticFile('p-recipes-'.$s, $result, true);
Util::loadStaticFile('p-recipes-sec', $result, true);
$result .= "\n\$WowheadProfiler.loadOnDemand('recipes', null);\n";
break;
// locale independant
case 'quick-excludes': // generated per character in profiler
case 'zones':
case 'weight-presets':
case 'item-scaling':
case 'realms':
case 'statistics':
if (!Util::loadStaticFile($set, $result) && CFG_DEBUG)
$result .= "alert('could not fetch static data: ".$set."');";
$result .= "\n\n";
break;
// localized
case 'talents':
if ($_ = $this->_get['class'])
$set .= "-".$_;
case 'pet-talents':
case 'glyphs':
case 'gems':
case 'enchants':
case 'itemsets':
case 'pets':
if (!Util::loadStaticFile($set, $result, true) && CFG_DEBUG)
$result .= "alert('could not fetch static data: ".$set." for locale: ".User::$localeString."');";
$result .= "\n\n";
break;
default:
break;
}
}
return $result;
}
private function checkSkill($val)
{
return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val));
}
private function checkCallback($val)
{
return substr($val, 0, 29) == '$WowheadProfiler.loadOnDemand';
}
private function loadProfilerData($file, $catg = 'null')
{
$result = '';
if ($this->_get['callback'])
if (Util::loadStaticFile('p-'.$file, $result, true))
$result .= "\n\$WowheadProfiler.loadOnDemand('".$file."', ".$catg.");\n";
return $result;
}
}
?>

View File

@@ -1,36 +1,36 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxGotocomment extends AjaxHandler
{
protected $_get = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']]
);
public function __construct(array $params)
{
parent::__construct($params);
// always this one
$this->handler = 'handleGoToComment';
$this->doRedirect = true;
}
/* responses
header()
*/
protected function handleGoToComment()
{
if (!$this->_get['id'])
exit; // just be blank
if ($_ = DB::Aowow()->selectRow('SELECT IFNULL(c2.id, c1.id) AS id, IFNULL(c2.type, c1.type) AS type, IFNULL(c2.typeId, c1.typeId) AS typeId FROM ?_comments c1 LEFT JOIN ?_comments c2 ON c1.replyTo = c2.id WHERE c1.id = ?d', $this->_get['id']))
return '?'.Util::$typeStrings[$_['type']].'='.$_['typeId'].'#comments:id='.$_['id'].($_['id'] != $this->_get['id'] ? ':reply='.$this->_get['id'] : null);
else
exit;
}
}
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxGotocomment extends AjaxHandler
{
protected $_get = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkInt']]
);
public function __construct(array $params)
{
parent::__construct($params);
// always this one
$this->handler = 'handleGoToComment';
$this->doRedirect = true;
}
/* responses
header()
*/
protected function handleGoToComment()
{
if (!$this->_get['id'])
exit; // just be blank
if ($_ = DB::Aowow()->selectRow('SELECT IFNULL(c2.id, c1.id) AS id, IFNULL(c2.type, c1.type) AS type, IFNULL(c2.typeId, c1.typeId) AS typeId FROM ?_comments c1 LEFT JOIN ?_comments c2 ON c1.replyTo = c2.id WHERE c1.id = ?d', $this->_get['id']))
return '?'.Util::$typeStrings[$_['type']].'='.$_['typeId'].'#comments:id='.$_['id'].($_['id'] != $this->_get['id'] ? ':reply='.$this->_get['id'] : null);
else
exit;
}
}
?>

View File

@@ -1,33 +1,33 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxLocale extends AjaxHandler
{
protected $_get = array(
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']]
);
public function __construct(array $params)
{
parent::__construct($params);
// always this one
$this->handler = 'handleLocale';
$this->doRedirect = true;
}
/* responses
header()
*/
protected function handleLocale()
{
User::setLocale($this->_get['locale']);
User::save();
return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '.';
}
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxLocale extends AjaxHandler
{
protected $_get = array(
'locale' => [FILTER_CALLBACK, ['options' => 'AjaxHandler::checkLocale']]
);
public function __construct(array $params)
{
parent::__construct($params);
// always this one
$this->handler = 'handleLocale';
$this->doRedirect = true;
}
/* responses
header()
*/
protected function handleLocale()
{
User::setLocale($this->_get['locale']);
User::save();
return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '.';
}
}
?>

View File

@@ -1,323 +1,323 @@
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxProfile extends AjaxHandler
{
protected $validParams = ['link', 'unlink', 'pin', 'unpin', 'public', 'private', 'avatar', 'resync', 'status', 'delete', 'purge', 'summary', 'load'];
protected $_get = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkId']],
// 'items' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkItems']],
'size' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
);
public function __construct(array $params)
{
parent::__construct($params);
if (!$this->params)
return;
switch ($this->params[0])
{
case 'link':
case 'unlink':
$this->handler = 'handleLink'; // always returns null
break;
case 'pin':
case 'unpin':
$this->handler = 'handlePin'; // always returns null
break;
case 'public':
case 'private':
$this->handler = 'handlePrivacy'; // always returns null
break;
case 'avatar':
$this->handler = 'handleAvatar'; // sets an image header
break; // so it has to die here or another header will be set
case 'resync':
case 'status':
$this->handler = 'handleResync';
break;
case 'save':
$this->handler = 'handleSave';
break;
case 'delete':
$this->handler = 'handleDelete';
break;
case 'purge':
$this->handler = 'handlePurge';
break;
case 'summary': // page is generated by jScript
die(); // just be empty
case 'load':
$this->handler = 'handleLoad';
break;
}
}
protected function handleLink($id, $mode) // links char with account
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
protected function handlePin($id, $mode) // (un)favorite
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
protected function handlePrivacy($id, $mode) // public visibility
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
protected function handleAvatar() // image
{
// something happened in the last years: those textures do not include tiny icons
$sizes = [/* 'tiny' => 15, */'small' => 18, 'medium' => 36, 'large' => 56];
$aPath = 'uploads/avatars/%d.jpg';
$s = $this->_get['size'] ?: 'medium';
if (!$this->_get['id'] || !preg_match('/^([0-9]+)\.(jpg|gif)$/', $this->_get['id'][0], $matches) || !in_array($s, array_keys($sizes)))
return;
$this->contentType = 'image/'.$matches[2];
$id = $matches[1];
$dest = imageCreateTruecolor($sizes[$s], $sizes[$s]);
if (file_exists(sprintf($aPath, $id)))
{
$offsetX = $offsetY = 0;
switch ($s)
{
case 'tiny':
$offsetX += $sizes['small'];
case 'small':
$offsetY += $sizes['medium'];
case 'medium':
$offsetX += $sizes['large'];
}
$src = imageCreateFromJpeg(printf($aPath, $id));
imagecopymerge($dest, $src, 0, 0, $offsetX, $offsetY, $sizes[$s], $sizes[$s], 100);
}
if ($matches[2] == 'gif')
imageGif($dest);
else
imageJpeg($dest);
return;
}
protected function handleResync() // resync init and status requests
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return
null [onOK]
int or str [onError]
*/
if ($this->params[0] == 'resync')
return '1';
else // $this->params[0] == 'status'
{
/*
not all fields are required, if zero they are omitted
statusCode:
0: end the request
1: waiting
2: working...
3: ready; click to view
4: error / retry
errorCode:
0: unk error
1: char does not exist
2: armory gone
[
processId,
[StatusCode, timeToRefresh, iCount, errorCode, iNResyncs],
[<anotherStatus>]...
]
*/
return '[0, [4, 10000, 1, 2]]';
}
}
protected function handleSave() // unKill a profile
{
/* params GET
id: <prId1,prId2,..,prIdN>
params POST
name, level, class, race, gender, nomodel, talenttree1, talenttree2, talenttree3, activespec, talentbuild1, glyphs1, talentbuild2, glyphs2, gearscore, icon, public [always]
description, source, copy, inv { inventory: array containing itemLinks } [optional]
}
return
int > 0 [profileId, if we came from an armoryProfile create a new one]
int < 0 [onError]
str [onError]
*/
return 'NYI';
}
protected function handleDelete() // kill a profile
{
/* params
id: <prId1,prId2,..,prIdN>
return
null
*/
return 'NYI';
}
protected function handlePurge() // removes certain saved information but not the entire character
{
/* params
id: <prId1,prId2,..,prIdN>
data: <mode> [string, tabName?]
return
null
*/
return 'NYI';
}
protected function handleLoad()
{
/* params
id: profileId
items: string [itemIds.join(':')]
unnamed: unixtime [only to force the browser to reload instead of cache]
return
lots...
*/
// titles, achievements, characterData, talents (, pets)
// and some onLoad-hook to .. load it registerProfile($data)
// everything else goes through data.php .. strangely enough
if (!$this->_get['id'])
return;
$char = new ProfileList(array(['id', $this->_get['id'][0]])); // or string or whatever
$buff = '';
if ($it = array_column($char->getField('inventory'), 0))
{
$itemz = new ItemList(array(['id', $it, CFG_SQL_LIMIT_NONE]));
$data = $itemz->getListviewData(ITEMINFO_JSON | ITEMINFO_SUBITEMS);
// get and apply inventory
foreach ($itemz->iterate() as $iId => $__)
$buff .= 'g_items.add('.$iId.', {name_'.User::$localeString.":'".Util::jsEscape($itemz->getField('name', true))."', quality:".$itemz->getField('quality').", icon:'".$itemz->getField('iconString')."', jsonequip:".Util::toJSON($data[$iId])."});\n";
$buff .= "\n";
}
if ($au = $char->getField('auras'))
{
$auraz = new SpellList(array(['id', $char->getField('auras')], CFG_SQL_LIMIT_NONE));
$dataz = $auraz->getListviewData();
$modz = $auraz->getProfilerMods();
// get and apply aura-mods
foreach ($dataz as $id => $data)
{
$mods = [];
if (!empty($modz[$id]))
{
foreach ($modz[$id] as $k => $v)
{
if (is_array($v))
$mods[] = $v;
else if ($str = @Util::$itemMods[$k])
$mods[$str] = $v;
}
}
$buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', modifier:".Util::toJSON($mods)."});\n";
}
$buff .= "\n";
}
/* depending on progress-achievements
// required by progress in JScript move to handleLoad()?
Util::$pageTemplate->extendGlobalIds(TYPE_NPC, [29120, 31134, 29306, 29311, 23980, 27656, 26861, 26723, 28923, 15991]);
*/
// load available titles
Util::loadStaticFile('p-titles-'.$char->getField('gender'), $buff, true);
// load available achievements
if (!Util::loadStaticFile('p-achievements', $buff, true))
{
$buff .= "\n\ng_achievement_catorder = [];";
$buff .= "\n\ng_achievement_points = [0];";
}
// excludes; structure UNK type => [maskBit => [typeIds]] ?
/*
g_user.excludes = [type:[typeIds]]
g_user.includes = [type:[typeIds]]
g_user.excludegroups = groupMask // requires g_user.settings != null
maskBit are matched against fieldId from excludeGroups
id: 1, label: LANG.dialog_notavail
id: 2, label: LANG.dialog_tcg
id: 4, label: LANG.dialog_collector
id: 8, label: LANG.dialog_promo
id: 16, label: LANG.dialog_nonus
id: 96, label: LANG.dialog_faction
id: 896, label: LANG.dialog_profession
id: 1024, label: LANG.dialog_noexalted
*/
// $buff .= "\n\ng_excludes = {};";
// add profile to buffer
$buff .= "\n\n\$WowheadProfiler.registerProfile(".Util::toJSON($char->getEntry(2)).");"; // can't use JSON_NUMERIC_CHECK or the talent-string becomes a float
return $buff."\n";
}
protected function checkId($val)
{
// expecting id-list
if (preg_match('/\d+(,\d+)*/', $val))
return array_map('intVal', explode(',', $val));
return null;
}
protected function checkItems($val)
{
// expecting item-list
if (preg_match('/\d+(:\d+)*/', $val))
return array_map('intVal', explode(': ', $val));
return null;
}
}
<?php
if (!defined('AOWOW_REVISION'))
die('invalid access');
class AjaxProfile extends AjaxHandler
{
protected $validParams = ['link', 'unlink', 'pin', 'unpin', 'public', 'private', 'avatar', 'resync', 'status', 'delete', 'purge', 'summary', 'load'];
protected $_get = array(
'id' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkId']],
// 'items' => [FILTER_CALLBACK, ['options' => 'AjaxProfile::checkItems']],
'size' => [FILTER_SANITIZE_STRING, 0xC], // FILTER_FLAG_STRIP_LOW | *_HIGH
);
public function __construct(array $params)
{
parent::__construct($params);
if (!$this->params)
return;
switch ($this->params[0])
{
case 'link':
case 'unlink':
$this->handler = 'handleLink'; // always returns null
break;
case 'pin':
case 'unpin':
$this->handler = 'handlePin'; // always returns null
break;
case 'public':
case 'private':
$this->handler = 'handlePrivacy'; // always returns null
break;
case 'avatar':
$this->handler = 'handleAvatar'; // sets an image header
break; // so it has to die here or another header will be set
case 'resync':
case 'status':
$this->handler = 'handleResync';
break;
case 'save':
$this->handler = 'handleSave';
break;
case 'delete':
$this->handler = 'handleDelete';
break;
case 'purge':
$this->handler = 'handlePurge';
break;
case 'summary': // page is generated by jScript
die(); // just be empty
case 'load':
$this->handler = 'handleLoad';
break;
}
}
protected function handleLink($id, $mode) // links char with account
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
protected function handlePin($id, $mode) // (un)favorite
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
protected function handlePrivacy($id, $mode) // public visibility
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return: null
*/
}
protected function handleAvatar() // image
{
// something happened in the last years: those textures do not include tiny icons
$sizes = [/* 'tiny' => 15, */'small' => 18, 'medium' => 36, 'large' => 56];
$aPath = 'uploads/avatars/%d.jpg';
$s = $this->_get['size'] ?: 'medium';
if (!$this->_get['id'] || !preg_match('/^([0-9]+)\.(jpg|gif)$/', $this->_get['id'][0], $matches) || !in_array($s, array_keys($sizes)))
return;
$this->contentType = 'image/'.$matches[2];
$id = $matches[1];
$dest = imageCreateTruecolor($sizes[$s], $sizes[$s]);
if (file_exists(sprintf($aPath, $id)))
{
$offsetX = $offsetY = 0;
switch ($s)
{
case 'tiny':
$offsetX += $sizes['small'];
case 'small':
$offsetY += $sizes['medium'];
case 'medium':
$offsetX += $sizes['large'];
}
$src = imageCreateFromJpeg(printf($aPath, $id));
imagecopymerge($dest, $src, 0, 0, $offsetX, $offsetY, $sizes[$s], $sizes[$s], 100);
}
if ($matches[2] == 'gif')
imageGif($dest);
else
imageJpeg($dest);
return;
}
protected function handleResync() // resync init and status requests
{
/* params
id: <prId1,prId2,..,prIdN>
user: <string> [optional]
return
null [onOK]
int or str [onError]
*/
if ($this->params[0] == 'resync')
return '1';
else // $this->params[0] == 'status'
{
/*
not all fields are required, if zero they are omitted
statusCode:
0: end the request
1: waiting
2: working...
3: ready; click to view
4: error / retry
errorCode:
0: unk error
1: char does not exist
2: armory gone
[
processId,
[StatusCode, timeToRefresh, iCount, errorCode, iNResyncs],
[<anotherStatus>]...
]
*/
return '[0, [4, 10000, 1, 2]]';
}
}
protected function handleSave() // unKill a profile
{
/* params GET
id: <prId1,prId2,..,prIdN>
params POST
name, level, class, race, gender, nomodel, talenttree1, talenttree2, talenttree3, activespec, talentbuild1, glyphs1, talentbuild2, glyphs2, gearscore, icon, public [always]
description, source, copy, inv { inventory: array containing itemLinks } [optional]
}
return
int > 0 [profileId, if we came from an armoryProfile create a new one]
int < 0 [onError]
str [onError]
*/
return 'NYI';
}
protected function handleDelete() // kill a profile
{
/* params
id: <prId1,prId2,..,prIdN>
return
null
*/
return 'NYI';
}
protected function handlePurge() // removes certain saved information but not the entire character
{
/* params
id: <prId1,prId2,..,prIdN>
data: <mode> [string, tabName?]
return
null
*/
return 'NYI';
}
protected function handleLoad()
{
/* params
id: profileId
items: string [itemIds.join(':')]
unnamed: unixtime [only to force the browser to reload instead of cache]
return
lots...
*/
// titles, achievements, characterData, talents (, pets)
// and some onLoad-hook to .. load it registerProfile($data)
// everything else goes through data.php .. strangely enough
if (!$this->_get['id'])
return;
$char = new ProfileList(array(['id', $this->_get['id'][0]])); // or string or whatever
$buff = '';
if ($it = array_column($char->getField('inventory'), 0))
{
$itemz = new ItemList(array(['id', $it, CFG_SQL_LIMIT_NONE]));
$data = $itemz->getListviewData(ITEMINFO_JSON | ITEMINFO_SUBITEMS);
// get and apply inventory
foreach ($itemz->iterate() as $iId => $__)
$buff .= 'g_items.add('.$iId.', {name_'.User::$localeString.":'".Util::jsEscape($itemz->getField('name', true))."', quality:".$itemz->getField('quality').", icon:'".$itemz->getField('iconString')."', jsonequip:".Util::toJSON($data[$iId])."});\n";
$buff .= "\n";
}
if ($au = $char->getField('auras'))
{
$auraz = new SpellList(array(['id', $char->getField('auras')], CFG_SQL_LIMIT_NONE));
$dataz = $auraz->getListviewData();
$modz = $auraz->getProfilerMods();
// get and apply aura-mods
foreach ($dataz as $id => $data)
{
$mods = [];
if (!empty($modz[$id]))
{
foreach ($modz[$id] as $k => $v)
{
if (is_array($v))
$mods[] = $v;
else if ($str = @Util::$itemMods[$k])
$mods[$str] = $v;
}
}
$buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', modifier:".Util::toJSON($mods)."});\n";
}
$buff .= "\n";
}
/* depending on progress-achievements
// required by progress in JScript move to handleLoad()?
Util::$pageTemplate->extendGlobalIds(TYPE_NPC, [29120, 31134, 29306, 29311, 23980, 27656, 26861, 26723, 28923, 15991]);
*/
// load available titles
Util::loadStaticFile('p-titles-'.$char->getField('gender'), $buff, true);
// load available achievements
if (!Util::loadStaticFile('p-achievements', $buff, true))
{
$buff .= "\n\ng_achievement_catorder = [];";
$buff .= "\n\ng_achievement_points = [0];";
}
// excludes; structure UNK type => [maskBit => [typeIds]] ?
/*
g_user.excludes = [type:[typeIds]]
g_user.includes = [type:[typeIds]]
g_user.excludegroups = groupMask // requires g_user.settings != null
maskBit are matched against fieldId from excludeGroups
id: 1, label: LANG.dialog_notavail
id: 2, label: LANG.dialog_tcg
id: 4, label: LANG.dialog_collector
id: 8, label: LANG.dialog_promo
id: 16, label: LANG.dialog_nonus
id: 96, label: LANG.dialog_faction
id: 896, label: LANG.dialog_profession
id: 1024, label: LANG.dialog_noexalted
*/
// $buff .= "\n\ng_excludes = {};";
// add profile to buffer
$buff .= "\n\n\$WowheadProfiler.registerProfile(".Util::toJSON($char->getEntry(2)).");"; // can't use JSON_NUMERIC_CHECK or the talent-string becomes a float
return $buff."\n";
}
protected function checkId($val)
{
// expecting id-list
if (preg_match('/\d+(,\d+)*/', $val))
return array_map('intVal', explode(',', $val));
return null;
}
protected function checkItems($val)
{
// expecting item-list
if (preg_match('/\d+(:\d+)*/', $val))
return array_map('intVal', explode(': ', $val));
return null;
}
}
?>

View File

@@ -1,26 +1,26 @@
<?php
define('AOWOW_REVISION', 22);
define('CLI', PHP_SAPI === 'cli');
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'];
$error = '';
foreach ($reqExt as $r)
if (!extension_loaded($r))
$error .= 'Required Extension <b>'.$r."</b> was not found. Please check if it should exist, using \"<i>php -m</i>\"\n\n";
if (version_compare(PHP_VERSION, '5.5.0') < 0)
$error .= 'PHP Version <b>5.5.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
if ($error)
{
echo CLI ? strip_tags($error) : $error;
die();
}
// include all necessities, set up basics
require_once 'includes/kernel.php';
?>
<?php
define('AOWOW_REVISION', 22);
define('CLI', PHP_SAPI === 'cli');
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'];
$error = '';
foreach ($reqExt as $r)
if (!extension_loaded($r))
$error .= 'Required Extension <b>'.$r."</b> was not found. Please check if it should exist, using \"<i>php -m</i>\"\n\n";
if (version_compare(PHP_VERSION, '5.5.0') < 0)
$error .= 'PHP Version <b>5.5.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
if ($error)
{
echo CLI ? strip_tags($error) : $error;
die();
}
// include all necessities, set up basics
require_once 'includes/kernel.php';
?>

View File

@@ -1,58 +1,58 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class EmoteList extends BaseType
{
public static $type = TYPE_EMOTE;
public static $brickFile = 'emote';
public static $dataTable = '?_emotes';
protected $queryBase = 'SELECT *, e.id AS ARRAY_KEY FROM ?_emotes e';
public function __construct($conditions = [])
{
parent::__construct($conditions);
// post processing
foreach ($this->iterate() as &$curTpl)
{
// remap for generic access
$curTpl['name'] = $curTpl['cmd'];
}
}
public function getListviewData()
{
$data = [];
foreach ($this->iterate() as $__)
{
$data[$this->id] = array(
'id' => $this->curTpl['id'],
'name' => $this->curTpl['cmd'],
'preview' => $this->getField('self', true) ?: ($this->getField('noTarget', true) ?: $this->getField('target', true))
);
// [nyi] sounds
}
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
{
$data = [];
foreach ($this->iterate() as $__)
$data[TYPE_EMOTE][$this->id] = ['name' => $this->getField('cmd')];
return $data;
}
public function renderTooltip() { }
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class EmoteList extends BaseType
{
public static $type = TYPE_EMOTE;
public static $brickFile = 'emote';
public static $dataTable = '?_emotes';
protected $queryBase = 'SELECT *, e.id AS ARRAY_KEY FROM ?_emotes e';
public function __construct($conditions = [])
{
parent::__construct($conditions);
// post processing
foreach ($this->iterate() as &$curTpl)
{
// remap for generic access
$curTpl['name'] = $curTpl['cmd'];
}
}
public function getListviewData()
{
$data = [];
foreach ($this->iterate() as $__)
{
$data[$this->id] = array(
'id' => $this->curTpl['id'],
'name' => $this->curTpl['cmd'],
'preview' => $this->getField('self', true) ?: ($this->getField('noTarget', true) ?: $this->getField('target', true))
);
// [nyi] sounds
}
return $data;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
{
$data = [];
foreach ($this->iterate() as $__)
$data[TYPE_EMOTE][$this->id] = ['name' => $this->getField('cmd')];
return $data;
}
public function renderTooltip() { }
}
?>

View File

@@ -1,345 +1,345 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class EnchantmentList extends BaseType
{
use listviewHelper;
public static $type = TYPE_ENCHANTMENT;
public static $brickFile = 'enchantment';
public static $dataTable = '?_itemenchantment';
private $jsonStats = [];
private $relSpells = [];
private $triggerIds = [];
protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie';
protected $queryOpts = array( // 502 => TYPE_ENCHANTMENT
'ie' => [['is']],
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 502 AND `is`.`typeId` = `ie`.`id`', true], 's' => ', `is`.*'],
);
public function __construct($conditions = [])
{
parent::__construct($conditions);
// post processing
foreach ($this->iterate() as &$curTpl)
{
$curTpl['spells'] = []; // [spellId, triggerType, charges, chanceOrPpm]
for ($i = 1; $i <=3; $i++)
{
if ($curTpl['object'.$i] <= 0)
continue;
switch ($curTpl['type'.$i])
{
case 1:
$proc = -$this->getField('ppmRate') ?: ($this->getField('procChance') ?: $this->getField('amount'.$i));
$curTpl['spells'][$i] = [$curTpl['object'.$i], 2, $curTpl['charges'], $proc];
$this->relSpells[] = $curTpl['object'.$i];
break;
case 3:
$curTpl['spells'][$i] = [$curTpl['object'.$i], 1, $curTpl['charges'], 0];
$this->relSpells[] = $curTpl['object'.$i];
break;
case 7:
$curTpl['spells'][$i] = [$curTpl['object'.$i], 0, $curTpl['charges'], 0];
$this->relSpells[] = $curTpl['object'.$i];
break;
}
}
// floats are fetched as string from db :<
$curTpl['dmg'] = floatVal($curTpl['dmg']);
$curTpl['dps'] = floatVal($curTpl['dps']);
// remove zero-stats
foreach (Util::$itemMods as $str)
if ($curTpl[$str] == 0) // empty(0.0f) => true .. yeah, sure
unset($curTpl[$str]);
if ($curTpl['dps'] == 0)
unset($curTpl['dps']);
}
if ($this->relSpells)
$this->relSpells = new SpellList(array(['id', $this->relSpells]));
}
// use if you JUST need the name
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_itemenchantment WHERE id = ?d', $id );
return Util::localizedString($n, 'name');
}
// end static use
public function getListviewData($addInfoMask = 0x0)
{
$data = [];
foreach ($this->iterate() as $__)
{
$data[$this->id] = array(
'id' => $this->id,
'name' => $this->getField('name', true),
'spells' => []
);
if ($this->curTpl['skillLine'] > 0)
$data[$this->id]['reqskill'] = $this->curTpl['skillLine'];
if ($this->curTpl['skillLevel'] > 0)
$data[$this->id]['reqskillrank'] = $this->curTpl['skillLevel'];
if ($this->curTpl['requiredLevel'] > 0)
$data[$this->id]['reqlevel'] = $this->curTpl['requiredLevel'];
foreach ($this->curTpl['spells'] as $s)
{
// enchant is procing or onUse
if ($s[1] == 2 || $s[1] == 0)
$data[$this->id]['spells'][$s[0]] = $s[2];
// spell is procing
else if ($this->relSpells && $this->relSpells->getEntry($s[0]) && ($_ = $this->relSpells->canTriggerSpell()))
{
foreach ($_ as $idx)
{
$this->triggerIds[] = $this->relSpells->getField('effect'.$idx.'TriggerSpell');
$data[$this->id]['spells'][$this->relSpells->getField('effect'.$idx.'TriggerSpell')] = $s[2];
}
}
}
if (!$data[$this->id]['spells'])
unset($data[$this->id]['spells']);
Util::arraySumByKey($data[$this->id], $this->getStatGain());
}
return $data;
}
public function getStatGain($addScalingKeys = false)
{
$data = [];
foreach (Util::$itemMods as $str)
if (isset($this->curTpl[$str]))
$data[$str] = $this->curTpl[$str];
if (isset($this->curTpl['dps']))
$data['dps'] = $this->curTpl['dps'];
// scaling enchantments are saved as 0 to item_stats, thus return empty
if ($addScalingKeys)
{
$spellStats = [];
if ($this->relSpells)
$spellStats = $this->relSpells->getStatGain();
for ($h = 1; $h <= 3; $h++)
{
$obj = (int)$this->curTpl['object'.$h];
switch ($this->curTpl['type'.$h])
{
case 3: // TYPE_EQUIP_SPELL Spells from ObjectX (use of amountX?)
if (!empty($spellStats[$obj]))
foreach ($spellStats[$obj] as $mod => $_)
if ($str = Util::$itemMods[$mod])
Util::arraySumByKey($data, [$str => 0]);
$obj = null;
break;
case 4: // TYPE_RESISTANCE +AmountX resistance for ObjectX School
switch ($obj)
{
case 0: // Physical
$obj = ITEM_MOD_ARMOR;
break;
case 1: // Holy
$obj = ITEM_MOD_HOLY_RESISTANCE;
break;
case 2: // Fire
$obj = ITEM_MOD_FIRE_RESISTANCE;
break;
case 3: // Nature
$obj = ITEM_MOD_NATURE_RESISTANCE;
break;
case 4: // Frost
$obj = ITEM_MOD_FROST_RESISTANCE;
break;
case 5: // Shadow
$obj = ITEM_MOD_SHADOW_RESISTANCE;
break;
case 6: // Arcane
$obj = ITEM_MOD_ARCANE_RESISTANCE;
break;
default:
$obj = null;
}
break;
case 5: // TYPE_STAT +AmountX for Statistic by type of ObjectX
if ($obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] ..
$obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere
break; // stats are directly assigned below
default: // TYPE_NONE dnd stuff; skip assignment below
$obj = null;
}
if ($obj !== null)
if ($str = Util::$itemMods[$obj]) // check if we use these mods
Util::arraySumByKey($data, [$str => 0]);
}
}
return $data;
}
public function getRelSpell($id)
{
if ($this->relSpells)
return $this->relSpells->getEntry($id);
return null;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
{
$data = [];
if ($addMask & GLOBALINFO_SELF)
foreach ($this->iterate() as $__)
$data[TYPE_ENCHANTMENT][$this->id] = ['name' => $this->getField('name', true)];
if ($addMask & GLOBALINFO_RELATED)
{
if ($this->relSpells)
$data = $this->relSpells->getJSGlobals(GLOBALINFO_SELF);
foreach ($this->triggerIds as $tId)
if (empty($data[TYPE_SPELL][$tId]))
$data[TYPE_SPELL][$tId] = $tId;
}
return $data;
}
public function renderTooltip() { }
}
class EnchantmentListFilter extends Filter
{
protected $enums = array(
3 => array( // requiresprof
null, 171, 164, 185, 333, 202, 129, 755, 165, 186, 197, true, false, 356, 182, 773
)
);
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
2 => [FILTER_CR_NUMERIC, 'id', null, true], // id
3 => [FILTER_CR_ENUM, 'skillLine' ], // requiresprof
4 => [FILTER_CR_NUMERIC, 'skillLevel', ], // reqskillrank
5 => [FILTER_CR_BOOLEAN, 'conditionId' ], // hascondition
10 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
12 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
21 => [FILTER_CR_NUMERIC, 'is.agi', null, true], // agi
23 => [FILTER_CR_NUMERIC, 'is.int', null, true], // int
22 => [FILTER_CR_NUMERIC, 'is.sta', null, true], // sta
24 => [FILTER_CR_NUMERIC, 'is.spi', null, true], // spi
20 => [FILTER_CR_NUMERIC, 'is.str', null, true], // str
115 => [FILTER_CR_NUMERIC, 'is.health', null, true], // health
116 => [FILTER_CR_NUMERIC, 'is.mana', null, true], // mana
60 => [FILTER_CR_NUMERIC, 'is.healthrgn', null, true], // healthrgn
61 => [FILTER_CR_NUMERIC, 'is.manargn', null, true], // manargn
41 => [FILTER_CR_NUMERIC, 'is.armor' , null, true], // armor
44 => [FILTER_CR_NUMERIC, 'is.blockrtng', null, true], // blockrtng
43 => [FILTER_CR_NUMERIC, 'is.block', null, true], // block
42 => [FILTER_CR_NUMERIC, 'is.defrtng', null, true], // defrtng
45 => [FILTER_CR_NUMERIC, 'is.dodgertng', null, true], // dodgertng
46 => [FILTER_CR_NUMERIC, 'is.parryrtng', null, true], // parryrtng
79 => [FILTER_CR_NUMERIC, 'is.resirtng', null, true], // resirtng
77 => [FILTER_CR_NUMERIC, 'is.atkpwr', null, true], // atkpwr
97 => [FILTER_CR_NUMERIC, 'is.feratkpwr', null, true], // feratkpwr
114 => [FILTER_CR_NUMERIC, 'is.armorpenrtng', null, true], // armorpenrtng
96 => [FILTER_CR_NUMERIC, 'is.critstrkrtng', null, true], // critstrkrtng
117 => [FILTER_CR_NUMERIC, 'is.exprtng', null, true], // exprtng
103 => [FILTER_CR_NUMERIC, 'is.hastertng', null, true], // hastertng
119 => [FILTER_CR_NUMERIC, 'is.hitrtng', null, true], // hitrtng
94 => [FILTER_CR_NUMERIC, 'is.splpen', null, true], // splpen
123 => [FILTER_CR_NUMERIC, 'is.splpwr', null, true], // splpwr
52 => [FILTER_CR_NUMERIC, 'is.arcsplpwr', null, true], // arcsplpwr
53 => [FILTER_CR_NUMERIC, 'is.firsplpwr', null, true], // firsplpwr
54 => [FILTER_CR_NUMERIC, 'is.frosplpwr', null, true], // frosplpwr
55 => [FILTER_CR_NUMERIC, 'is.holsplpwr', null, true], // holsplpwr
56 => [FILTER_CR_NUMERIC, 'is.natsplpwr', null, true], // natsplpwr
57 => [FILTER_CR_NUMERIC, 'is.shasplpwr', null, true], // shasplpwr
32 => [FILTER_CR_NUMERIC, 'is.dps', true, true], // dps
34 => [FILTER_CR_NUMERIC, 'is.dmg', true, true], // dmg
25 => [FILTER_CR_NUMERIC, 'is.arcres', null, true], // arcres
26 => [FILTER_CR_NUMERIC, 'is.firres', null, true], // firres
28 => [FILTER_CR_NUMERIC, 'is.frores', null, true], // frores
30 => [FILTER_CR_NUMERIC, 'is.holres', null, true], // holres
27 => [FILTER_CR_NUMERIC, 'is.natres', null, true], // natres
29 => [FILTER_CR_NUMERIC, 'is.shares', null, true], // shares
37 => [FILTER_CR_NUMERIC, 'is.mleatkpwr', null, true], // mleatkpwr
84 => [FILTER_CR_NUMERIC, 'is.mlecritstrkrtng', null, true], // mlecritstrkrtng
78 => [FILTER_CR_NUMERIC, 'is.mlehastertng', null, true], // mlehastertng
95 => [FILTER_CR_NUMERIC, 'is.mlehitrtng', null, true], // mlehitrtng
38 => [FILTER_CR_NUMERIC, 'is.rgdatkpwr', null, true], // rgdatkpwr
40 => [FILTER_CR_NUMERIC, 'is.rgdcritstrkrtng', null, true], // rgdcritstrkrtng
101 => [FILTER_CR_NUMERIC, 'is.rgdhastertng', null, true], // rgdhastertng
39 => [FILTER_CR_NUMERIC, 'is.rgdhitrtng', null, true], // rgdhitrtng
49 => [FILTER_CR_NUMERIC, 'is.splcritstrkrtng', null, true], // splcritstrkrtng
102 => [FILTER_CR_NUMERIC, 'is.splhastertng', null, true], // splhastertng
48 => [FILTER_CR_NUMERIC, 'is.splhitrtng', null, true], // splhitrtng
51 => [FILTER_CR_NUMERIC, 'is.spldmg', null, true], // spldmg
50 => [FILTER_CR_NUMERIC, 'is.splheal', null, true] // splheal
);
protected function createSQLForCriterium(&$cr)
{
if (in_array($cr[0], array_keys($this->genericFilter)))
{
if ($genCr = $this->genericCriterion($cr))
return $genCr;
unset($cr);
$this->error = true;
return [1];
}
}
protected function createSQLForValues()
{
$parts = [];
$_v = &$this->fiData['v'];
//string
if (isset($_v['na']))
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
$parts[] = $_;
// type
if (isset($_v['ty']))
{
$_ = (array)$_v['ty'];
if (!array_diff($_, [1, 2, 3, 4, 5, 6, 7, 8]))
$parts[] = ['OR', ['type1', $_], ['type2', $_], ['type3', $_]];
else
unset($_v['ty']);
}
return $parts;
}
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class EnchantmentList extends BaseType
{
use listviewHelper;
public static $type = TYPE_ENCHANTMENT;
public static $brickFile = 'enchantment';
public static $dataTable = '?_itemenchantment';
private $jsonStats = [];
private $relSpells = [];
private $triggerIds = [];
protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie';
protected $queryOpts = array( // 502 => TYPE_ENCHANTMENT
'ie' => [['is']],
'is' => ['j' => ['?_item_stats `is` ON `is`.`type` = 502 AND `is`.`typeId` = `ie`.`id`', true], 's' => ', `is`.*'],
);
public function __construct($conditions = [])
{
parent::__construct($conditions);
// post processing
foreach ($this->iterate() as &$curTpl)
{
$curTpl['spells'] = []; // [spellId, triggerType, charges, chanceOrPpm]
for ($i = 1; $i <=3; $i++)
{
if ($curTpl['object'.$i] <= 0)
continue;
switch ($curTpl['type'.$i])
{
case 1:
$proc = -$this->getField('ppmRate') ?: ($this->getField('procChance') ?: $this->getField('amount'.$i));
$curTpl['spells'][$i] = [$curTpl['object'.$i], 2, $curTpl['charges'], $proc];
$this->relSpells[] = $curTpl['object'.$i];
break;
case 3:
$curTpl['spells'][$i] = [$curTpl['object'.$i], 1, $curTpl['charges'], 0];
$this->relSpells[] = $curTpl['object'.$i];
break;
case 7:
$curTpl['spells'][$i] = [$curTpl['object'.$i], 0, $curTpl['charges'], 0];
$this->relSpells[] = $curTpl['object'.$i];
break;
}
}
// floats are fetched as string from db :<
$curTpl['dmg'] = floatVal($curTpl['dmg']);
$curTpl['dps'] = floatVal($curTpl['dps']);
// remove zero-stats
foreach (Util::$itemMods as $str)
if ($curTpl[$str] == 0) // empty(0.0f) => true .. yeah, sure
unset($curTpl[$str]);
if ($curTpl['dps'] == 0)
unset($curTpl['dps']);
}
if ($this->relSpells)
$this->relSpells = new SpellList(array(['id', $this->relSpells]));
}
// use if you JUST need the name
public static function getName($id)
{
$n = DB::Aowow()->SelectRow('SELECT name_loc0, name_loc2, name_loc3, name_loc6, name_loc8 FROM ?_itemenchantment WHERE id = ?d', $id );
return Util::localizedString($n, 'name');
}
// end static use
public function getListviewData($addInfoMask = 0x0)
{
$data = [];
foreach ($this->iterate() as $__)
{
$data[$this->id] = array(
'id' => $this->id,
'name' => $this->getField('name', true),
'spells' => []
);
if ($this->curTpl['skillLine'] > 0)
$data[$this->id]['reqskill'] = $this->curTpl['skillLine'];
if ($this->curTpl['skillLevel'] > 0)
$data[$this->id]['reqskillrank'] = $this->curTpl['skillLevel'];
if ($this->curTpl['requiredLevel'] > 0)
$data[$this->id]['reqlevel'] = $this->curTpl['requiredLevel'];
foreach ($this->curTpl['spells'] as $s)
{
// enchant is procing or onUse
if ($s[1] == 2 || $s[1] == 0)
$data[$this->id]['spells'][$s[0]] = $s[2];
// spell is procing
else if ($this->relSpells && $this->relSpells->getEntry($s[0]) && ($_ = $this->relSpells->canTriggerSpell()))
{
foreach ($_ as $idx)
{
$this->triggerIds[] = $this->relSpells->getField('effect'.$idx.'TriggerSpell');
$data[$this->id]['spells'][$this->relSpells->getField('effect'.$idx.'TriggerSpell')] = $s[2];
}
}
}
if (!$data[$this->id]['spells'])
unset($data[$this->id]['spells']);
Util::arraySumByKey($data[$this->id], $this->getStatGain());
}
return $data;
}
public function getStatGain($addScalingKeys = false)
{
$data = [];
foreach (Util::$itemMods as $str)
if (isset($this->curTpl[$str]))
$data[$str] = $this->curTpl[$str];
if (isset($this->curTpl['dps']))
$data['dps'] = $this->curTpl['dps'];
// scaling enchantments are saved as 0 to item_stats, thus return empty
if ($addScalingKeys)
{
$spellStats = [];
if ($this->relSpells)
$spellStats = $this->relSpells->getStatGain();
for ($h = 1; $h <= 3; $h++)
{
$obj = (int)$this->curTpl['object'.$h];
switch ($this->curTpl['type'.$h])
{
case 3: // TYPE_EQUIP_SPELL Spells from ObjectX (use of amountX?)
if (!empty($spellStats[$obj]))
foreach ($spellStats[$obj] as $mod => $_)
if ($str = Util::$itemMods[$mod])
Util::arraySumByKey($data, [$str => 0]);
$obj = null;
break;
case 4: // TYPE_RESISTANCE +AmountX resistance for ObjectX School
switch ($obj)
{
case 0: // Physical
$obj = ITEM_MOD_ARMOR;
break;
case 1: // Holy
$obj = ITEM_MOD_HOLY_RESISTANCE;
break;
case 2: // Fire
$obj = ITEM_MOD_FIRE_RESISTANCE;
break;
case 3: // Nature
$obj = ITEM_MOD_NATURE_RESISTANCE;
break;
case 4: // Frost
$obj = ITEM_MOD_FROST_RESISTANCE;
break;
case 5: // Shadow
$obj = ITEM_MOD_SHADOW_RESISTANCE;
break;
case 6: // Arcane
$obj = ITEM_MOD_ARCANE_RESISTANCE;
break;
default:
$obj = null;
}
break;
case 5: // TYPE_STAT +AmountX for Statistic by type of ObjectX
if ($obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] ..
$obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere
break; // stats are directly assigned below
default: // TYPE_NONE dnd stuff; skip assignment below
$obj = null;
}
if ($obj !== null)
if ($str = Util::$itemMods[$obj]) // check if we use these mods
Util::arraySumByKey($data, [$str => 0]);
}
}
return $data;
}
public function getRelSpell($id)
{
if ($this->relSpells)
return $this->relSpells->getEntry($id);
return null;
}
public function getJSGlobals($addMask = GLOBALINFO_ANY)
{
$data = [];
if ($addMask & GLOBALINFO_SELF)
foreach ($this->iterate() as $__)
$data[TYPE_ENCHANTMENT][$this->id] = ['name' => $this->getField('name', true)];
if ($addMask & GLOBALINFO_RELATED)
{
if ($this->relSpells)
$data = $this->relSpells->getJSGlobals(GLOBALINFO_SELF);
foreach ($this->triggerIds as $tId)
if (empty($data[TYPE_SPELL][$tId]))
$data[TYPE_SPELL][$tId] = $tId;
}
return $data;
}
public function renderTooltip() { }
}
class EnchantmentListFilter extends Filter
{
protected $enums = array(
3 => array( // requiresprof
null, 171, 164, 185, 333, 202, 129, 755, 165, 186, 197, true, false, 356, 182, 773
)
);
protected $genericFilter = array( // misc (bool): _NUMERIC => useFloat; _STRING => localized; _FLAG => match Value; _BOOLEAN => stringSet
2 => [FILTER_CR_NUMERIC, 'id', null, true], // id
3 => [FILTER_CR_ENUM, 'skillLine' ], // requiresprof
4 => [FILTER_CR_NUMERIC, 'skillLevel', ], // reqskillrank
5 => [FILTER_CR_BOOLEAN, 'conditionId' ], // hascondition
10 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_COMMENT ], // hascomments
11 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
12 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_VIDEO ], // hasvideos
21 => [FILTER_CR_NUMERIC, 'is.agi', null, true], // agi
23 => [FILTER_CR_NUMERIC, 'is.int', null, true], // int
22 => [FILTER_CR_NUMERIC, 'is.sta', null, true], // sta
24 => [FILTER_CR_NUMERIC, 'is.spi', null, true], // spi
20 => [FILTER_CR_NUMERIC, 'is.str', null, true], // str
115 => [FILTER_CR_NUMERIC, 'is.health', null, true], // health
116 => [FILTER_CR_NUMERIC, 'is.mana', null, true], // mana
60 => [FILTER_CR_NUMERIC, 'is.healthrgn', null, true], // healthrgn
61 => [FILTER_CR_NUMERIC, 'is.manargn', null, true], // manargn
41 => [FILTER_CR_NUMERIC, 'is.armor' , null, true], // armor
44 => [FILTER_CR_NUMERIC, 'is.blockrtng', null, true], // blockrtng
43 => [FILTER_CR_NUMERIC, 'is.block', null, true], // block
42 => [FILTER_CR_NUMERIC, 'is.defrtng', null, true], // defrtng
45 => [FILTER_CR_NUMERIC, 'is.dodgertng', null, true], // dodgertng
46 => [FILTER_CR_NUMERIC, 'is.parryrtng', null, true], // parryrtng
79 => [FILTER_CR_NUMERIC, 'is.resirtng', null, true], // resirtng
77 => [FILTER_CR_NUMERIC, 'is.atkpwr', null, true], // atkpwr
97 => [FILTER_CR_NUMERIC, 'is.feratkpwr', null, true], // feratkpwr
114 => [FILTER_CR_NUMERIC, 'is.armorpenrtng', null, true], // armorpenrtng
96 => [FILTER_CR_NUMERIC, 'is.critstrkrtng', null, true], // critstrkrtng
117 => [FILTER_CR_NUMERIC, 'is.exprtng', null, true], // exprtng
103 => [FILTER_CR_NUMERIC, 'is.hastertng', null, true], // hastertng
119 => [FILTER_CR_NUMERIC, 'is.hitrtng', null, true], // hitrtng
94 => [FILTER_CR_NUMERIC, 'is.splpen', null, true], // splpen
123 => [FILTER_CR_NUMERIC, 'is.splpwr', null, true], // splpwr
52 => [FILTER_CR_NUMERIC, 'is.arcsplpwr', null, true], // arcsplpwr
53 => [FILTER_CR_NUMERIC, 'is.firsplpwr', null, true], // firsplpwr
54 => [FILTER_CR_NUMERIC, 'is.frosplpwr', null, true], // frosplpwr
55 => [FILTER_CR_NUMERIC, 'is.holsplpwr', null, true], // holsplpwr
56 => [FILTER_CR_NUMERIC, 'is.natsplpwr', null, true], // natsplpwr
57 => [FILTER_CR_NUMERIC, 'is.shasplpwr', null, true], // shasplpwr
32 => [FILTER_CR_NUMERIC, 'is.dps', true, true], // dps
34 => [FILTER_CR_NUMERIC, 'is.dmg', true, true], // dmg
25 => [FILTER_CR_NUMERIC, 'is.arcres', null, true], // arcres
26 => [FILTER_CR_NUMERIC, 'is.firres', null, true], // firres
28 => [FILTER_CR_NUMERIC, 'is.frores', null, true], // frores
30 => [FILTER_CR_NUMERIC, 'is.holres', null, true], // holres
27 => [FILTER_CR_NUMERIC, 'is.natres', null, true], // natres
29 => [FILTER_CR_NUMERIC, 'is.shares', null, true], // shares
37 => [FILTER_CR_NUMERIC, 'is.mleatkpwr', null, true], // mleatkpwr
84 => [FILTER_CR_NUMERIC, 'is.mlecritstrkrtng', null, true], // mlecritstrkrtng
78 => [FILTER_CR_NUMERIC, 'is.mlehastertng', null, true], // mlehastertng
95 => [FILTER_CR_NUMERIC, 'is.mlehitrtng', null, true], // mlehitrtng
38 => [FILTER_CR_NUMERIC, 'is.rgdatkpwr', null, true], // rgdatkpwr
40 => [FILTER_CR_NUMERIC, 'is.rgdcritstrkrtng', null, true], // rgdcritstrkrtng
101 => [FILTER_CR_NUMERIC, 'is.rgdhastertng', null, true], // rgdhastertng
39 => [FILTER_CR_NUMERIC, 'is.rgdhitrtng', null, true], // rgdhitrtng
49 => [FILTER_CR_NUMERIC, 'is.splcritstrkrtng', null, true], // splcritstrkrtng
102 => [FILTER_CR_NUMERIC, 'is.splhastertng', null, true], // splhastertng
48 => [FILTER_CR_NUMERIC, 'is.splhitrtng', null, true], // splhitrtng
51 => [FILTER_CR_NUMERIC, 'is.spldmg', null, true], // spldmg
50 => [FILTER_CR_NUMERIC, 'is.splheal', null, true] // splheal
);
protected function createSQLForCriterium(&$cr)
{
if (in_array($cr[0], array_keys($this->genericFilter)))
{
if ($genCr = $this->genericCriterion($cr))
return $genCr;
unset($cr);
$this->error = true;
return [1];
}
}
protected function createSQLForValues()
{
$parts = [];
$_v = &$this->fiData['v'];
//string
if (isset($_v['na']))
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
$parts[] = $_;
// type
if (isset($_v['ty']))
{
$_ = (array)$_v['ty'];
if (!array_diff($_, [1, 2, 3, 4, 5, 6, 7, 8]))
$parts[] = ['OR', ['type1', $_], ['type2', $_], ['type3', $_]];
else
unset($_v['ty']);
}
return $parts;
}
}
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,106 +1,106 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 100: Emotes g_initPath()
// tabid 0: Database g_initHeader()
class EmotePage extends GenericPage
{
use DetailPage;
protected $type = TYPE_EMOTE;
protected $typeId = 0;
protected $tpl = 'detail-page-generic';
protected $path = [0, 100];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
public function __construct($pageCall, $id)
{
parent::__construct($pageCall, $id);
$this->typeId = intVal($id);
$this->subject = new EmoteList(array(['id', $this->typeId]));
if ($this->subject->error)
$this->notFound(Util::ucFirst(Lang::game('emote')), Lang::emote('notFound'));
$this->name = Util::ucFirst($this->subject->getField('cmd'));
}
protected function generatePath() { }
protected function generateTitle()
{
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('emote')));
}
protected function generateContent()
{
/***********/
/* Infobox */
/***********/
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
// has Animation
if ($this->subject->getField('isAnimated'))
$infobox[] = Lang::emote('isAnimated');
/****************/
/* Main Content */
/****************/
$text = '';
if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << User::$localeId))
{
$text .= '[h3]'.Lang::emote('aliases').'[/h3][ul]';
foreach ($aliasses as $a)
$text .= '[li]/'.$a.'[/li]';
$text .= '[/ul][br][br]';
}
$texts = [];
if ($_ = $this->subject->getField('self', true))
$texts[Lang::emote('self')] = $_;
if ($_ = $this->subject->getField('target', true))
$texts[Lang::emote('target')] = $_;
if ($_ = $this->subject->getField('noTarget', true))
$texts[Lang::emote('noTarget')] = $_;
if (!$texts)
$text .= '[div][i class=q0]'.Lang::emote('noText').'[/i][/div]';
else
foreach ($texts as $h => $t)
$text .= '[pad][b]'.$h.'[/b][ul][li][span class=s4]'.preg_replace('/%\d?\$?s/', '<'.Util::ucFirst(Lang::main('name')).'>', $t).'[/span][/li][/ul]';
$this->extraText = $text;
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
$this->redButtons = array(
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
BUTTON_WOWHEAD => false
);
/**************/
/* Extra Tabs */
/**************/
// tab: achievement
$condition = array(
['ac.type', ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE],
['ac.value1', $this->typeId],
);
$acv = new AchievementList($condition);
$this->lvTabs[] = ['achievement', ['data' => array_values($acv->getListviewData())]];
$this->extendGlobalData($acv->getJsGlobals());
}
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 100: Emotes g_initPath()
// tabid 0: Database g_initHeader()
class EmotePage extends GenericPage
{
use DetailPage;
protected $type = TYPE_EMOTE;
protected $typeId = 0;
protected $tpl = 'detail-page-generic';
protected $path = [0, 100];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
public function __construct($pageCall, $id)
{
parent::__construct($pageCall, $id);
$this->typeId = intVal($id);
$this->subject = new EmoteList(array(['id', $this->typeId]));
if ($this->subject->error)
$this->notFound(Util::ucFirst(Lang::game('emote')), Lang::emote('notFound'));
$this->name = Util::ucFirst($this->subject->getField('cmd'));
}
protected function generatePath() { }
protected function generateTitle()
{
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('emote')));
}
protected function generateContent()
{
/***********/
/* Infobox */
/***********/
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
// has Animation
if ($this->subject->getField('isAnimated'))
$infobox[] = Lang::emote('isAnimated');
/****************/
/* Main Content */
/****************/
$text = '';
if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << User::$localeId))
{
$text .= '[h3]'.Lang::emote('aliases').'[/h3][ul]';
foreach ($aliasses as $a)
$text .= '[li]/'.$a.'[/li]';
$text .= '[/ul][br][br]';
}
$texts = [];
if ($_ = $this->subject->getField('self', true))
$texts[Lang::emote('self')] = $_;
if ($_ = $this->subject->getField('target', true))
$texts[Lang::emote('target')] = $_;
if ($_ = $this->subject->getField('noTarget', true))
$texts[Lang::emote('noTarget')] = $_;
if (!$texts)
$text .= '[div][i class=q0]'.Lang::emote('noText').'[/i][/div]';
else
foreach ($texts as $h => $t)
$text .= '[pad][b]'.$h.'[/b][ul][li][span class=s4]'.preg_replace('/%\d?\$?s/', '<'.Util::ucFirst(Lang::main('name')).'>', $t).'[/span][/li][/ul]';
$this->extraText = $text;
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
$this->redButtons = array(
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
BUTTON_WOWHEAD => false
);
/**************/
/* Extra Tabs */
/**************/
// tab: achievement
$condition = array(
['ac.type', ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE],
['ac.value1', $this->typeId],
);
$acv = new AchievementList($condition);
$this->lvTabs[] = ['achievement', ['data' => array_values($acv->getListviewData())]];
$this->extendGlobalData($acv->getJsGlobals());
}
}
?>

View File

@@ -1,44 +1,44 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 100: Emotes g_initPath()
// tabid 0: Database g_initHeader()
class EmotesPage extends GenericPage
{
use ListPage;
protected $type = TYPE_EMOTE;
protected $tpl = 'list-page-generic';
protected $path = [0, 100];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
public function __construct($pageCall, $pageParam)
{
parent::__construct($pageCall, $pageParam);
$this->name = Util::ucFirst(Lang::game('emotes'));
}
protected function generateContent()
{
$tabData = array(
'data' => array_values((new EmoteList())->getListviewData()),
'name' => Util::ucFirst(Lang::game('emotes'))
);
$this->lvTabs[] = ['emote', $tabData, 'emote'];
}
protected function generateTitle()
{
array_unshift($this->title, $this->name);
}
protected function generatePath() { }
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 100: Emotes g_initPath()
// tabid 0: Database g_initHeader()
class EmotesPage extends GenericPage
{
use ListPage;
protected $type = TYPE_EMOTE;
protected $tpl = 'list-page-generic';
protected $path = [0, 100];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
public function __construct($pageCall, $pageParam)
{
parent::__construct($pageCall, $pageParam);
$this->name = Util::ucFirst(Lang::game('emotes'));
}
protected function generateContent()
{
$tabData = array(
'data' => array_values((new EmoteList())->getListviewData()),
'name' => Util::ucFirst(Lang::game('emotes'))
);
$this->lvTabs[] = ['emote', $tabData, 'emote'];
}
protected function generateTitle()
{
array_unshift($this->title, $this->name);
}
protected function generatePath() { }
}
?>

View File

@@ -1,324 +1,324 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 101: Enchantment g_initPath()
// tabId 0: Database g_initHeader()
class EnchantmentPage extends GenericPage
{
use DetailPage;
protected $type = TYPE_ENCHANTMENT;
protected $typeId = 0;
protected $tpl = 'enchantment';
protected $path = [0, 101];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
public function __construct($pageCall, $id)
{
parent::__construct($pageCall, $id);
$this->typeId = intVal($id);
$this->subject = new EnchantmentList(array(['id', $this->typeId]));
if ($this->subject->error)
$this->notFound(Util::ucFirst(Lang::game('enchantment')), Lang::enchantment('notFound'));
$this->extendGlobalData($this->subject->getJSGlobals());
$this->name = Util::ucFirst($this->subject->getField('name', true));
}
private function getDistinctType()
{
$type = 0;
for ($i = 1; $i < 4; $i++)
{
if ($_ = $this->subject->getField('type'.$i))
{
if ($type) // already set
return 0;
else
$type = $_;
}
}
return $type;
}
protected function generateContent()
{
/***********/
/* Infobox */
/***********/
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
// reqLevel
if ($_ = $this->subject->getField('requiredLevel'))
$infobox[] = sprintf(Lang::game('reqLevel'), $_);
// reqskill
if ($_ = $this->subject->getField('skillLine'))
{
$this->extendGlobalIds(TYPE_SKILL, $_);
$foo = sprintf(Lang::game('requires'), '&nbsp;[skill='.$_.']');
if ($_ = $this->subject->getField('skillLevel'))
$foo .= ' ('.$_.')';
$infobox[] = $foo;
}
/****************/
/* Main Content */
/****************/
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
$this->redButtons = array(
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
BUTTON_WOWHEAD => false
);
$this->effects = [];
// 3 effects
for ($i = 1; $i < 4; $i++)
{
$_ty = $this->subject->getField('type'.$i);
$_qty = $this->subject->getField('amount'.$i);
$_obj = $this->subject->getField('object'.$i);
switch ($_ty)
{
case 1:
case 3:
case 7:
$sArr = $this->subject->getField('spells')[$i];
$spl = $this->subject->getRelSpell($sArr[0]);
$this->effects[$i]['name'] = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Type: '.$_ty, Lang::item('trigger', $sArr[1])) : Lang::item('trigger', $sArr[1]);
$this->effects[$i]['proc'] = $sArr[3];
$this->effects[$i]['value'] = $_qty ?: null;
$this->effects[$i]['icon'] = array(
'name' => !$spl ? Util::ucFirst(Lang::game('spell')).' #'.$sArr[0] : Util::localizedString($spl, 'name'),
'id' => $sArr[0],
'count' => $sArr[2]
);
break;
case 5:
if ($_obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] ..
$_obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere
$this->effects[$i]['tip'] = [$_obj, Util::$itemMods[$_obj]];
// DO NOT BREAK!
case 2:
case 6:
case 8:
case 4:
$this->effects[$i]['name'] = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Type: '.$_ty, Lang::enchantment('types', $_ty)) : Lang::enchantment('types', $_ty);
$this->effects[$i]['value'] = $_qty;
if ($_ty == 4)
$this->effects[$i]['name'] .= Lang::main('colon').'('.(User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Object: '.$_obj, Lang::getMagicSchools(1 << $_obj)) : Lang::getMagicSchools(1 << $_obj)).')';
}
}
// activation conditions
if ($_ = $this->subject->getField('conditionId'))
{
$x = '';
if ($gemCnd = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantmentcondition WHERE id = ?d', $_))
{
for ($i = 1; $i < 6; $i++)
{
if (!$gemCnd['color'.$i])
continue;
$fiColors = function ($idx)
{
$foo = '';
switch ($idx)
{
case 2: $foo = '0:3:5'; break; // red
case 3: $foo = '2:4:5'; break; // yellow
case 4: $foo = '1:3:4'; break; // blue
}
return $foo;
};
$bLink = $gemCnd['color'.$i] ? '<a href="?items=3&filter=ty='.$fiColors($gemCnd['color'.$i]).'">'.Lang::item('gemColors', $gemCnd['color'.$i] - 1).'</a>' : '';
$cLink = $gemCnd['cmpColor'.$i] ? '<a href="?items=3&filter=ty='.$fiColors($gemCnd['cmpColor'.$i]).'">'.Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1).'</a>' : '';
switch ($gemCnd['comparator'.$i])
{
case 2: // requires less <color> than (<value> || <comparecolor>) gems
case 5: // requires at least <color> than (<value> || <comparecolor>) gems
$sp = (int)$gemCnd['value'.$i] > 1;
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.sprintf(Lang::item('gemConditions', $gemCnd['comparator'.$i], $sp), $gemCnd['value'.$i], $bLink).'</span><br />';
break;
case 3: // requires more <color> than (<value> || <comparecolor>) gems
$link = '<a href="?items=3&filter=ty='.$fiColors($gemCnd['cmpColor'.$i]).'">'.Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1).'</a>';
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.sprintf(Lang::item('gemConditions', 3), $bLink, $cLink).'</span><br />';
break;
}
}
}
$this->activateCondition = $x;
}
/**************/
/* Extra Tabs */
/**************/
// used by gem
$gemList = new ItemList(array(['gemEnchantmentId', $this->typeId]));
if (!$gemList->error)
{
$this->lvTabs[] = ['item', array(
'data' => array_values($gemList->getListviewData()),
'name' => '$LANG.tab_usedby + \' \' + LANG.gems',
'id' => 'used-by-gem',
)];
$this->extendGlobalData($gemList->getJsGlobals());
}
// used by socket bonus
$socketsList = new ItemList(array(['socketBonus', $this->typeId]));
if (!$socketsList->error)
{
$this->lvTabs[] = ['item', array(
'data' => array_values($socketsList->getListviewData()),
'name' => '$LANG.tab_usedby + \' \' + \''.Lang::item('socketBonus').'\'',
'id' => 'used-by-socketbonus',
)];
$this->extendGlobalData($socketsList->getJsGlobals());
}
// used by spell
// used by useItem
$cnd = array(
'OR',
['AND', ['effect1Id', [53, 54, 156, 92]], ['effect1MiscValue', $this->typeId]],
['AND', ['effect2Id', [53, 54, 156, 92]], ['effect2MiscValue', $this->typeId]],
['AND', ['effect3Id', [53, 54, 156, 92]], ['effect3MiscValue', $this->typeId]],
);
$spellList = new SpellList($cnd);
if (!$spellList->error)
{
$spellData = $spellList->getListviewData();
$this->extendGlobalData($spellList->getJsGlobals());
$spellIds = $spellList->getFoundIDs();
$conditions = array(
'OR', // [use, useUndelayed]
['AND', ['spellTrigger1', [0, 5]], ['spellId1', $spellIds]],
['AND', ['spellTrigger2', [0, 5]], ['spellId2', $spellIds]],
['AND', ['spellTrigger3', [0, 5]], ['spellId3', $spellIds]],
['AND', ['spellTrigger4', [0, 5]], ['spellId4', $spellIds]],
['AND', ['spellTrigger5', [0, 5]], ['spellId5', $spellIds]]
);
$ubItems = new ItemList($conditions);
if (!$ubItems->error)
{
$this->lvTabs[] = ['item', array(
'data' => array_values($ubItems->getListviewData()),
'name' => '$LANG.tab_usedby + \' \' + LANG.types[3][0]',
'id' => 'used-by-item',
)];
$this->extendGlobalData($ubItems->getJSGlobals(GLOBALINFO_SELF));
}
// remove found spells if they are used by an item
if (!$ubItems->error)
{
foreach ($spellList->iterate() as $sId => $__)
{
// if Perm. Enchantment has a createItem its a Scroll of Enchantment (display both)
for ($i = 1; $i < 4; $i++)
if ($spellList->getField('effect'.$i.'Id') == 53 && $spellList->getField('effect'.$i.'CreateItemId'))
continue 2;
foreach ($ubItems->iterate() as $__)
{
for ($i = 1; $i < 6; $i++)
{
if ($ubItems->getField('spellId'.$i) == $sId)
{
unset($spellData[$sId]);
break 2;
}
}
}
}
}
$this->lvTabs[] = ['spell', array(
'data' => array_values($spellData),
'name' => '$LANG.tab_usedby + \' \' + LANG.types[6][0]',
'id' => 'used-by-spell',
)];
}
// used by randomAttrItem
$ire = DB::Aowow()->select(
'SELECT *, ABS(id) AS ARRAY_KEY FROM ?_itemrandomenchant WHERE enchantId1 = ?d OR enchantId2 = ?d OR enchantId3 = ?d OR enchantId4 = ?d OR enchantId5 = ?d',
$this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId
);
if ($ire)
{
if ($iet = DB::World()->select('SELECT entry AS ARRAY_KEY, ench, chance FROM item_enchantment_template WHERE ench IN (?a)', array_keys($ire)))
{
$randIds = []; // transform back to signed format
foreach ($iet as $tplId => $data)
$randIds[$ire[$data['ench']]['id'] > 0 ? $tplId : -$tplId] = $ire[$data['ench']]['id'];
$randItems = new ItemList(array(CFG_SQL_LIMIT_NONE, ['randomEnchant', array_keys($randIds)]));
if (!$randItems->error)
{
$data = $randItems->getListviewData();
foreach ($randItems->iterate() as $iId => $__)
{
$re = $randItems->getField('randomEnchant');
$data[$iId]['percent'] = $iet[abs($re)]['chance'];
$data[$iId]['count'] = 1; // expected by js or the pct-col becomes unsortable
$data[$iId]['rel'] = 'rand='.$ire[$iet[abs($re)]['ench']]['id'];
$data[$iId]['name'] .= ' '.Util::localizedString($ire[$iet[abs($re)]['ench']], 'name');
}
$this->lvTabs[] = ['item', array(
'data' => array_values($data),
'id' => 'used-by-rand',
'name' => '$LANG.tab_usedby + \' \' + \''.Lang::item('_rndEnchants').'\'',
'extraCols' => ['$Listview.extraCols.percent']
)];
$this->extendGlobalData($randItems->getJSGlobals(GLOBALINFO_SELF));
}
}
}
}
protected function generateTitle()
{
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('enchantment')));
}
protected function generatePath()
{
if ($_ = $this->getDistinctType())
$this->path[] = $_;
}
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 101: Enchantment g_initPath()
// tabId 0: Database g_initHeader()
class EnchantmentPage extends GenericPage
{
use DetailPage;
protected $type = TYPE_ENCHANTMENT;
protected $typeId = 0;
protected $tpl = 'enchantment';
protected $path = [0, 101];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
public function __construct($pageCall, $id)
{
parent::__construct($pageCall, $id);
$this->typeId = intVal($id);
$this->subject = new EnchantmentList(array(['id', $this->typeId]));
if ($this->subject->error)
$this->notFound(Util::ucFirst(Lang::game('enchantment')), Lang::enchantment('notFound'));
$this->extendGlobalData($this->subject->getJSGlobals());
$this->name = Util::ucFirst($this->subject->getField('name', true));
}
private function getDistinctType()
{
$type = 0;
for ($i = 1; $i < 4; $i++)
{
if ($_ = $this->subject->getField('type'.$i))
{
if ($type) // already set
return 0;
else
$type = $_;
}
}
return $type;
}
protected function generateContent()
{
/***********/
/* Infobox */
/***********/
$infobox = Lang::getInfoBoxForFlags($this->subject->getField('cuFlags'));
// reqLevel
if ($_ = $this->subject->getField('requiredLevel'))
$infobox[] = sprintf(Lang::game('reqLevel'), $_);
// reqskill
if ($_ = $this->subject->getField('skillLine'))
{
$this->extendGlobalIds(TYPE_SKILL, $_);
$foo = sprintf(Lang::game('requires'), '&nbsp;[skill='.$_.']');
if ($_ = $this->subject->getField('skillLevel'))
$foo .= ' ('.$_.')';
$infobox[] = $foo;
}
/****************/
/* Main Content */
/****************/
$this->infobox = $infobox ? '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]' : null;
$this->redButtons = array(
BUTTON_LINKS => ['type' => $this->type, 'typeId' => $this->typeId],
BUTTON_WOWHEAD => false
);
$this->effects = [];
// 3 effects
for ($i = 1; $i < 4; $i++)
{
$_ty = $this->subject->getField('type'.$i);
$_qty = $this->subject->getField('amount'.$i);
$_obj = $this->subject->getField('object'.$i);
switch ($_ty)
{
case 1:
case 3:
case 7:
$sArr = $this->subject->getField('spells')[$i];
$spl = $this->subject->getRelSpell($sArr[0]);
$this->effects[$i]['name'] = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Type: '.$_ty, Lang::item('trigger', $sArr[1])) : Lang::item('trigger', $sArr[1]);
$this->effects[$i]['proc'] = $sArr[3];
$this->effects[$i]['value'] = $_qty ?: null;
$this->effects[$i]['icon'] = array(
'name' => !$spl ? Util::ucFirst(Lang::game('spell')).' #'.$sArr[0] : Util::localizedString($spl, 'name'),
'id' => $sArr[0],
'count' => $sArr[2]
);
break;
case 5:
if ($_obj < 2) // [mana, health] are on [0, 1] respectively and are expected on [1, 2] ..
$_obj++; // 0 is weaponDmg .. ehh .. i messed up somewhere
$this->effects[$i]['tip'] = [$_obj, Util::$itemMods[$_obj]];
// DO NOT BREAK!
case 2:
case 6:
case 8:
case 4:
$this->effects[$i]['name'] = User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Type: '.$_ty, Lang::enchantment('types', $_ty)) : Lang::enchantment('types', $_ty);
$this->effects[$i]['value'] = $_qty;
if ($_ty == 4)
$this->effects[$i]['name'] .= Lang::main('colon').'('.(User::isInGroup(U_GROUP_EMPLOYEE) ? sprintf(Util::$dfnString, 'Object: '.$_obj, Lang::getMagicSchools(1 << $_obj)) : Lang::getMagicSchools(1 << $_obj)).')';
}
}
// activation conditions
if ($_ = $this->subject->getField('conditionId'))
{
$x = '';
if ($gemCnd = DB::Aowow()->selectRow('SELECT * FROM ?_itemenchantmentcondition WHERE id = ?d', $_))
{
for ($i = 1; $i < 6; $i++)
{
if (!$gemCnd['color'.$i])
continue;
$fiColors = function ($idx)
{
$foo = '';
switch ($idx)
{
case 2: $foo = '0:3:5'; break; // red
case 3: $foo = '2:4:5'; break; // yellow
case 4: $foo = '1:3:4'; break; // blue
}
return $foo;
};
$bLink = $gemCnd['color'.$i] ? '<a href="?items=3&filter=ty='.$fiColors($gemCnd['color'.$i]).'">'.Lang::item('gemColors', $gemCnd['color'.$i] - 1).'</a>' : '';
$cLink = $gemCnd['cmpColor'.$i] ? '<a href="?items=3&filter=ty='.$fiColors($gemCnd['cmpColor'.$i]).'">'.Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1).'</a>' : '';
switch ($gemCnd['comparator'.$i])
{
case 2: // requires less <color> than (<value> || <comparecolor>) gems
case 5: // requires at least <color> than (<value> || <comparecolor>) gems
$sp = (int)$gemCnd['value'.$i] > 1;
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.sprintf(Lang::item('gemConditions', $gemCnd['comparator'.$i], $sp), $gemCnd['value'.$i], $bLink).'</span><br />';
break;
case 3: // requires more <color> than (<value> || <comparecolor>) gems
$link = '<a href="?items=3&filter=ty='.$fiColors($gemCnd['cmpColor'.$i]).'">'.Lang::item('gemColors', $gemCnd['cmpColor'.$i] - 1).'</a>';
$x .= '<span class="q0">'.Lang::achievement('reqNumCrt').' '.sprintf(Lang::item('gemConditions', 3), $bLink, $cLink).'</span><br />';
break;
}
}
}
$this->activateCondition = $x;
}
/**************/
/* Extra Tabs */
/**************/
// used by gem
$gemList = new ItemList(array(['gemEnchantmentId', $this->typeId]));
if (!$gemList->error)
{
$this->lvTabs[] = ['item', array(
'data' => array_values($gemList->getListviewData()),
'name' => '$LANG.tab_usedby + \' \' + LANG.gems',
'id' => 'used-by-gem',
)];
$this->extendGlobalData($gemList->getJsGlobals());
}
// used by socket bonus
$socketsList = new ItemList(array(['socketBonus', $this->typeId]));
if (!$socketsList->error)
{
$this->lvTabs[] = ['item', array(
'data' => array_values($socketsList->getListviewData()),
'name' => '$LANG.tab_usedby + \' \' + \''.Lang::item('socketBonus').'\'',
'id' => 'used-by-socketbonus',
)];
$this->extendGlobalData($socketsList->getJsGlobals());
}
// used by spell
// used by useItem
$cnd = array(
'OR',
['AND', ['effect1Id', [53, 54, 156, 92]], ['effect1MiscValue', $this->typeId]],
['AND', ['effect2Id', [53, 54, 156, 92]], ['effect2MiscValue', $this->typeId]],
['AND', ['effect3Id', [53, 54, 156, 92]], ['effect3MiscValue', $this->typeId]],
);
$spellList = new SpellList($cnd);
if (!$spellList->error)
{
$spellData = $spellList->getListviewData();
$this->extendGlobalData($spellList->getJsGlobals());
$spellIds = $spellList->getFoundIDs();
$conditions = array(
'OR', // [use, useUndelayed]
['AND', ['spellTrigger1', [0, 5]], ['spellId1', $spellIds]],
['AND', ['spellTrigger2', [0, 5]], ['spellId2', $spellIds]],
['AND', ['spellTrigger3', [0, 5]], ['spellId3', $spellIds]],
['AND', ['spellTrigger4', [0, 5]], ['spellId4', $spellIds]],
['AND', ['spellTrigger5', [0, 5]], ['spellId5', $spellIds]]
);
$ubItems = new ItemList($conditions);
if (!$ubItems->error)
{
$this->lvTabs[] = ['item', array(
'data' => array_values($ubItems->getListviewData()),
'name' => '$LANG.tab_usedby + \' \' + LANG.types[3][0]',
'id' => 'used-by-item',
)];
$this->extendGlobalData($ubItems->getJSGlobals(GLOBALINFO_SELF));
}
// remove found spells if they are used by an item
if (!$ubItems->error)
{
foreach ($spellList->iterate() as $sId => $__)
{
// if Perm. Enchantment has a createItem its a Scroll of Enchantment (display both)
for ($i = 1; $i < 4; $i++)
if ($spellList->getField('effect'.$i.'Id') == 53 && $spellList->getField('effect'.$i.'CreateItemId'))
continue 2;
foreach ($ubItems->iterate() as $__)
{
for ($i = 1; $i < 6; $i++)
{
if ($ubItems->getField('spellId'.$i) == $sId)
{
unset($spellData[$sId]);
break 2;
}
}
}
}
}
$this->lvTabs[] = ['spell', array(
'data' => array_values($spellData),
'name' => '$LANG.tab_usedby + \' \' + LANG.types[6][0]',
'id' => 'used-by-spell',
)];
}
// used by randomAttrItem
$ire = DB::Aowow()->select(
'SELECT *, ABS(id) AS ARRAY_KEY FROM ?_itemrandomenchant WHERE enchantId1 = ?d OR enchantId2 = ?d OR enchantId3 = ?d OR enchantId4 = ?d OR enchantId5 = ?d',
$this->typeId, $this->typeId, $this->typeId, $this->typeId, $this->typeId
);
if ($ire)
{
if ($iet = DB::World()->select('SELECT entry AS ARRAY_KEY, ench, chance FROM item_enchantment_template WHERE ench IN (?a)', array_keys($ire)))
{
$randIds = []; // transform back to signed format
foreach ($iet as $tplId => $data)
$randIds[$ire[$data['ench']]['id'] > 0 ? $tplId : -$tplId] = $ire[$data['ench']]['id'];
$randItems = new ItemList(array(CFG_SQL_LIMIT_NONE, ['randomEnchant', array_keys($randIds)]));
if (!$randItems->error)
{
$data = $randItems->getListviewData();
foreach ($randItems->iterate() as $iId => $__)
{
$re = $randItems->getField('randomEnchant');
$data[$iId]['percent'] = $iet[abs($re)]['chance'];
$data[$iId]['count'] = 1; // expected by js or the pct-col becomes unsortable
$data[$iId]['rel'] = 'rand='.$ire[$iet[abs($re)]['ench']]['id'];
$data[$iId]['name'] .= ' '.Util::localizedString($ire[$iet[abs($re)]['ench']], 'name');
}
$this->lvTabs[] = ['item', array(
'data' => array_values($data),
'id' => 'used-by-rand',
'name' => '$LANG.tab_usedby + \' \' + \''.Lang::item('_rndEnchants').'\'',
'extraCols' => ['$Listview.extraCols.percent']
)];
$this->extendGlobalData($randItems->getJSGlobals(GLOBALINFO_SELF));
}
}
}
}
protected function generateTitle()
{
array_unshift($this->title, $this->name, Util::ucFirst(Lang::game('enchantment')));
}
protected function generatePath()
{
if ($_ = $this->getDistinctType())
$this->path[] = $_;
}
}
?>

View File

@@ -1,105 +1,105 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 101: Enchantment g_initPath()
// tabId 0: Database g_initHeader()
class EnchantmentsPage extends GenericPage
{
use ListPage;
protected $type = TYPE_ENCHANTMENT;
protected $tpl = 'enchantments';
protected $path = [0, 101];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
protected $js = ['filters.js'];
public function __construct($pageCall, $pageParam)
{
$this->filterObj = new EnchantmentListFilter();
$this->getCategoryFromUrl($pageParam);;
parent::__construct($pageCall, $pageParam);
$this->name = Util::ucFirst(Lang::game('enchantments'));
$this->subCat = $pageParam !== null ? '='.$pageParam : '';
}
protected function generateContent()
{
$tabData = array(
'data' => [],
'name' => Util::ucFirst(Lang::game('enchantments'))
);
$conditions = [];
if (!User::isInGroup(U_GROUP_EMPLOYEE))
$conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
if ($_ = $this->filterObj->getConditions())
$conditions[] = $_;
$ench = new EnchantmentList($conditions);
$tabData['data'] = array_values($ench->getListviewData());
$this->extendGlobalData($ench->getJSGlobals());
// recreate form selection
$this->filter = array_merge($this->filterObj->getForm('form'), $this->filter);
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
$this->filter['fi'] = $this->filterObj->getForm();
$xCols = $this->filterObj->getForm('extraCols', true);
foreach (Util::$itemFilter as $fiId => $str)
if (array_column($tabData['data'], $str))
$xCols[] = $fiId;
if (array_column($tabData['data'], 'dmg'))
$xCols[] = 34;
if ($xCols)
$this->filter['fi']['extraCols'] = "fi_extraCols = ".Util::toJSON(array_values(array_unique($xCols))).";";
if (!empty($this->filter['fi']['extraCols']))
$tabData['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
if ($ench->getMatches() > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_enchantmentsfound', $ench->getMatches(), CFG_SQL_LIMIT_DEFAULT);
$tabData['_truncated'] = 1;
}
if (array_filter(array_column($tabData['data'], 'spells')))
$tabData['visibleCols'] = ['trigger'];
if (!$ench->hasSetFields(['skillLine']))
$tabData['hiddenCols'] = ['skill'];
if ($this->filterObj->error)
$tabData['_errors'] = '$1';
$this->lvTabs[] = ['enchantment', $tabData, 'enchantment'];
}
protected function generateTitle()
{
$form = $this->filterObj->getForm('form');
if (!empty($form['ty']) && intVal($form['ty']) && $form['ty'] > 0 && $form['ty'] < 9)
array_unshift($this->title, Lang::enchantment('types', $form['ty']));
array_unshift($this->title, $this->name);
}
protected function generatePath()
{
$form = $this->filterObj->getForm('form');
if (isset($form['ty']) && !is_array($form['ty']))
$this->path[] = $form['ty'];
}
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
// menuId 101: Enchantment g_initPath()
// tabId 0: Database g_initHeader()
class EnchantmentsPage extends GenericPage
{
use ListPage;
protected $type = TYPE_ENCHANTMENT;
protected $tpl = 'enchantments';
protected $path = [0, 101];
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
protected $js = ['filters.js'];
public function __construct($pageCall, $pageParam)
{
$this->filterObj = new EnchantmentListFilter();
$this->getCategoryFromUrl($pageParam);;
parent::__construct($pageCall, $pageParam);
$this->name = Util::ucFirst(Lang::game('enchantments'));
$this->subCat = $pageParam !== null ? '='.$pageParam : '';
}
protected function generateContent()
{
$tabData = array(
'data' => [],
'name' => Util::ucFirst(Lang::game('enchantments'))
);
$conditions = [];
if (!User::isInGroup(U_GROUP_EMPLOYEE))
$conditions[] = [['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0];
if ($_ = $this->filterObj->getConditions())
$conditions[] = $_;
$ench = new EnchantmentList($conditions);
$tabData['data'] = array_values($ench->getListviewData());
$this->extendGlobalData($ench->getJSGlobals());
// recreate form selection
$this->filter = array_merge($this->filterObj->getForm('form'), $this->filter);
$this->filter['query'] = isset($_GET['filter']) ? $_GET['filter'] : NULL;
$this->filter['fi'] = $this->filterObj->getForm();
$xCols = $this->filterObj->getForm('extraCols', true);
foreach (Util::$itemFilter as $fiId => $str)
if (array_column($tabData['data'], $str))
$xCols[] = $fiId;
if (array_column($tabData['data'], 'dmg'))
$xCols[] = 34;
if ($xCols)
$this->filter['fi']['extraCols'] = "fi_extraCols = ".Util::toJSON(array_values(array_unique($xCols))).";";
if (!empty($this->filter['fi']['extraCols']))
$tabData['extraCols'] = '$fi_getExtraCols(fi_extraCols, 0, 0)';
if ($ench->getMatches() > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['note'] = sprintf(Util::$tryFilteringString, 'LANG.lvnote_enchantmentsfound', $ench->getMatches(), CFG_SQL_LIMIT_DEFAULT);
$tabData['_truncated'] = 1;
}
if (array_filter(array_column($tabData['data'], 'spells')))
$tabData['visibleCols'] = ['trigger'];
if (!$ench->hasSetFields(['skillLine']))
$tabData['hiddenCols'] = ['skill'];
if ($this->filterObj->error)
$tabData['_errors'] = '$1';
$this->lvTabs[] = ['enchantment', $tabData, 'enchantment'];
}
protected function generateTitle()
{
$form = $this->filterObj->getForm('form');
if (!empty($form['ty']) && intVal($form['ty']) && $form['ty'] > 0 && $form['ty'] < 9)
array_unshift($this->title, Lang::enchantment('types', $form['ty']));
array_unshift($this->title, $this->name);
}
protected function generatePath()
{
$form = $this->filterObj->getForm('form');
if (isset($form['ty']) && !is_array($form['ty']))
$this->path[] = $form['ty'];
}
}
?>

View File

@@ -1,263 +1,263 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class UserPage extends GenericPage
{
protected $tpl = 'user';
protected $js = ['user.js', 'profile.js'];
protected $css = [['path' => 'Profiler.css']];
protected $mode = CACHE_TYPE_NONE;
protected $typeId = 0;
protected $pageName = '';
public function __construct($pageCall, $pageParam)
{
parent::__construct($pageCall, $pageParam);
if ($pageParam)
{
// todo: check if account is disabled or something
if ($user = DB::Aowow()->selectRow('SELECT a.id, a.user, a.displayName, a.consecutiveVisits, a.userGroups, a.avatar, a.title, a.description, a.joinDate, a.prevLogin, IFNULL(SUM(ar.amount), 0) AS sumRep FROM ?_account a LEFT JOIN ?_account_reputation ar ON a.id = ar.userId WHERE a.user = ? GROUP BY a.id', $pageParam))
$this->user = $user;
else
$this->notFound(sprintf(Lang::user('notFound'), $pageParam));
}
else if (User::$id)
{
header('Location: ?user='.User::$displayName, true, 302);
die();
}
else
$this->forwardToSignIn('user');
}
protected function generateContent()
{
/***********/
/* Infobox */
/***********/
$infobox = $contrib = $groups = [];
foreach (Lang::account('groups') as $idx => $key)
if ($idx >= 0 && $this->user['userGroups'] & (1 << $idx))
$groups[] = (!fMod(count($groups) + 1, 3) ? '[br]' : null).Lang::account('groups', $idx);
$infobox[] = Lang::user('joinDate'). Lang::main('colon').'[tooltip name=joinDate]'. date('l, G:i:s', $this->user['joinDate']). '[/tooltip][span class=tip tooltip=joinDate]'. date(Lang::main('dateFmtShort'), $this->user['joinDate']). '[/span]';
$infobox[] = Lang::user('lastLogin').Lang::main('colon').'[tooltip name=lastLogin]'.date('l, G:i:s', $this->user['prevLogin']).'[/tooltip][span class=tip tooltip=lastLogin]'.date(Lang::main('dateFmtShort'), $this->user['prevLogin']).'[/span]';
$infobox[] = Lang::user('userGroups').Lang::main('colon').($groups ? implode(', ', $groups) : Lang::account('groups', -1));
$infobox[] = Lang::user('consecVisits').Lang::main('colon').$this->user['consecutiveVisits'];
$infobox[] = Util::ucFirst(Lang::main('siteRep')).Lang::main('colon').Lang::nf($this->user['sumRep']);
// contrib -> [url=http://www.wowhead.com/client]Data uploads: n [small]([tooltip=tooltip_totaldatauploads]xx.y MB[/tooltip])[/small][/url]
$co = DB::Aowow()->selectRow(
'SELECT COUNT(DISTINCT c.id) AS sum, SUM(IFNULL(cr.value, 0)) AS nRates FROM ?_comments c LEFT JOIN ?_comments_rates cr ON cr.commentId = c.id AND cr.userId <> 0 WHERE c.replyTo = 0 AND c.userId = ?d',
$this->user['id']
);
if ($co['sum'])
$contrib[] = Lang::user('comments').Lang::main('colon').$co['sum'].($co['nRates'] ? ' [small]([tooltip=tooltip_totalratings]'.$co['nRates'].'[/tooltip])[/small]' : null);
$ss = DB::Aowow()->selectRow('SELECT COUNT(*) AS sum, SUM(IF(status & ?d, 1, 0)) AS nSticky, SUM(IF(status & ?d, 0, 1)) AS nPending FROM ?_screenshots WHERE userIdOwner = ?d AND (status & ?d) = 0',
CC_FLAG_STICKY,
CC_FLAG_APPROVED,
$this->user['id'],
CC_FLAG_DELETED
);
if ($ss['sum'])
{
$buff = [];
if ($ss['nSticky'] || $ss['nPending'])
{
if ($normal = ($ss['sum'] - $ss['nSticky'] - $ss['nPending']))
$buff[] = '[tooltip=tooltip_normal]'.$normal.'[/tooltip]';
if ($ss['nSticky'])
$buff[] = '[tooltip=tooltip_sticky]'.$ss['nSticky'].'[/tooltip]';
if ($ss['nPending'])
$buff[] = '[tooltip=tooltip_pending]'.$ss['nPending'].'[/tooltip]';
}
$contrib[] = Lang::user('screenshots').Lang::main('colon').$ss['sum'].($buff ? ' [small]('.implode($buff, ' + ').')[/small]' : null);
}
$vi = DB::Aowow()->selectRow('SELECT COUNT(id) AS sum, SUM(IF(status & ?d, 1, 0)) AS nSticky, SUM(IF(status & ?d, 0, 1)) AS nPending FROM ?_videos WHERE userIdOwner = ?d AND (status & ?d) = 0',
CC_FLAG_STICKY,
CC_FLAG_APPROVED,
$this->user['id'],
CC_FLAG_DELETED
);
if ($vi['sum'])
{
$buff = [];
if ($vi['nSticky'] || $vi['nPending'])
{
if ($normal = ($vi['sum'] - $vi['nSticky'] - $vi['nPending']))
$buff[] = '[tooltip=tooltip_normal]'.$normal.'[/tooltip]';
if ($vi['nSticky'])
$buff[] = '[tooltip=tooltip_sticky]'.$vi['nSticky'].'[/tooltip]';
if ($vi['nPending'])
$buff[] = '[tooltip=tooltip_pending]'.$vi['nPending'].'[/tooltip]';
}
$contrib[] = Lang::user('videos').Lang::main('colon').$vi['sum'].($buff ? ' [small]('.implode($buff, ' + ').')[/small]' : null);
}
// contrib -> Forum posts: 5769 [small]([tooltip=topics]579[/tooltip] + [tooltip=replies]5190[/tooltip])[/small]
$this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]';
if ($contrib)
$this->contributions = '[ul][li]'.implode('[/li][li]', $contrib).'[/li][/ul]';
/****************/
/* Main Content */
/****************/
$this->name = $this->user['title'] ? $this->user['displayName'].'&nbsp;&lt;'.$this->user['title'].'&gt;' : sprintf(Lang::user('profileTitle'), $this->user['displayName']);
/**************/
/* Extra Tabs */
/**************/
$this->lvTabs = [];
$this->forceTabs = true;
// [unused] Site Achievements
// Reputation changelog (params only for comment-events)
if ($repData = DB::Aowow()->select('SELECT action, amount, date AS \'when\', IF(action IN (3, 4, 5), sourceA, 0) AS param FROM ?_account_reputation WHERE userId = ?d', $this->user['id']))
{
foreach ($repData as &$r)
$r['when'] = date(Util::$dateFormatInternal, $r['when']);
$this->lvTabs[] = ['reputationhistory', ['data' => $repData]];
}
// Comments
if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => false], $nFound))
{
$tabData = array(
'data' => $_,
'hiddenCols' => ['author'],
'onBeforeCreate' => '$Listview.funcBox.beforeUserComments',
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestcomments';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_usercomments, '.$nFound.')';
}
$this->lvTabs[] = ['commentpreview', $tabData];
}
// Comment Replies
if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => true], $nFound))
{
$tabData = array(
'data' => $_,
'hiddenCols' => ['author'],
'onBeforeCreate' => '$Listview.funcBox.beforeUserComments',
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestreplies';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_userreplies, '.$nFound.')';
}
$this->lvTabs[] = ['replypreview', $tabData];
}
// Screenshots
if ($_ = CommunityContent::getScreenshots(-$this->user['id'], 0, $nFound))
{
$tabData = array(
'data' => $_,
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestscreenshots';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_userscreenshots, '.$nFound.')';
}
$this->lvTabs[] = ['screenshot', $tabData];
}
// Videos
if ($_ = CommunityContent::getVideos(-$this->user['id'], 0, $nFound))
{
$tabData = array(
'data' => $_,
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestvideos';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_uservideos, '.$nFound.')';
}
$this->lvTabs[] = ['video', $tabData];
}
// forum -> latest topics [unused]
// forum -> latest replies [unused]
// Characters [todo]
$this->user['characterData'] = [];
/*
us_addCharactersTab([
{
id:763,
"name":"Lilywhite",
"achievementpoints":"0",
"guild":"whatever",
"guildrank":"0",
"realm":"draenor",
"realmname":"Draenor",
"battlegroup":"cyclone",
"battlegroupname":"Cyclone",
"region":"us",
"level":"10",
"race":"7",
"gender":"0",
"classs":"1",
"faction":"0",
"gearscore":"0",
"talenttree1":"0",
"talenttree2":"0",
"talenttree3":"0",
"talentspec":0,
"published":1,
"pinned":0
}
]);
*/
// Profiles [todo]
$this->user['profileData'] = [];
}
protected function generateTitle()
{
array_unshift($this->title, sprintf(Lang::user('profileTitle'), $this->user['displayName']));
}
protected function generatePath() { }
}
?>
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
class UserPage extends GenericPage
{
protected $tpl = 'user';
protected $js = ['user.js', 'profile.js'];
protected $css = [['path' => 'Profiler.css']];
protected $mode = CACHE_TYPE_NONE;
protected $typeId = 0;
protected $pageName = '';
public function __construct($pageCall, $pageParam)
{
parent::__construct($pageCall, $pageParam);
if ($pageParam)
{
// todo: check if account is disabled or something
if ($user = DB::Aowow()->selectRow('SELECT a.id, a.user, a.displayName, a.consecutiveVisits, a.userGroups, a.avatar, a.title, a.description, a.joinDate, a.prevLogin, IFNULL(SUM(ar.amount), 0) AS sumRep FROM ?_account a LEFT JOIN ?_account_reputation ar ON a.id = ar.userId WHERE a.user = ? GROUP BY a.id', $pageParam))
$this->user = $user;
else
$this->notFound(sprintf(Lang::user('notFound'), $pageParam));
}
else if (User::$id)
{
header('Location: ?user='.User::$displayName, true, 302);
die();
}
else
$this->forwardToSignIn('user');
}
protected function generateContent()
{
/***********/
/* Infobox */
/***********/
$infobox = $contrib = $groups = [];
foreach (Lang::account('groups') as $idx => $key)
if ($idx >= 0 && $this->user['userGroups'] & (1 << $idx))
$groups[] = (!fMod(count($groups) + 1, 3) ? '[br]' : null).Lang::account('groups', $idx);
$infobox[] = Lang::user('joinDate'). Lang::main('colon').'[tooltip name=joinDate]'. date('l, G:i:s', $this->user['joinDate']). '[/tooltip][span class=tip tooltip=joinDate]'. date(Lang::main('dateFmtShort'), $this->user['joinDate']). '[/span]';
$infobox[] = Lang::user('lastLogin').Lang::main('colon').'[tooltip name=lastLogin]'.date('l, G:i:s', $this->user['prevLogin']).'[/tooltip][span class=tip tooltip=lastLogin]'.date(Lang::main('dateFmtShort'), $this->user['prevLogin']).'[/span]';
$infobox[] = Lang::user('userGroups').Lang::main('colon').($groups ? implode(', ', $groups) : Lang::account('groups', -1));
$infobox[] = Lang::user('consecVisits').Lang::main('colon').$this->user['consecutiveVisits'];
$infobox[] = Util::ucFirst(Lang::main('siteRep')).Lang::main('colon').Lang::nf($this->user['sumRep']);
// contrib -> [url=http://www.wowhead.com/client]Data uploads: n [small]([tooltip=tooltip_totaldatauploads]xx.y MB[/tooltip])[/small][/url]
$co = DB::Aowow()->selectRow(
'SELECT COUNT(DISTINCT c.id) AS sum, SUM(IFNULL(cr.value, 0)) AS nRates FROM ?_comments c LEFT JOIN ?_comments_rates cr ON cr.commentId = c.id AND cr.userId <> 0 WHERE c.replyTo = 0 AND c.userId = ?d',
$this->user['id']
);
if ($co['sum'])
$contrib[] = Lang::user('comments').Lang::main('colon').$co['sum'].($co['nRates'] ? ' [small]([tooltip=tooltip_totalratings]'.$co['nRates'].'[/tooltip])[/small]' : null);
$ss = DB::Aowow()->selectRow('SELECT COUNT(*) AS sum, SUM(IF(status & ?d, 1, 0)) AS nSticky, SUM(IF(status & ?d, 0, 1)) AS nPending FROM ?_screenshots WHERE userIdOwner = ?d AND (status & ?d) = 0',
CC_FLAG_STICKY,
CC_FLAG_APPROVED,
$this->user['id'],
CC_FLAG_DELETED
);
if ($ss['sum'])
{
$buff = [];
if ($ss['nSticky'] || $ss['nPending'])
{
if ($normal = ($ss['sum'] - $ss['nSticky'] - $ss['nPending']))
$buff[] = '[tooltip=tooltip_normal]'.$normal.'[/tooltip]';
if ($ss['nSticky'])
$buff[] = '[tooltip=tooltip_sticky]'.$ss['nSticky'].'[/tooltip]';
if ($ss['nPending'])
$buff[] = '[tooltip=tooltip_pending]'.$ss['nPending'].'[/tooltip]';
}
$contrib[] = Lang::user('screenshots').Lang::main('colon').$ss['sum'].($buff ? ' [small]('.implode($buff, ' + ').')[/small]' : null);
}
$vi = DB::Aowow()->selectRow('SELECT COUNT(id) AS sum, SUM(IF(status & ?d, 1, 0)) AS nSticky, SUM(IF(status & ?d, 0, 1)) AS nPending FROM ?_videos WHERE userIdOwner = ?d AND (status & ?d) = 0',
CC_FLAG_STICKY,
CC_FLAG_APPROVED,
$this->user['id'],
CC_FLAG_DELETED
);
if ($vi['sum'])
{
$buff = [];
if ($vi['nSticky'] || $vi['nPending'])
{
if ($normal = ($vi['sum'] - $vi['nSticky'] - $vi['nPending']))
$buff[] = '[tooltip=tooltip_normal]'.$normal.'[/tooltip]';
if ($vi['nSticky'])
$buff[] = '[tooltip=tooltip_sticky]'.$vi['nSticky'].'[/tooltip]';
if ($vi['nPending'])
$buff[] = '[tooltip=tooltip_pending]'.$vi['nPending'].'[/tooltip]';
}
$contrib[] = Lang::user('videos').Lang::main('colon').$vi['sum'].($buff ? ' [small]('.implode($buff, ' + ').')[/small]' : null);
}
// contrib -> Forum posts: 5769 [small]([tooltip=topics]579[/tooltip] + [tooltip=replies]5190[/tooltip])[/small]
$this->infobox = '[ul][li]'.implode('[/li][li]', $infobox).'[/li][/ul]';
if ($contrib)
$this->contributions = '[ul][li]'.implode('[/li][li]', $contrib).'[/li][/ul]';
/****************/
/* Main Content */
/****************/
$this->name = $this->user['title'] ? $this->user['displayName'].'&nbsp;&lt;'.$this->user['title'].'&gt;' : sprintf(Lang::user('profileTitle'), $this->user['displayName']);
/**************/
/* Extra Tabs */
/**************/
$this->lvTabs = [];
$this->forceTabs = true;
// [unused] Site Achievements
// Reputation changelog (params only for comment-events)
if ($repData = DB::Aowow()->select('SELECT action, amount, date AS \'when\', IF(action IN (3, 4, 5), sourceA, 0) AS param FROM ?_account_reputation WHERE userId = ?d', $this->user['id']))
{
foreach ($repData as &$r)
$r['when'] = date(Util::$dateFormatInternal, $r['when']);
$this->lvTabs[] = ['reputationhistory', ['data' => $repData]];
}
// Comments
if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => false], $nFound))
{
$tabData = array(
'data' => $_,
'hiddenCols' => ['author'],
'onBeforeCreate' => '$Listview.funcBox.beforeUserComments',
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestcomments';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_usercomments, '.$nFound.')';
}
$this->lvTabs[] = ['commentpreview', $tabData];
}
// Comment Replies
if ($_ = CommunityContent::getCommentPreviews(['user' => $this->user['id'], 'replies' => true], $nFound))
{
$tabData = array(
'data' => $_,
'hiddenCols' => ['author'],
'onBeforeCreate' => '$Listview.funcBox.beforeUserComments',
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestreplies';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_userreplies, '.$nFound.')';
}
$this->lvTabs[] = ['replypreview', $tabData];
}
// Screenshots
if ($_ = CommunityContent::getScreenshots(-$this->user['id'], 0, $nFound))
{
$tabData = array(
'data' => $_,
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestscreenshots';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_userscreenshots, '.$nFound.')';
}
$this->lvTabs[] = ['screenshot', $tabData];
}
// Videos
if ($_ = CommunityContent::getVideos(-$this->user['id'], 0, $nFound))
{
$tabData = array(
'data' => $_,
'_totalCount' => $nFound
);
if ($nFound > CFG_SQL_LIMIT_DEFAULT)
{
$tabData['name'] = '$LANG.tab_latestvideos';
$tabData['note'] = '$$WH.sprintf(LANG.lvnote_uservideos, '.$nFound.')';
}
$this->lvTabs[] = ['video', $tabData];
}
// forum -> latest topics [unused]
// forum -> latest replies [unused]
// Characters [todo]
$this->user['characterData'] = [];
/*
us_addCharactersTab([
{
id:763,
"name":"Lilywhite",
"achievementpoints":"0",
"guild":"whatever",
"guildrank":"0",
"realm":"draenor",
"realmname":"Draenor",
"battlegroup":"cyclone",
"battlegroupname":"Cyclone",
"region":"us",
"level":"10",
"race":"7",
"gender":"0",
"classs":"1",
"faction":"0",
"gearscore":"0",
"talenttree1":"0",
"talenttree2":"0",
"talenttree3":"0",
"talentspec":0,
"published":1,
"pinned":0
}
]);
*/
// Profiles [todo]
$this->user['profileData'] = [];
}
protected function generateTitle()
{
array_unshift($this->title, sprintf(Lang::user('profileTitle'), $this->user['displayName']));
}
protected function generatePath() { }
}
?>

View File

@@ -1,301 +1,301 @@
var mn_content = [
// [22, 'Achievements', '?admin=achievements', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV | U_GROUP_BUREAU}],
[3, 'Announcements', '?admin=announcements', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [25, 'Guides Awaiting Approval', '?admin=guides', null, {requiredAccess: U_GROUP_STAFF}],
// [20, 'Global Images & Headers', '?admin=headers', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [21, 'Modelviewer', '?admin=modelviewer', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
[23, 'Out of Date Comments', '?admin=out-of-date', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD}],
[5, 'Screenshots', '?admin=screenshots', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT}],
// [18, 'Upload Image', '?npc=15384#submit-a-screenshot', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR, rel: 'np'}],
[17, 'Videos', '?admin=videos', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_VIDEO}],
[, 'Homepage'],
[13, 'Featured Box', '?admin=home-featuredbox', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Homepage Featured Box'}],
[14, 'Oneliners', '?admin=home-oneliners', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Homepage Oneliners'}],
// [15, 'Skins', '?admin=home-skins', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SALESAGENT, breadcrumb: 'Homepage Skins'}],
[16, 'Titles', '?admin=home-titles', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Homepage Titles'}],
// [, 'Articles'],
// [8, 'List', '?admin=articles', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_EDITOR | U_GROUP_LOCALIZER, breadcrumb: 'List of Articles'}],
// [9, 'Editors\' Lounge', '?admin=editors-lounge', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_EDITOR | U_GROUP_LOCALIZER}],
// [23, 'Related Links', '?admin=related-links', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [, 'News'],
// [10, 'New Post', '?edit=news', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER, breadcrumb: 'News Post'}],
// [11, 'Content Corner', '?admin=content-corner', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER}],
// [12, 'Tags', '?admin=newstag', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_BLOGGER, breadcrumb: 'News Tags'}],
// [24, 'Patch Updates', '?admin=patch-updates', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [26, 'Featured Guides', '?admin=featuredguides', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Featured Guides'}],
// [, 'Community'],
// [4, 'Contests', '?admin=contests', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SALESAGENT}],
// [27, 'Top User Contest', '?admin=topuser-contest', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SALESAGENT}],
// [19, 'Forums', '?admin=forums', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [6, 'Profanity Filter', '?admin=profanity', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [, 'Other'],
// [7, 'Holiday Gift Guide', '?admin=holidaygift', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}]
];
var mn_dev = [
// [17, 'Cookies', '?admin=cookies', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[21, 'PHP Information', '?admin=phpinfo', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[18, 'Site Configuration', '?admin=siteconfig', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[16, 'Weight Presets', '?admin=weight-presets', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
// [22, 'API Keys', '?admin=apikey', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
// [, 'Cache'],
// [2, 'Create Folders', '?admin=cache-folder', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Create Cache Folders'}],
// [3, 'Expire Range', '?admin=cache-expire', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Expire Cache Range'}],
// [1, 'Manage', '?admin=cache-manage', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Manage Cache'}],
// [20, 'Memcached', '?admin=memcached', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Manage Memcached'}],
// [, 'Database'],
// [8, 'Add Fake Item', '?admin=fakeitem', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [10, 'Add Fake NPC', '?admin=fakenpc', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [19, 'Check Consistency', '?admin=db-check-consistency', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Check Database Consistency'}],
// [4, 'Execute SQL', '?admin=sql', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [9, 'Export Fake Item', '?admin=luaitem', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [26, 'Denormalized Fields Fix', '?admin=denormalized-fix', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [11, 'Minimum & Maximum Values', '?admin=minmax', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [7, 'SQL Find & Replace', '?admin=sql-replace', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [25, 'Switch Active Database', '?admin=active-db', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [5, 'Updates', '?admin=db-update', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Database Updates'}],
// [, 'Generators'],
// [12, 'Talent Calculator Icons', '?admin=talentcalc-icons', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}]
];
var mn_localization = [
[1, 'Generate Files', '?admin=locale-export', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Generate Localization Files'}],
[, 'Terms'],
[4, 'Check Integrity', '?admin=locale-integrity', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_LOCALIZER, breadcrumb: 'Check Term Integrity'}],
[2, 'Manage', '?admin=locale-search', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_LOCALIZER, breadcrumb: 'Manage Terms'}],
[, 'Deprecated'],
[6, 'Create Template', '?admin=locale-template', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Create Localization Template'}],
[5, 'Import Old Localized File', '?admin=locale-import', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[7, 'Upload Global Strings', '?admin=locale-upload', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}]
];
var mn_statistics = [
[1, 'Comments', '?admin=stats&table=comments'],
[2, 'Comment Votes', '?admin=stats&table=commentratings'],
[3, 'Forum Posts', '?admin=stats&table=forumposts'],
[5, 'Registrations', '?admin=stats&table=registrations'],
[4, 'Screenshots', '?admin=stats&table=screenshots'],
[7, 'Uploads', '?admin=stats&table=uploads'],
[6, 'Videos', '?admin=stats&table=videos'],
[8, 'Vists by Registered Users', '?admin=stats&table=visits-by-registered']
];
var mn_users = [
[2, 'Action Log', '?admin=log', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
[3, 'Banned IPs', '?admin=bannedip', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
[1, 'Manage', '?admin=finduser', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MODERATOR, breadcrumb: 'Manage Users'}],
[5, 'Roles', '?admin=staff', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MODERATOR}],
[, 'Deprecated'],
[4, 'Get Registration Email', '?admin=getregistrationemail', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}]
];
var mn_staff = [
[1, 'Content', null, mn_content],
[2, 'Development', null, mn_dev],
// [3, 'Localization', null, mn_localization],
// [7, 'Statistics', null, mn_statistics, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
// [4, 'Users', null, mn_users],
// [5, 'View Reports', '?admin=reports', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR | U_GROUP_MOD | U_GROUP_LOCALIZER | U_GROUP_SCREENSHOT | U_GROUP_VIDEO} ],
[, 'Page'],
[102, 'Validate', 'http://validator.w3.org/check/referer', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_TESTER}]];
mn_path.push([4, 'Staff', null, mn_staff]);
$(document).ready(function () {
var footer = $('div.stafffooter');
if (footer.length > 0) {
var totalHeight = $(window).height();
if (footer.offset().top < (totalHeight - 100)) {
var offset = footer.offset();
offset.top = totalHeight - 100;
footer.offset(offset);
}
}
var articleAccess = U_GROUP_EMPLOYEE | U_GROUP_EDITOR | (Locale.getId() != LOCALE_ENUS ? U_GROUP_LOCALIZER : 0);
var urlParams = $WH.g_getGets();
var buff;
var refresh = {};
var subMenu = null;
if (urlParams.refresh != null) {
buff = 'See Cached';
refresh.refresh = null
}
else {
var mCached = {};
var fiCache = {};
buff = 'Refresh';
if (PageTemplate.get('pageName') == 'home') {
refresh.home = '';
mCached.home = '';
fiCache.home = ''
}
refresh.refresh = '';
mCached.refresh = 'memcached';
fiCache.refresh = 'filecache';
subMenu = [
[1, 'Memcached', g_modifyUrl(location.href, mCached), null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
[2, 'File cache', g_modifyUrl(location.href, fiCache), null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}]
]
}
mn_staff.push([100, buff, g_modifyUrl(location.href, refresh), subMenu, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}]);
if (location.href.match(/website-achievement=([0-9]+)(\/.*)?/i)) {
mn_staff.push([, 'Achievement']);
mn_staff.push([200, 'Manage', '?admin=achievements&action=edit&id=' + RegExp.$1, null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV | U_GROUP_BUREAU}])
}
if (location.href.match(/website-achievements(\/.*)?/i)) {
mn_staff.push([, 'Achievements']);
mn_staff.push([200, 'Manage', '?admin=achievements', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV | U_GROUP_BUREAU}])
}
if (location.href.match(/news=([0-9]+)(\/.*)/i)) {
mn_staff.push([, 'News Post']);
mn_staff.push([200, 'Edit', '?edit=news&id=' + RegExp.$1, null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER}]);
mn_staff.push([203, 'View forum topic', '/forums&topic=' + RegExp.$1, null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER}])
}
if (location.href.match(/user=([a-z0-9]+)/i)) {
mn_staff.push([, 'User']);
mn_staff.push([201, 'Manage', '?admin=manageuser&name=' + RegExp.$1, null, {requiredAccess: U_GROUP_MODERATOR}])
}
if ($WH.isset('g_pageInfo')) {
if (g_pageInfo.type && g_pageInfo.typeId) {
mn_staff.push([, 'DB Entry']);
// mn_staff.push([1001, 'Edit Article', '?edit=article&type=' + g_pageInfo.type + '&typeid=' + g_pageInfo.typeId, null, {requiredAccess: articleAccess}]);
mn_staff.push([1000, 'Manage Screenshots', '?admin=screenshots&type=' + g_pageInfo.type + '&typeid=' + g_pageInfo.typeId, null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT}]);
mn_staff.push([1000, 'Manage Videos', '?admin=videos&type=' + g_pageInfo.type + '&typeid=' + g_pageInfo.typeId, null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_VIDEO}])
}
if (g_pageInfo.articleUrl) {
mn_staff.push([, 'Article']);
mn_staff.push([1002, 'Edit', '?edit=article&' + g_pageInfo.articleUrl, null, {requiredAccess: (g_pageInfo.editAccess ? g_pageInfo.editAccess: articleAccess)}]);
mn_staff.push([1003, 'Options', '?edit=article-options&url=' + g_pageInfo.articleUrl, null, {requiredAccess: articleAccess}])
}
}
Menu.sort(mn_staff)
});
var staff_deleteCacheKey = function (b, key) {
var div = $('#purge-memcache' + b);
var url = '?purgekey=' + key;
var data = {};
if ($.isArray(key)) {
url = '?purgekey';
data.keys = key;
}
$.ajax({
method: 'GET',
url: url,
data: data,
success: function (x) {
if (x == 0) {
this.replaceWith('<span class="q2">Key successfully deleted!</span>');
}
else {
this.replaceWith('<span style="color: red">Key deletion failed: ' + x + '</span>');
}
}.bind(div)
})
};
$(document).ready(function () {
$('#save-blog-form').submit(function () {
var form = $(this);
var blogId = form.find('input[name=blog-id]').val();
form.find('.spinning-circle').show();
form.find('input[type=submit]').attr('disabled', 'disabled').val('Saving..');
form.find('#save-status').html('');
leavePage(1);
$.ajax({
url: '?edit=news&id=' + blogId,
async: true,
cache: false,
data: $(this).serialize(),
type: 'POST',
error: function () {
alert('An error has occured. The news was not saved.')
},
success: function (data) {
var response = eval(data);
if (!response.success) {
alert('An error has occured, the news was not saved: ' + response.message);
return
}
form.find('input[name=blog-id]').val(response.entry);
form.find('#save-status').html('<span class="q2">Your news has been saved!</span> [<a target="_blank" href="' + response.url + '">link</a>]')
},
complete: function () {
form.find('.spinning-circle').hide();
form.find('input[type=submit]').attr('disabled', '').val('Save')
}
});
return false
})
});
var listviewIdList = new function () {
function onShow(container, i, str) {
Lightbox.setSize(950, 590);
if (i) {
container.className = 'modelviewer';
var div = $WH.ce('div');
var pre = $WH.ce('pre');
container.debug = pre;
pre.className = 'code';
$WH.ae(div, pre);
$WH.ae(container, div);
var a = $WH.ce('a');
a.className = 'modelviewer-close';
a.href = 'javascript:;';
a.onclick = Lightbox.hide;
$WH.ae(a, $WH.ce('span'));
$WH.ae(container, a);
clear = $WH.ce('div');
clear.className = 'clear';
$WH.ae(container, clear);
}
var ta = $('<textarea>').css('height', '100px').css('width', '100%').text(str);
$WH.ee(container.debug);
$WH.ae(container.debug, ta[0]);
}
this.show = function (str) {
Lightbox.show('debuginfo', { onShow: onShow }, str);
}
};
var TwigProfiler = new function () {
this.show = function (rows) {
if (!rows) {
rows = [];
}
var len = rows.length;
$('#footer-twig-count').text(len);
var tbl = $('#footer-twig-table');
for (var i = 0; i < len; ++i) {
tbl.append($('<tr/>')
.append($('<td/>', {css: {'white-space': 'nowrap', 'text-align': 'right'}, 'class': 'q2', text: rows[i].action} ))
.append($('<td/>', {css: {'white-space': 'nowrap'}} ).append($('<small/>', {text: rows[i].name} )))
.append($('<td/>', {css: {'white-space': 'nowrap'}} ).append($('<small/>', {text: rows[i].time} )))
);
}
}
};
var mn_content = [
// [22, 'Achievements', '?admin=achievements', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV | U_GROUP_BUREAU}],
[3, 'Announcements', '?admin=announcements', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [25, 'Guides Awaiting Approval', '?admin=guides', null, {requiredAccess: U_GROUP_STAFF}],
// [20, 'Global Images & Headers', '?admin=headers', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [21, 'Modelviewer', '?admin=modelviewer', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
[23, 'Out of Date Comments', '?admin=out-of-date', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD}],
[5, 'Screenshots', '?admin=screenshots', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT}],
// [18, 'Upload Image', '?npc=15384#submit-a-screenshot', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR, rel: 'np'}],
[17, 'Videos', '?admin=videos', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_VIDEO}],
[, 'Homepage'],
[13, 'Featured Box', '?admin=home-featuredbox', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Homepage Featured Box'}],
[14, 'Oneliners', '?admin=home-oneliners', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Homepage Oneliners'}],
// [15, 'Skins', '?admin=home-skins', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SALESAGENT, breadcrumb: 'Homepage Skins'}],
[16, 'Titles', '?admin=home-titles', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Homepage Titles'}],
// [, 'Articles'],
// [8, 'List', '?admin=articles', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_EDITOR | U_GROUP_LOCALIZER, breadcrumb: 'List of Articles'}],
// [9, 'Editors\' Lounge', '?admin=editors-lounge', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_EDITOR | U_GROUP_LOCALIZER}],
// [23, 'Related Links', '?admin=related-links', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [, 'News'],
// [10, 'New Post', '?edit=news', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER, breadcrumb: 'News Post'}],
// [11, 'Content Corner', '?admin=content-corner', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER}],
// [12, 'Tags', '?admin=newstag', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_BLOGGER, breadcrumb: 'News Tags'}],
// [24, 'Patch Updates', '?admin=patch-updates', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [26, 'Featured Guides', '?admin=featuredguides', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU, breadcrumb: 'Featured Guides'}],
// [, 'Community'],
// [4, 'Contests', '?admin=contests', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SALESAGENT}],
// [27, 'Top User Contest', '?admin=topuser-contest', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SALESAGENT}],
// [19, 'Forums', '?admin=forums', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [6, 'Profanity Filter', '?admin=profanity', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
// [, 'Other'],
// [7, 'Holiday Gift Guide', '?admin=holidaygift', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}]
];
var mn_dev = [
// [17, 'Cookies', '?admin=cookies', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[21, 'PHP Information', '?admin=phpinfo', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[18, 'Site Configuration', '?admin=siteconfig', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[16, 'Weight Presets', '?admin=weight-presets', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
// [22, 'API Keys', '?admin=apikey', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
// [, 'Cache'],
// [2, 'Create Folders', '?admin=cache-folder', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Create Cache Folders'}],
// [3, 'Expire Range', '?admin=cache-expire', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Expire Cache Range'}],
// [1, 'Manage', '?admin=cache-manage', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Manage Cache'}],
// [20, 'Memcached', '?admin=memcached', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Manage Memcached'}],
// [, 'Database'],
// [8, 'Add Fake Item', '?admin=fakeitem', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [10, 'Add Fake NPC', '?admin=fakenpc', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [19, 'Check Consistency', '?admin=db-check-consistency', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Check Database Consistency'}],
// [4, 'Execute SQL', '?admin=sql', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [9, 'Export Fake Item', '?admin=luaitem', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [26, 'Denormalized Fields Fix', '?admin=denormalized-fix', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [11, 'Minimum & Maximum Values', '?admin=minmax', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [7, 'SQL Find & Replace', '?admin=sql-replace', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [25, 'Switch Active Database', '?admin=active-db', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
// [5, 'Updates', '?admin=db-update', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Database Updates'}],
// [, 'Generators'],
// [12, 'Talent Calculator Icons', '?admin=talentcalc-icons', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}]
];
var mn_localization = [
[1, 'Generate Files', '?admin=locale-export', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Generate Localization Files'}],
[, 'Terms'],
[4, 'Check Integrity', '?admin=locale-integrity', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_LOCALIZER, breadcrumb: 'Check Term Integrity'}],
[2, 'Manage', '?admin=locale-search', null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_LOCALIZER, breadcrumb: 'Manage Terms'}],
[, 'Deprecated'],
[6, 'Create Template', '?admin=locale-template', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV, breadcrumb: 'Create Localization Template'}],
[5, 'Import Old Localized File', '?admin=locale-import', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}],
[7, 'Upload Global Strings', '?admin=locale-upload', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV}]
];
var mn_statistics = [
[1, 'Comments', '?admin=stats&table=comments'],
[2, 'Comment Votes', '?admin=stats&table=commentratings'],
[3, 'Forum Posts', '?admin=stats&table=forumposts'],
[5, 'Registrations', '?admin=stats&table=registrations'],
[4, 'Screenshots', '?admin=stats&table=screenshots'],
[7, 'Uploads', '?admin=stats&table=uploads'],
[6, 'Videos', '?admin=stats&table=videos'],
[8, 'Vists by Registered Users', '?admin=stats&table=visits-by-registered']
];
var mn_users = [
[2, 'Action Log', '?admin=log', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
[3, 'Banned IPs', '?admin=bannedip', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}],
[1, 'Manage', '?admin=finduser', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MODERATOR, breadcrumb: 'Manage Users'}],
[5, 'Roles', '?admin=staff', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MODERATOR}],
[, 'Deprecated'],
[4, 'Get Registration Email', '?admin=getregistrationemail', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU}]
];
var mn_staff = [
[1, 'Content', null, mn_content],
[2, 'Development', null, mn_dev],
// [3, 'Localization', null, mn_localization],
// [7, 'Statistics', null, mn_statistics, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
// [4, 'Users', null, mn_users],
// [5, 'View Reports', '?admin=reports', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR | U_GROUP_MOD | U_GROUP_LOCALIZER | U_GROUP_SCREENSHOT | U_GROUP_VIDEO} ],
[, 'Page'],
[102, 'Validate', 'http://validator.w3.org/check/referer', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV | U_GROUP_TESTER}]];
mn_path.push([4, 'Staff', null, mn_staff]);
$(document).ready(function () {
var footer = $('div.stafffooter');
if (footer.length > 0) {
var totalHeight = $(window).height();
if (footer.offset().top < (totalHeight - 100)) {
var offset = footer.offset();
offset.top = totalHeight - 100;
footer.offset(offset);
}
}
var articleAccess = U_GROUP_EMPLOYEE | U_GROUP_EDITOR | (Locale.getId() != LOCALE_ENUS ? U_GROUP_LOCALIZER : 0);
var urlParams = $WH.g_getGets();
var buff;
var refresh = {};
var subMenu = null;
if (urlParams.refresh != null) {
buff = 'See Cached';
refresh.refresh = null
}
else {
var mCached = {};
var fiCache = {};
buff = 'Refresh';
if (PageTemplate.get('pageName') == 'home') {
refresh.home = '';
mCached.home = '';
fiCache.home = ''
}
refresh.refresh = '';
mCached.refresh = 'memcached';
fiCache.refresh = 'filecache';
subMenu = [
[1, 'Memcached', g_modifyUrl(location.href, mCached), null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}],
[2, 'File cache', g_modifyUrl(location.href, fiCache), null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}]
]
}
mn_staff.push([100, buff, g_modifyUrl(location.href, refresh), subMenu, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_DEV}]);
if (location.href.match(/website-achievement=([0-9]+)(\/.*)?/i)) {
mn_staff.push([, 'Achievement']);
mn_staff.push([200, 'Manage', '?admin=achievements&action=edit&id=' + RegExp.$1, null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV | U_GROUP_BUREAU}])
}
if (location.href.match(/website-achievements(\/.*)?/i)) {
mn_staff.push([, 'Achievements']);
mn_staff.push([200, 'Manage', '?admin=achievements', null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_DEV | U_GROUP_BUREAU}])
}
if (location.href.match(/news=([0-9]+)(\/.*)/i)) {
mn_staff.push([, 'News Post']);
mn_staff.push([200, 'Edit', '?edit=news&id=' + RegExp.$1, null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER}]);
mn_staff.push([203, 'View forum topic', '/forums&topic=' + RegExp.$1, null, {requiredAccess: U_GROUP_EMPLOYEE | U_GROUP_BLOGGER}])
}
if (location.href.match(/user=([a-z0-9]+)/i)) {
mn_staff.push([, 'User']);
mn_staff.push([201, 'Manage', '?admin=manageuser&name=' + RegExp.$1, null, {requiredAccess: U_GROUP_MODERATOR}])
}
if ($WH.isset('g_pageInfo')) {
if (g_pageInfo.type && g_pageInfo.typeId) {
mn_staff.push([, 'DB Entry']);
// mn_staff.push([1001, 'Edit Article', '?edit=article&type=' + g_pageInfo.type + '&typeid=' + g_pageInfo.typeId, null, {requiredAccess: articleAccess}]);
mn_staff.push([1000, 'Manage Screenshots', '?admin=screenshots&type=' + g_pageInfo.type + '&typeid=' + g_pageInfo.typeId, null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_SCREENSHOT}]);
mn_staff.push([1000, 'Manage Videos', '?admin=videos&type=' + g_pageInfo.type + '&typeid=' + g_pageInfo.typeId, null, {requiredAccess: U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_VIDEO}])
}
if (g_pageInfo.articleUrl) {
mn_staff.push([, 'Article']);
mn_staff.push([1002, 'Edit', '?edit=article&' + g_pageInfo.articleUrl, null, {requiredAccess: (g_pageInfo.editAccess ? g_pageInfo.editAccess: articleAccess)}]);
mn_staff.push([1003, 'Options', '?edit=article-options&url=' + g_pageInfo.articleUrl, null, {requiredAccess: articleAccess}])
}
}
Menu.sort(mn_staff)
});
var staff_deleteCacheKey = function (b, key) {
var div = $('#purge-memcache' + b);
var url = '?purgekey=' + key;
var data = {};
if ($.isArray(key)) {
url = '?purgekey';
data.keys = key;
}
$.ajax({
method: 'GET',
url: url,
data: data,
success: function (x) {
if (x == 0) {
this.replaceWith('<span class="q2">Key successfully deleted!</span>');
}
else {
this.replaceWith('<span style="color: red">Key deletion failed: ' + x + '</span>');
}
}.bind(div)
})
};
$(document).ready(function () {
$('#save-blog-form').submit(function () {
var form = $(this);
var blogId = form.find('input[name=blog-id]').val();
form.find('.spinning-circle').show();
form.find('input[type=submit]').attr('disabled', 'disabled').val('Saving..');
form.find('#save-status').html('');
leavePage(1);
$.ajax({
url: '?edit=news&id=' + blogId,
async: true,
cache: false,
data: $(this).serialize(),
type: 'POST',
error: function () {
alert('An error has occured. The news was not saved.')
},
success: function (data) {
var response = eval(data);
if (!response.success) {
alert('An error has occured, the news was not saved: ' + response.message);
return
}
form.find('input[name=blog-id]').val(response.entry);
form.find('#save-status').html('<span class="q2">Your news has been saved!</span> [<a target="_blank" href="' + response.url + '">link</a>]')
},
complete: function () {
form.find('.spinning-circle').hide();
form.find('input[type=submit]').attr('disabled', '').val('Save')
}
});
return false
})
});
var listviewIdList = new function () {
function onShow(container, i, str) {
Lightbox.setSize(950, 590);
if (i) {
container.className = 'modelviewer';
var div = $WH.ce('div');
var pre = $WH.ce('pre');
container.debug = pre;
pre.className = 'code';
$WH.ae(div, pre);
$WH.ae(container, div);
var a = $WH.ce('a');
a.className = 'modelviewer-close';
a.href = 'javascript:;';
a.onclick = Lightbox.hide;
$WH.ae(a, $WH.ce('span'));
$WH.ae(container, a);
clear = $WH.ce('div');
clear.className = 'clear';
$WH.ae(container, clear);
}
var ta = $('<textarea>').css('height', '100px').css('width', '100%').text(str);
$WH.ee(container.debug);
$WH.ae(container.debug, ta[0]);
}
this.show = function (str) {
Lightbox.show('debuginfo', { onShow: onShow }, str);
}
};
var TwigProfiler = new function () {
this.show = function (rows) {
if (!rows) {
rows = [];
}
var len = rows.length;
$('#footer-twig-count').text(len);
var tbl = $('#footer-twig-table');
for (var i = 0; i < len; ++i) {
tbl.append($('<tr/>')
.append($('<td/>', {css: {'white-space': 'nowrap', 'text-align': 'right'}, 'class': 'q2', text: rows[i].action} ))
.append($('<td/>', {css: {'white-space': 'nowrap'}} ).append($('<small/>', {text: rows[i].name} )))
.append($('<td/>', {css: {'white-space': 'nowrap'}} ).append($('<small/>', {text: rows[i].time} )))
);
}
}
};

View File

@@ -1,72 +1,72 @@
Listview.templates.emote = {
sort: [1],
searchable: 1,
filtrable: 1,
columns: [
{
id: 'name',
name: LANG.name,
type: 'text',
align: 'left',
value: 'name',
compute: function(emote, td, tr) {
var wrapper = $WH.ce('div');
var a = $WH.ce('a');
a.style.fontFamily = 'Verdana, sans-serif';
a.href = this.getItemLink(emote);
$WH.ae(a, $WH.ct(emote.name));
$WH.ae(wrapper, a);
$WH.ae(td, wrapper);
},
sortFunc: function(a, b, col) {
return $WH.strcmp(a.name, b.name);
},
getVisibleText: function(emote) {
return emote.name;
}
},
{
id: 'preview',
name: LANG.preview,
type: 'text',
align: 'left',
value: 'name',
compute: function(emote, td, tr) {
var prev = '';
if (emote.preview) {
td.className = 's4';
prev = emote.preview.replace(/%\d?\$?s/g, '<' + LANG.name + '>');
$WH.ae(td, $WH.ct(prev));
}
else {
td.className = 'q0';
td.style.textAlign = 'right';
td.style.Align = 'right';
var
sm = $WH.ce('small'),
i = $WH.ce('i');
sm.style.paddingRight = '8px';
$WH.ae(i, $WH.ct(LANG.lvnodata));
$WH.ae(sm, i);
$WH.ae(td, sm);
}
},
sortFunc: function(a, b, col) {
return $WH.strcmp(a.preview.replace(/%\d?\$?s/g, ''), b.preview.replace(/%\d?\$?s/g, ''));
},
getVisibleText: function(emote) {
return emote.preview.replace(/%\d?\$?s/g, '');
}
}
],
getItemLink: function(emote) {
return '?emote=' + emote.id;
}
}
Listview.templates.emote = {
sort: [1],
searchable: 1,
filtrable: 1,
columns: [
{
id: 'name',
name: LANG.name,
type: 'text',
align: 'left',
value: 'name',
compute: function(emote, td, tr) {
var wrapper = $WH.ce('div');
var a = $WH.ce('a');
a.style.fontFamily = 'Verdana, sans-serif';
a.href = this.getItemLink(emote);
$WH.ae(a, $WH.ct(emote.name));
$WH.ae(wrapper, a);
$WH.ae(td, wrapper);
},
sortFunc: function(a, b, col) {
return $WH.strcmp(a.name, b.name);
},
getVisibleText: function(emote) {
return emote.name;
}
},
{
id: 'preview',
name: LANG.preview,
type: 'text',
align: 'left',
value: 'name',
compute: function(emote, td, tr) {
var prev = '';
if (emote.preview) {
td.className = 's4';
prev = emote.preview.replace(/%\d?\$?s/g, '<' + LANG.name + '>');
$WH.ae(td, $WH.ct(prev));
}
else {
td.className = 'q0';
td.style.textAlign = 'right';
td.style.Align = 'right';
var
sm = $WH.ce('small'),
i = $WH.ce('i');
sm.style.paddingRight = '8px';
$WH.ae(i, $WH.ct(LANG.lvnodata));
$WH.ae(sm, i);
$WH.ae(td, sm);
}
},
sortFunc: function(a, b, col) {
return $WH.strcmp(a.preview.replace(/%\d?\$?s/g, ''), b.preview.replace(/%\d?\$?s/g, ''));
},
getVisibleText: function(emote) {
return emote.preview.replace(/%\d?\$?s/g, '');
}
}
],
getItemLink: function(emote) {
return '?emote=' + emote.id;
}
}

View File

@@ -1,140 +1,140 @@
Listview.templates.enchantment = {
sort: [1],
searchable: 1,
filtrable: 1,
columns: [
{
id: 'name',
name: LANG.name,
type: 'text',
align: 'left',
value: 'name',
compute: function(enchantment, td, tr) {
var
wrapper = $WH.ce('div');
var a = $WH.ce('a');
a.style.fontFamily = 'Verdana, sans-serif';
a.href = this.getItemLink(enchantment);
if (!enchantment.name) {
var i = $WH.ce('i');
i.className = 'q0';
$WH.ae(i, $WH.ct('<' + LANG.pr_header_noname + '>'));
$WH.ae(a, i);
}
else
$WH.ae(a, $WH.ct(enchantment.name));
$WH.ae(wrapper, a);
$WH.ae(td, wrapper);
},
sortFunc: function(a, b, col) {
return $WH.strcmp(a.name, b.name);
},
getVisibleText: function(enchantment) {
return enchantment.name || LANG.pr_header_noname;
}
},
{
id: 'trigger',
name: LANG.types[6][2],
type: 'text',
align: 'left',
value: 'name',
width: '10%',
hidden: 1,
compute: function(enchantment, td, tr) {
if (enchantment.spells) {
var d = $WH.ce('div');
d.style.width = (26 * Object.keys(enchantment.spells).length) + 'px';
d.style.margin = '0 auto';
$.each(enchantment.spells, function (spellId, charges) {
var icon = g_spells.createIcon(spellId, 0, charges);
icon.style.cssFloat = icon.style.styleFloat = 'left';
$WH.ae(d, icon);
});
$WH.ae(td, d);
}
},
getVisibleText: function(enchantment) {
if (!enchantment.spells)
return null; // no spell
var spellId = $(enchantment.spells).first();
if (g_spells[spellId])
return g_spells[spellId]['name_' + Locale.getName()];
return ''; // unk spell
},
sortFunc: function(a, b, col) {
return $WH.strcmp(this.getVisibleText(a), this.getVisibleText(b));
}
},
{
id: 'skill',
name: LANG.skill,
type: 'text',
width: '16%',
getValue: function(enchantment) {
return enchantment.reqskillrank || 0;
},
compute: function(enchantment, td, tr) {
if (enchantment.reqskill != null) {
var div = $WH.ce('div');
div.className = 'small';
// DK is the only class in use
if (enchantment.reqskill == 776) {
var a = $WH.ce('a');
a.className = 'q0';
a.href = '?class=6';
$WH.ae(a, $WH.ct(g_chr_classes[6]));
$WH.ae(div, a);
$WH.ae(div, $WH.ce('br'));
}
var a = $WH.ce('a');
a.className = 'q1';
a.href = '?skill=' + enchantment.reqskill;
$WH.ae(a, $WH.ct(g_spell_skills[enchantment.reqskill]));
$WH.ae(div, a);
if (enchantment.reqskillrank > 0) {
var sp = $WH.ce('span');
sp.className = 'q0';
$WH.ae(sp, $WH.ct(' (' + enchantment.reqskillrank + ')'));
$WH.ae(div, sp);
}
$WH.ae(td, div);
}
},
getVisibleText: function(enchantment) {
var buff = '';
if (g_spell_skills[enchantment.reqskill]) {
buff += g_spell_skills[enchantment.reqskill];
if (enchantment.reqskillrank > 0) {
buff += ' ' + enchantment.reqskillrank;
}
}
return buff;
},
sortFunc: function(a, b, col) {
return $WH.strcmp(g_spell_skills[a.reqskill], g_spell_skills[b.reqskill]) || $WH.strcmp(a.reqskillrank, b.reqskillrank);
}
},
],
getItemLink: function(enchantment) {
return '?enchantment=' + enchantment.id;
}
}
Listview.templates.enchantment = {
sort: [1],
searchable: 1,
filtrable: 1,
columns: [
{
id: 'name',
name: LANG.name,
type: 'text',
align: 'left',
value: 'name',
compute: function(enchantment, td, tr) {
var
wrapper = $WH.ce('div');
var a = $WH.ce('a');
a.style.fontFamily = 'Verdana, sans-serif';
a.href = this.getItemLink(enchantment);
if (!enchantment.name) {
var i = $WH.ce('i');
i.className = 'q0';
$WH.ae(i, $WH.ct('<' + LANG.pr_header_noname + '>'));
$WH.ae(a, i);
}
else
$WH.ae(a, $WH.ct(enchantment.name));
$WH.ae(wrapper, a);
$WH.ae(td, wrapper);
},
sortFunc: function(a, b, col) {
return $WH.strcmp(a.name, b.name);
},
getVisibleText: function(enchantment) {
return enchantment.name || LANG.pr_header_noname;
}
},
{
id: 'trigger',
name: LANG.types[6][2],
type: 'text',
align: 'left',
value: 'name',
width: '10%',
hidden: 1,
compute: function(enchantment, td, tr) {
if (enchantment.spells) {
var d = $WH.ce('div');
d.style.width = (26 * Object.keys(enchantment.spells).length) + 'px';
d.style.margin = '0 auto';
$.each(enchantment.spells, function (spellId, charges) {
var icon = g_spells.createIcon(spellId, 0, charges);
icon.style.cssFloat = icon.style.styleFloat = 'left';
$WH.ae(d, icon);
});
$WH.ae(td, d);
}
},
getVisibleText: function(enchantment) {
if (!enchantment.spells)
return null; // no spell
var spellId = $(enchantment.spells).first();
if (g_spells[spellId])
return g_spells[spellId]['name_' + Locale.getName()];
return ''; // unk spell
},
sortFunc: function(a, b, col) {
return $WH.strcmp(this.getVisibleText(a), this.getVisibleText(b));
}
},
{
id: 'skill',
name: LANG.skill,
type: 'text',
width: '16%',
getValue: function(enchantment) {
return enchantment.reqskillrank || 0;
},
compute: function(enchantment, td, tr) {
if (enchantment.reqskill != null) {
var div = $WH.ce('div');
div.className = 'small';
// DK is the only class in use
if (enchantment.reqskill == 776) {
var a = $WH.ce('a');
a.className = 'q0';
a.href = '?class=6';
$WH.ae(a, $WH.ct(g_chr_classes[6]));
$WH.ae(div, a);
$WH.ae(div, $WH.ce('br'));
}
var a = $WH.ce('a');
a.className = 'q1';
a.href = '?skill=' + enchantment.reqskill;
$WH.ae(a, $WH.ct(g_spell_skills[enchantment.reqskill]));
$WH.ae(div, a);
if (enchantment.reqskillrank > 0) {
var sp = $WH.ce('span');
sp.className = 'q0';
$WH.ae(sp, $WH.ct(' (' + enchantment.reqskillrank + ')'));
$WH.ae(div, sp);
}
$WH.ae(td, div);
}
},
getVisibleText: function(enchantment) {
var buff = '';
if (g_spell_skills[enchantment.reqskill]) {
buff += g_spell_skills[enchantment.reqskill];
if (enchantment.reqskillrank > 0) {
buff += ' ' + enchantment.reqskillrank;
}
}
return buff;
},
sortFunc: function(a, b, col) {
return $WH.strcmp(g_spell_skills[a.reqskill], g_spell_skills[b.reqskill]) || $WH.strcmp(a.reqskillrank, b.reqskillrank);
}
},
],
getItemLink: function(enchantment) {
return '?enchantment=' + enchantment.id;
}
}

View File

@@ -1,17 +1,17 @@
var _ = function(family)
{
family.foodCount = 0;
for (var food in g_pet_foods)
{
if( family.diet & food)
family.foodCount++;
}
family.foodCount = 0;
for (var food in g_pet_foods)
{
if( family.diet & food)
family.foodCount++;
}
family.spellCount = 0;
family.spellCount = 0;
for (var i = 0, len = family.spells.length; i < len; ++i)
{
if (family.spells[i])
family.spellCount++;
}
for (var i = 0, len = family.spells.length; i < len; ++i)
{
if (family.spells[i])
family.spellCount++;
}
};

View File

@@ -1,10 +1,10 @@
<h2><img src="<?php echo STATIC_URL; ?>/images/icons/bubble-big.gif" width="32" height="29" alt="" style="vertical-align:middle;margin-right:8px">Reminder</h2>
Your screenshot will <b class="q10">not</b> be approved if it doesn't correspond to the following guidelines.
<ul>
<li><div>Be sure to turn up your <u><b>graphics settings</b></u> to make sure the shot looks good!</div></li>
<li><div><u><b>Model viewer</b></u> shots are deleted on sight (this also includes character select, typically).</div></li>
<li><div>Don't include the <u><b>onscreen text</b></u> and the <u><b>selection circle</b></u> of a NPC.</div></li>
<li><div>Don't include any <u><b>UI</b></u> in the shot if you can help it.</div></li>
<li><div>Use the screenshot <u><b>cropping tool</b></u> to focus on the item as much as possible and reduce any unnecessary surrounding, as to better show off the item in question when reduced to the thumbnail that will be present on the item's page.</div></li>
</ul>
<h2><img src="<?php echo STATIC_URL; ?>/images/icons/bubble-big.gif" width="32" height="29" alt="" style="vertical-align:middle;margin-right:8px">Reminder</h2>
Your screenshot will <b class="q10">not</b> be approved if it doesn't correspond to the following guidelines.
<ul>
<li><div>Be sure to turn up your <u><b>graphics settings</b></u> to make sure the shot looks good!</div></li>
<li><div><u><b>Model viewer</b></u> shots are deleted on sight (this also includes character select, typically).</div></li>
<li><div>Don't include the <u><b>onscreen text</b></u> and the <u><b>selection circle</b></u> of a NPC.</div></li>
<li><div>Don't include any <u><b>UI</b></u> in the shot if you can help it.</div></li>
<li><div>Use the screenshot <u><b>cropping tool</b></u> to focus on the item as much as possible and reduce any unnecessary surrounding, as to better show off the item in question when reduced to the thumbnail that will be present on the item's page.</div></li>
</ul>

View File

@@ -1,10 +1,10 @@
<h2><img src="<?php echo STATIC_URL; ?>/images/icons/bubble-big.gif" width="32" height="29" alt="" style="vertical-align:middle;margin-right:8px">Hinweis</h2>
Euer Screenshot wird <b class="q10">nicht</b> zugelassen werden, wenn er nicht unseren Richtlinien entspricht.
<ul>
<li><div>Achtet darauf die Qualität Eurer <u><b>Video Einstellungen</b></u> zu erhöhen, damit Euer Bild gut aussieht!</div></li>
<li><div>Bilder des <u><b>Modelviewers</b></u> werden sofort gelöscht (das beinhaltet in der Regel auch Bilder der Charakterauswahl).</div></li>
<li><div>Vermeidet <u><b>Bildschirmtext</b></u> und die <u><b>Zielmarkierung</b></u> an NPCs.</div></li>
<li><div>Bezieht das <u><b>Interface</b></u> nicht ins Bild mit ein, wenn Ihr es vermeiden könnt.</div></li>
<li><div>Benutzt das <u><b>Zuschneidewerkzeug</b></u> um den Fokus so weit wie möglich auf das Objekt zu legen und unnötigen Rand zu reduzieren. Dies hilft das Objekt besser in der Vorschau zu erkennen, welche auf der entsprechenden Seite angezeigt wird.</div></li>
</ul>
<h2><img src="<?php echo STATIC_URL; ?>/images/icons/bubble-big.gif" width="32" height="29" alt="" style="vertical-align:middle;margin-right:8px">Hinweis</h2>
Euer Screenshot wird <b class="q10">nicht</b> zugelassen werden, wenn er nicht unseren Richtlinien entspricht.
<ul>
<li><div>Achtet darauf die Qualität Eurer <u><b>Video Einstellungen</b></u> zu erhöhen, damit Euer Bild gut aussieht!</div></li>
<li><div>Bilder des <u><b>Modelviewers</b></u> werden sofort gelöscht (das beinhaltet in der Regel auch Bilder der Charakterauswahl).</div></li>
<li><div>Vermeidet <u><b>Bildschirmtext</b></u> und die <u><b>Zielmarkierung</b></u> an NPCs.</div></li>
<li><div>Bezieht das <u><b>Interface</b></u> nicht ins Bild mit ein, wenn Ihr es vermeiden könnt.</div></li>
<li><div>Benutzt das <u><b>Zuschneidewerkzeug</b></u> um den Fokus so weit wie möglich auf das Objekt zu legen und unnötigen Rand zu reduzieren. Dies hilft das Objekt besser in der Vorschau zu erkennen, welche auf der entsprechenden Seite angezeigt wird.</div></li>
</ul>

View File

@@ -1,280 +1,280 @@
<?php $this->brick('header'); ?>
<script type="text/javascript">
function createStatusIcon(errTxt)
{
function fadeout()
{
$(this).animate({ opacity: '0.0' }, 250, null, function() {
$WH.de(this);
$WH.Tooltip.hide()
});
}
var a = $WH.ce('a');
a.style.opacity = 0;
a.className = errTxt ? 'icon-report' : 'icon-tick';
g_addTooltip(a, errTxt || 'success', 'q');
a.onclick = fadeout.bind(a);
setTimeout(function () { $(a).animate({ opacity: '1.0' }, 250); }, 50);
setTimeout(fadeout.bind(a), 10000);
return a;
}
function cfg_add(el)
{
_self = el.parentNode.parentNode;
var tr = $WH.ce('tr');
tr.style.position = 'relative';
var td = $WH.ce('td'),
key = $WH.ce('input');
key.type = 'text';
key.name = 'key';
$WH.ae(td, key);
$WH.ae(tr, td);
var td = $WH.ce('td'),
val = $WH.ce('input');
val.type = 'text';
val.name = 'value';
$WH.ae(td, val);
$WH.ae(tr, td);
var td = $WH.ce('td'),
aCancel = $WH.ce('a'),
aSubmit = $WH.ce('a'),
status = $WH.ce('span');
aSubmit.className = 'icon-save tip';
g_addTooltip(aSubmit, 'Submit Setting', 'q');
aCancel.className = 'icon-delete tip';
g_addTooltip(aCancel, 'Cancel', 'q');
aSubmit.onclick = cfg_new.bind(aSubmit, key, val);
aCancel.onclick = function () {
$WH.Tooltip.hide();
$WH.de(this.parentNode.parentNode);
};
status.className = 'status';
$WH.ae(td, aSubmit);
$WH.ae(td, $WH.ct('|'));
$WH.ae(td, aCancel);
$WH.ae(td, status);
$WH.ae(tr, td);
_self.parentNode.insertBefore(tr, _self);
key.focus();
}
function cfg_new(elKey, elVal)
{
var
_td = this.parentNode,
_row = this.parentNode.parentNode,
_status = $(_td).find('.status')[0];
// already performing action
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
return;
else if (_status.lastChild && _status.lastChild.tagName == 'A')
$WH.ee(_status);
if (!elKey.value || !elVal.value)
{
$WH.ae(_status, createStatusIcon('key or value are empty'));
return;
}
var
key = elKey.value.toLowerCase().trim(),
value = elVal.value.trim();
$(_status).append(CreateAjaxLoader());
new Ajax('?admin=siteconfig&action=add&key=' + key + '&val=' + value, {
method: 'get',
onSuccess: function(xhr) {
$WH.ee(_status);
if (!xhr.responseText) {
$WH.ee(_row);
$(_row).append($('<td>' + key + '</td>')).append($('<td><input id="' + key + '" type="text" name="' + key + '" value="' + value + '" /></td>'));
var
td = $WH.ce('td'),
a = $WH.ce('a'),
sp = $WH.ce('span');
g_addTooltip(a, 'Save Changes', 'q');
a.onclick = cfg_submit.bind(a, key);
a.className = 'icon-save tip';
$WH.ae(td, a);
a = $WH.ce('a');
a.className = 'icon-refresh tip disabled';
$WH.ae(td, $WH.ct('|'));
$WH.ae(td, a);
a = $WH.ce('a');
g_addTooltip(a, 'Remove Setting', 'q');
a.onclick = cfg_remove.bind(a, key);
a.className = 'icon-delete tip';
$WH.ae(td, $WH.ct('|'));
$WH.ae(td, a);
sp.className = 'status';
$WH.ae(sp, createStatusIcon());
$WH.ae(td, sp);
$WH.ae(_row, td);
}
else {
$WH.ae(_status, createStatusIcon(xhr.responseText));
}
}
});
}
function cfg_submit(id)
{
var
node = $WH.ge(id),
_td = this.parentNode,
_status = $(_td).find('.status')[0];
if (!node)
return;
var value = 0;
// already performing action
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
return;
else if (_status.lastChild && _status.lastChild.tagName == 'A')
$WH.ee(_status);
if (node.tagName == 'DIV')
{
// bitmask
$(node).find('input[type="checkbox"]').each(function(idx, opt) {
if (opt.checked)
value |= (1 << opt.value);
});
// boolean
$(node).find('input[type="radio"]').each(function(idx, opt) {
if (opt.checked)
value = opt.value;
});
}
else if (node.tagName == 'SELECT') // opt-list
{
$(node).find('option').each(function(idx, opt) {
if (opt.selected)
value = opt.value;
});
}
else if (node.tagName == 'INPUT') // string or numeric
{
if (node.value && node.value.search(/[^\d\s\/\*\-\+\.]/i) == -1)
node.value = eval(node.value);
value = node.value;
}
value = value.toString().trim();
if (!value.length && (node.tagName != 'INPUT' || node.type != 'text'))
{
$WH.ae(_status, createStatusIcon('value is empty'));
return;
}
$(_status).append(CreateAjaxLoader());
new Ajax('?admin=siteconfig&action=update&key=' + id + '&val=' + value, {
method: 'get',
onSuccess: function(xhr) {
$WH.ee(_status);
$WH.ae(_status, createStatusIcon(xhr.responseText));
}
});
}
function cfg_default(id, val)
{
var node = $WH.ge(id);
if (!node)
return;
if (node.tagName == 'DIV')
{
// bitmask
$(node).find('input[type="checkbox"]').each(function(idx, opt) { opt.checked = !!(val & (1 << opt.value)); });
// boolean
$(node).find('input[type="radio"]').each(function(idx, opt) { opt.checked = !!opt.value == !!val; });
}
else if (node.tagName == 'SELECT') // opt-list
$(node).find('option').each(function(idx, opt) { opt.selected = opt.value == val; });
else if (node.tagName == 'INPUT') // string or numeric
node.value = node.type == 'text' ? val : eval(val);
}
function cfg_remove(id)
{
var
_td = this.parentNode,
_status = $(_td).find('.status')[0];
// already performing action
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
return;
else if (_status.lastChild && _status.lastChild.tagName == 'A')
$WH.ee(_status);
if (!confirm('Confirm remove'))
return;
$(_status).append(CreateAjaxLoader());
new Ajax('?admin=siteconfig&action=remove&key=' + id, {
method: 'get',
onSuccess: function(xhr) {
if (!xhr.responseText)
$WH.de(_td.parentNode);
else {
$WH.ee(_status);
$WH.ae(_status, createStatusIcon(xhr.responseText));
}
}
});
}
</script>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate');
$this->brick('lvTabs');
?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>
<?php $this->brick('header'); ?>
<script type="text/javascript">
function createStatusIcon(errTxt)
{
function fadeout()
{
$(this).animate({ opacity: '0.0' }, 250, null, function() {
$WH.de(this);
$WH.Tooltip.hide()
});
}
var a = $WH.ce('a');
a.style.opacity = 0;
a.className = errTxt ? 'icon-report' : 'icon-tick';
g_addTooltip(a, errTxt || 'success', 'q');
a.onclick = fadeout.bind(a);
setTimeout(function () { $(a).animate({ opacity: '1.0' }, 250); }, 50);
setTimeout(fadeout.bind(a), 10000);
return a;
}
function cfg_add(el)
{
_self = el.parentNode.parentNode;
var tr = $WH.ce('tr');
tr.style.position = 'relative';
var td = $WH.ce('td'),
key = $WH.ce('input');
key.type = 'text';
key.name = 'key';
$WH.ae(td, key);
$WH.ae(tr, td);
var td = $WH.ce('td'),
val = $WH.ce('input');
val.type = 'text';
val.name = 'value';
$WH.ae(td, val);
$WH.ae(tr, td);
var td = $WH.ce('td'),
aCancel = $WH.ce('a'),
aSubmit = $WH.ce('a'),
status = $WH.ce('span');
aSubmit.className = 'icon-save tip';
g_addTooltip(aSubmit, 'Submit Setting', 'q');
aCancel.className = 'icon-delete tip';
g_addTooltip(aCancel, 'Cancel', 'q');
aSubmit.onclick = cfg_new.bind(aSubmit, key, val);
aCancel.onclick = function () {
$WH.Tooltip.hide();
$WH.de(this.parentNode.parentNode);
};
status.className = 'status';
$WH.ae(td, aSubmit);
$WH.ae(td, $WH.ct('|'));
$WH.ae(td, aCancel);
$WH.ae(td, status);
$WH.ae(tr, td);
_self.parentNode.insertBefore(tr, _self);
key.focus();
}
function cfg_new(elKey, elVal)
{
var
_td = this.parentNode,
_row = this.parentNode.parentNode,
_status = $(_td).find('.status')[0];
// already performing action
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
return;
else if (_status.lastChild && _status.lastChild.tagName == 'A')
$WH.ee(_status);
if (!elKey.value || !elVal.value)
{
$WH.ae(_status, createStatusIcon('key or value are empty'));
return;
}
var
key = elKey.value.toLowerCase().trim(),
value = elVal.value.trim();
$(_status).append(CreateAjaxLoader());
new Ajax('?admin=siteconfig&action=add&key=' + key + '&val=' + value, {
method: 'get',
onSuccess: function(xhr) {
$WH.ee(_status);
if (!xhr.responseText) {
$WH.ee(_row);
$(_row).append($('<td>' + key + '</td>')).append($('<td><input id="' + key + '" type="text" name="' + key + '" value="' + value + '" /></td>'));
var
td = $WH.ce('td'),
a = $WH.ce('a'),
sp = $WH.ce('span');
g_addTooltip(a, 'Save Changes', 'q');
a.onclick = cfg_submit.bind(a, key);
a.className = 'icon-save tip';
$WH.ae(td, a);
a = $WH.ce('a');
a.className = 'icon-refresh tip disabled';
$WH.ae(td, $WH.ct('|'));
$WH.ae(td, a);
a = $WH.ce('a');
g_addTooltip(a, 'Remove Setting', 'q');
a.onclick = cfg_remove.bind(a, key);
a.className = 'icon-delete tip';
$WH.ae(td, $WH.ct('|'));
$WH.ae(td, a);
sp.className = 'status';
$WH.ae(sp, createStatusIcon());
$WH.ae(td, sp);
$WH.ae(_row, td);
}
else {
$WH.ae(_status, createStatusIcon(xhr.responseText));
}
}
});
}
function cfg_submit(id)
{
var
node = $WH.ge(id),
_td = this.parentNode,
_status = $(_td).find('.status')[0];
if (!node)
return;
var value = 0;
// already performing action
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
return;
else if (_status.lastChild && _status.lastChild.tagName == 'A')
$WH.ee(_status);
if (node.tagName == 'DIV')
{
// bitmask
$(node).find('input[type="checkbox"]').each(function(idx, opt) {
if (opt.checked)
value |= (1 << opt.value);
});
// boolean
$(node).find('input[type="radio"]').each(function(idx, opt) {
if (opt.checked)
value = opt.value;
});
}
else if (node.tagName == 'SELECT') // opt-list
{
$(node).find('option').each(function(idx, opt) {
if (opt.selected)
value = opt.value;
});
}
else if (node.tagName == 'INPUT') // string or numeric
{
if (node.value && node.value.search(/[^\d\s\/\*\-\+\.]/i) == -1)
node.value = eval(node.value);
value = node.value;
}
value = value.toString().trim();
if (!value.length && (node.tagName != 'INPUT' || node.type != 'text'))
{
$WH.ae(_status, createStatusIcon('value is empty'));
return;
}
$(_status).append(CreateAjaxLoader());
new Ajax('?admin=siteconfig&action=update&key=' + id + '&val=' + value, {
method: 'get',
onSuccess: function(xhr) {
$WH.ee(_status);
$WH.ae(_status, createStatusIcon(xhr.responseText));
}
});
}
function cfg_default(id, val)
{
var node = $WH.ge(id);
if (!node)
return;
if (node.tagName == 'DIV')
{
// bitmask
$(node).find('input[type="checkbox"]').each(function(idx, opt) { opt.checked = !!(val & (1 << opt.value)); });
// boolean
$(node).find('input[type="radio"]').each(function(idx, opt) { opt.checked = !!opt.value == !!val; });
}
else if (node.tagName == 'SELECT') // opt-list
$(node).find('option').each(function(idx, opt) { opt.selected = opt.value == val; });
else if (node.tagName == 'INPUT') // string or numeric
node.value = node.type == 'text' ? val : eval(val);
}
function cfg_remove(id)
{
var
_td = this.parentNode,
_status = $(_td).find('.status')[0];
// already performing action
if (_status.lastChild && _status.lastChild.tagName == 'IMG')
return;
else if (_status.lastChild && _status.lastChild.tagName == 'A')
$WH.ee(_status);
if (!confirm('Confirm remove'))
return;
$(_status).append(CreateAjaxLoader());
new Ajax('?admin=siteconfig&action=remove&key=' + id, {
method: 'get',
onSuccess: function(xhr) {
if (!xhr.responseText)
$WH.de(_td.parentNode);
else {
$WH.ee(_status);
$WH.ae(_status, createStatusIcon(xhr.responseText));
}
}
});
}
</script>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate');
$this->brick('lvTabs');
?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>

File diff suppressed because it is too large Load Diff

View File

@@ -1,118 +1,118 @@
<?php $this->brick('header'); ?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate');
$this->brick('infobox');
?>
<div class="text">
<?php $this->brick('redButtons'); ?>
<h1 class="h1-icon"><?php echo $this->name; ?></h1>
<div class="clear"></div>
<?php $this->brick('article'); ?>
<h3><?php echo Lang::enchantment('details'); ?></h3>
<table class="grid" id="spelldetails">
<colgroup>
<col width="8%" />
<col width="42%" />
<col width="50%" />
</colgroup>
<?php
if (!empty($this->activateCondition)):
?>
<tr>
<th><?php echo Lang::enchantment('activation'); ?></th>
<td colspan="2"><?php echo $this->activateCondition; ?></td>
</tr>
<?php
endif;
foreach ($this->effects as $i => $e):
?>
<tr>
<th><?php echo Lang::spell('_effect').' #'.$i; ?></th>
<td colspan="3" style="line-height: 17px">
<?php
echo ' '.$e['name'].(!empty($e['tip']) ? Lang::main('colon').'(<span class="tip" id="efftip-'.$i.'"></span>)' : '').'<small>';
if (isset($e['value'])):
echo '<br>'.Lang::spell('_value').Lang::main('colon').$e['value'];
endif;
if (!empty($e['proc'])):
echo '<br>';
if ($e['proc'] < 0):
echo sprintf(Lang::spell('ppm'), Lang::nf(-$e['proc'], 1));
elseif ($e['proc'] < 100.0):
echo Lang::spell('procChance').Lang::main('colon').$e['proc'].'%';
endif;
endif;
echo "</small>\n";
if (!empty($e['tip'])):
?>
<script type="text/javascript">
<?php
echo " \$WH.ae(\$WH.ge('efftip-".$i."'), \$WH.ct(LANG.traits['".$e['tip'][1]."'][0]));\n";
if (User::isInGroup(U_GROUP_EMPLOYEE)):
echo " g_addTooltip(\$WH.ge('efftip-".$i."'), 'Object: ".$e['tip'][0]."', 'q');\n";
endif;
?>
</script>
<?php
endif;
if (isset($e['icon'])):
?>
<table class="icontab">
<tr>
<th id="icontab-icon<?php echo $i; ?>"></th>
<?php
echo ' <td>'.(strpos($e['icon']['name'], '#') ? $e['icon']['name'] : sprintf('<a href="?spell=%d">%s</a>', $e['icon']['id'], $e['icon']['name']))."</td>\n";
?>
<th></th><td></td>
</tr>
</table>
<script type="text/javascript">
<?php echo '$WH.ge(\'icontab-icon'.$i.'\').appendChild(g_spells.createIcon('.$e['icon']['id'].', 1, '.$e['icon']['count']."));\n"; ?>
</script>
<?php
endif;
?>
</td>
</tr>
<?php
endforeach;
?>
</table>
<h2 class="clear"><?php echo Lang::main('related'); ?></h2>
</div>
<?php
$this->brick('lvTabs', ['relTabs' => true]);
$this->brick('contribute');
?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>
<?php $this->brick('header'); ?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate');
$this->brick('infobox');
?>
<div class="text">
<?php $this->brick('redButtons'); ?>
<h1 class="h1-icon"><?php echo $this->name; ?></h1>
<div class="clear"></div>
<?php $this->brick('article'); ?>
<h3><?php echo Lang::enchantment('details'); ?></h3>
<table class="grid" id="spelldetails">
<colgroup>
<col width="8%" />
<col width="42%" />
<col width="50%" />
</colgroup>
<?php
if (!empty($this->activateCondition)):
?>
<tr>
<th><?php echo Lang::enchantment('activation'); ?></th>
<td colspan="2"><?php echo $this->activateCondition; ?></td>
</tr>
<?php
endif;
foreach ($this->effects as $i => $e):
?>
<tr>
<th><?php echo Lang::spell('_effect').' #'.$i; ?></th>
<td colspan="3" style="line-height: 17px">
<?php
echo ' '.$e['name'].(!empty($e['tip']) ? Lang::main('colon').'(<span class="tip" id="efftip-'.$i.'"></span>)' : '').'<small>';
if (isset($e['value'])):
echo '<br>'.Lang::spell('_value').Lang::main('colon').$e['value'];
endif;
if (!empty($e['proc'])):
echo '<br>';
if ($e['proc'] < 0):
echo sprintf(Lang::spell('ppm'), Lang::nf(-$e['proc'], 1));
elseif ($e['proc'] < 100.0):
echo Lang::spell('procChance').Lang::main('colon').$e['proc'].'%';
endif;
endif;
echo "</small>\n";
if (!empty($e['tip'])):
?>
<script type="text/javascript">
<?php
echo " \$WH.ae(\$WH.ge('efftip-".$i."'), \$WH.ct(LANG.traits['".$e['tip'][1]."'][0]));\n";
if (User::isInGroup(U_GROUP_EMPLOYEE)):
echo " g_addTooltip(\$WH.ge('efftip-".$i."'), 'Object: ".$e['tip'][0]."', 'q');\n";
endif;
?>
</script>
<?php
endif;
if (isset($e['icon'])):
?>
<table class="icontab">
<tr>
<th id="icontab-icon<?php echo $i; ?>"></th>
<?php
echo ' <td>'.(strpos($e['icon']['name'], '#') ? $e['icon']['name'] : sprintf('<a href="?spell=%d">%s</a>', $e['icon']['id'], $e['icon']['name']))."</td>\n";
?>
<th></th><td></td>
</tr>
</table>
<script type="text/javascript">
<?php echo '$WH.ge(\'icontab-icon'.$i.'\').appendChild(g_spells.createIcon('.$e['icon']['id'].', 1, '.$e['icon']['count']."));\n"; ?>
</script>
<?php
endif;
?>
</td>
</tr>
<?php
endforeach;
?>
</table>
<h2 class="clear"><?php echo Lang::main('related'); ?></h2>
</div>
<?php
$this->brick('lvTabs', ['relTabs' => true]);
$this->brick('contribute');
?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>

View File

@@ -1,75 +1,75 @@
<?php
$this->brick('header');
$f = $this->filter; // shorthand
?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate', ['fi' => empty($f['query']) ? null : ['query' => $f['query'], 'menuItem' => 101]]);
?>
<div id="fi" style="display: <?php echo empty($f['query']) ? 'none' : 'block' ?>;">
<form action="?enchantments&filter" method="post" name="fi" onsubmit="return fi_submit(this)" onreset="return fi_reset(this)">
<div class="rightpanel">
<div style="float: left"><?php echo Util::ucFirst(Lang::game('type')).Lang::main('colon'); ?></div>
<small><a href="javascript:;" onclick="document.forms['fi'].elements['ty[]'].selectedIndex = -1; return false" onmousedown="return false"><?php echo Lang::main('clear'); ?></a></small>
<div class="clear"></div>
<select name="ty[]" size="8" multiple="multiple" class="rightselect">
<?php
foreach (Lang::enchantment('types') as $i => $str):
if ($str):
echo ' <option value="'.$i.'"'.(isset($f['ty']) && in_array($i, (array)$f['ty']) ? ' selected' : null).' >'.$str."</option>\n";
endif;
endforeach;
?>
</select>
</div>
<table>
<tr>
<td><?php echo Util::ucFirst(Lang::main('name')).Lang::main('colon'); ?></td>
<td colspan="2">
<table><tr>
<td>&nbsp;<input type="text" name="na" size="30" <?php echo isset($f['na']) ? 'value="'.Util::htmlEscape($f['na']).'" ' : null; ?>/></td>
</tr></table>
</td>
</tr><tr>
</table>
<div id="fi_criteria" class="padded criteria"><div></div></div><div><a href="javascript:;" id="fi_addcriteria" onclick="fi_addCriterion(this); return false"><?php echo Lang::main('addFilter'); ?></a></div>
<div class="padded2">
<?php echo Lang::main('match').Lang::main('colon'); ?><input type="radio" name="ma" value="" id="ma-0" <?php echo !isset($f['ma']) ? 'checked="checked" ' : null ?>/><label for="ma-0"><?php echo Lang::main('allFilter'); ?></label><input type="radio" name="ma" value="1" id="ma-1" <?php echo isset($f['ma']) ? 'checked="checked" ' : null ?> /><label for="ma-1"><?php echo Lang::main('oneFilter'); ?></label>
</div>
<div class="clear"></div>
<div class="padded">
<input type="submit" value="<?php echo Lang::main('applyFilter'); ?>" />
<input type="reset" value="<?php echo Lang::main('resetForm'); ?>" />
</div>
</form>
<div class="pad"></div>
</div>
<script type="text/javascript">//<![CDATA[
fi_init('enchantments');
<?php
foreach ($f['fi'] as $str):
echo ' '.$str."\n";
endforeach;
?>
//]]></script>
<?php $this->brick('lvTabs'); ?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>
<?php
$this->brick('header');
$f = $this->filter; // shorthand
?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate', ['fi' => empty($f['query']) ? null : ['query' => $f['query'], 'menuItem' => 101]]);
?>
<div id="fi" style="display: <?php echo empty($f['query']) ? 'none' : 'block' ?>;">
<form action="?enchantments&filter" method="post" name="fi" onsubmit="return fi_submit(this)" onreset="return fi_reset(this)">
<div class="rightpanel">
<div style="float: left"><?php echo Util::ucFirst(Lang::game('type')).Lang::main('colon'); ?></div>
<small><a href="javascript:;" onclick="document.forms['fi'].elements['ty[]'].selectedIndex = -1; return false" onmousedown="return false"><?php echo Lang::main('clear'); ?></a></small>
<div class="clear"></div>
<select name="ty[]" size="8" multiple="multiple" class="rightselect">
<?php
foreach (Lang::enchantment('types') as $i => $str):
if ($str):
echo ' <option value="'.$i.'"'.(isset($f['ty']) && in_array($i, (array)$f['ty']) ? ' selected' : null).' >'.$str."</option>\n";
endif;
endforeach;
?>
</select>
</div>
<table>
<tr>
<td><?php echo Util::ucFirst(Lang::main('name')).Lang::main('colon'); ?></td>
<td colspan="2">
<table><tr>
<td>&nbsp;<input type="text" name="na" size="30" <?php echo isset($f['na']) ? 'value="'.Util::htmlEscape($f['na']).'" ' : null; ?>/></td>
</tr></table>
</td>
</tr><tr>
</table>
<div id="fi_criteria" class="padded criteria"><div></div></div><div><a href="javascript:;" id="fi_addcriteria" onclick="fi_addCriterion(this); return false"><?php echo Lang::main('addFilter'); ?></a></div>
<div class="padded2">
<?php echo Lang::main('match').Lang::main('colon'); ?><input type="radio" name="ma" value="" id="ma-0" <?php echo !isset($f['ma']) ? 'checked="checked" ' : null ?>/><label for="ma-0"><?php echo Lang::main('allFilter'); ?></label><input type="radio" name="ma" value="1" id="ma-1" <?php echo isset($f['ma']) ? 'checked="checked" ' : null ?> /><label for="ma-1"><?php echo Lang::main('oneFilter'); ?></label>
</div>
<div class="clear"></div>
<div class="padded">
<input type="submit" value="<?php echo Lang::main('applyFilter'); ?>" />
<input type="reset" value="<?php echo Lang::main('resetForm'); ?>" />
</div>
</form>
<div class="pad"></div>
</div>
<script type="text/javascript">//<![CDATA[
fi_init('enchantments');
<?php
foreach ($f['fi'] as $str):
echo ' '.$str."\n";
endforeach;
?>
//]]></script>
<?php $this->brick('lvTabs'); ?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>

View File

@@ -9,10 +9,10 @@
{/foreach}
{/if}
<script type="text/javascript">
g_initPath({$page.path}, {if empty($filter.query)} 0 {else} 1 {/if}); _// activeTab: 1, breadcrumb: [1,5,2,'eu','blackout','dragonblight']});
<script type="text/javascript">
g_initPath({$page.path}, {if empty($filter.query)} 0 {else} 1 {/if}); _// activeTab: 1, breadcrumb: [1,5,2,'eu','blackout','dragonblight']});
{if isset($filter.query)}Menu.append(mn_database[1], '&filter={$filter.query|escape:'quotes'}'); // todo: menu order varies per locale{/if}
</script>
</script>
<div id="fi">
<form action="/web/20120205222627/http://www.wowhead.com/filter=guilds" method="post" name="fi" onsubmit="return fi_submit(this)" onreset="return fi_reset(this)">

View File

@@ -1,46 +1,46 @@
<?php $this->brick('header'); ?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate');
$this->brick('infobox');
?>
<script type="text/javascript">var g_pageInfo = { username: '<?php echo Util::jsEscape($this->user['displayName']); ?>' }</script>
<div class="text">
<div id="h1-icon-generic" class="h1-icon"></div>
<script type="text/javascript">
$WH.ge('h1-icon-generic').appendChild(Icon.createUser(<?php echo (is_numeric($this->user['avatar']) ? 2 : 1).', \''.($this->user['avatar'] ?: 'inv_misc_questionmark').'\''?>, 1, null, <?php echo User::isInGroup(U_GROUP_PREMIUM) ? 0 : 2; ?>, false, Icon.getPrivilegeBorder(<?php echo $this->user['sumRep']; ?>)));
</script>
<h1 class="h1-icon"><?php echo $this->name; ?></h1>
</div>
<h3 class="first"><?php echo Lang::user('publicDesc'); ?></h3>
<div id="description" class="left"><?php # must follow directly, no whitespaces allowed
if (!empty($this->user['description'])):
?>
<div id="description-generic"></div>
<script type="text/javascript">//<![CDATA[
Markup.printHtml('<?php echo $this->user['description']; ?>', "description-generic", { allow: Markup.CLASS_USER, roles: "<?php echo $this->user['userGroups']; ?>" });
//]]></script>
<?php
endif;
?></div>
<script type="text/javascript">us_addDescription()</script>
<div id="roster-status" class="profiler-message clear" style="display: none"></div>
<?php $this->brick('lvTabs', ['relTabs' => true]); ?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>
<?php $this->brick('header'); ?>
<div class="main" id="main">
<div class="main-precontents" id="main-precontents"></div>
<div class="main-contents" id="main-contents">
<?php
$this->brick('announcement');
$this->brick('pageTemplate');
$this->brick('infobox');
?>
<script type="text/javascript">var g_pageInfo = { username: '<?php echo Util::jsEscape($this->user['displayName']); ?>' }</script>
<div class="text">
<div id="h1-icon-generic" class="h1-icon"></div>
<script type="text/javascript">
$WH.ge('h1-icon-generic').appendChild(Icon.createUser(<?php echo (is_numeric($this->user['avatar']) ? 2 : 1).', \''.($this->user['avatar'] ?: 'inv_misc_questionmark').'\''?>, 1, null, <?php echo User::isInGroup(U_GROUP_PREMIUM) ? 0 : 2; ?>, false, Icon.getPrivilegeBorder(<?php echo $this->user['sumRep']; ?>)));
</script>
<h1 class="h1-icon"><?php echo $this->name; ?></h1>
</div>
<h3 class="first"><?php echo Lang::user('publicDesc'); ?></h3>
<div id="description" class="left"><?php # must follow directly, no whitespaces allowed
if (!empty($this->user['description'])):
?>
<div id="description-generic"></div>
<script type="text/javascript">//<![CDATA[
Markup.printHtml('<?php echo $this->user['description']; ?>', "description-generic", { allow: Markup.CLASS_USER, roles: "<?php echo $this->user['userGroups']; ?>" });
//]]></script>
<?php
endif;
?></div>
<script type="text/javascript">us_addDescription()</script>
<div id="roster-status" class="profiler-message clear" style="display: none"></div>
<?php $this->brick('lvTabs', ['relTabs' => true]); ?>
<div class="clear"></div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>