* move related functions to separate class
 * implement out of date comment handling shorthand
 * implement admin interface to work with reports
   - listing based on user group
   - assign to self / unassign from self
   - close with reason
   - comment functionality
   - reward reputation to creator based on resolution
This commit is contained in:
Sarjuuk
2022-03-28 17:47:55 +02:00
parent 6db77ed4f2
commit 8425eeb685
10 changed files with 506 additions and 168 deletions

View File

@@ -5,7 +5,7 @@ if (!defined('AOWOW_REVISION'))
class AjaxAdmin extends AjaxHandler
{
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override', 'guide'];
protected $validParams = ['screenshots', 'siteconfig', 'weight-presets', 'spawn-override', 'guide', 'comment'];
protected $_get = array(
'action' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW ],
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkIdListUnsigned'],
@@ -89,6 +89,13 @@ class AjaxAdmin extends AjaxHandler
$this->handler = 'guideManage';
}
else if ($this->params[0] == 'comment')
{
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD))
return;
$this->handler = 'commentOutOfDate';
}
}
// get all => null (optional)
@@ -526,6 +533,28 @@ class AjaxAdmin extends AjaxHandler
return '-1';
}
protected function commentOutOfDate() : string
{
$ok = false;
switch ($this->_post['status'])
{
case 0: // up to date
if ($ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` & ~?d WHERE `id` = ?d', CC_FLAG_OUTDATED, $this->_post['id']))
if ($rep = new Report(Report::MODE_COMMENT, Report::CO_OUT_OF_DATE, $this->_post['id']))
$rep->close(Report::STATUS_CLOSED_WONTFIX);
break;
case 1: // outdated, mark as deleted and clear other flags (sticky + outdated)
if ($ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = ?d, `deleteUserId` = ?d, `deleteDate` = ?d WHERE `id` = ?d', CC_FLAG_DELETED, User::$id, time(), $this->_post['id']))
if ($rep = new Report(Report::MODE_COMMENT, Report::CO_OUT_OF_DATE, $this->_post['id']))
$rep->close(Report::STATUS_CLOSED_SOLVED);
break;
default:
trigger_error('AjaxHandler::comentOutOfDate - called with invalid status');
}
return $ok ? '1' : '0';
}
/***************************/
/* additional input filter */

View File

@@ -177,7 +177,7 @@ class AjaxComment extends AjaxHandler
}
// 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}',
$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'],
@@ -187,13 +187,14 @@ class AjaxComment extends AjaxHandler
// 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',
$coInfo = DB::Aowow()->select('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` IN (?a) GROUP BY b.`type`, b.`typeId`',
CC_FLAG_DELETED,
$this->_post['id']
);
if (!$coInfo['hasMore'] && ($tbl = Type::getClassAttrib($coInfo['type'], 'dataTable')))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags & ~?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
foreach ($coInfo as $co)
if (!$co['hasMore'] && ($tbl = Type::getClassAttrib($co['type'], 'dataTable')))
DB::Aowow()->query('UPDATE ?# SET `cuFlags` = `cuFlags` & ~?d WHERE `id` = ?d', $tbl, CUSTOM_HAS_COMMENT, $co['typeId']);
}
else
trigger_error('AjaxComment::handleCommentDelete - user #'.User::$id.' could not flag comment #'.$this->_post['id'].' as deleted', E_USER_ERROR);
@@ -208,7 +209,7 @@ class AjaxComment extends AjaxHandler
}
// 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}',
$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
@@ -217,9 +218,10 @@ class AjaxComment extends AjaxHandler
// reflag hasComment
if ($ok)
{
$coInfo = DB::Aowow()->selectRow('SELECT type, typeId FROM ?_comments WHERE id = ?d', $this->_post['id']);
if ($tbl = Type::getClassAttrib($coInfo['type'], 'dataTable'))
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $coInfo['typeId']);
$coInfo = DB::Aowow()->select('SELECT `type`, `typeId` FROM ?_comments WHERE `id` IN (?a) GROUP BY `type`, `typeId`', $this->_post['id']);
foreach ($coInfo as $co)
if ($tbl = Type::getClassAttrib($co['type'], 'dataTable'))
DB::Aowow()->query('UPDATE ?# SET `cuFlags` = `cuFlags` | ?d WHERE `id` = ?d', $tbl, CUSTOM_HAS_COMMENT, $co['typeId']);
}
else
trigger_error('AjaxComment::handleCommentUndelete - user #'.User::$id.' could not unflag comment #'.$this->_post['id'].' as deleted', E_USER_ERROR);
@@ -300,19 +302,24 @@ class AjaxComment extends AjaxHandler
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]);
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]);
else
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~0x4 WHERE id = ?d', $this->_post['id'][0]);
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]);
}
else if (DB::Aowow()->selectCell('SELECT 1 FROM ?_reports WHERE `mode` = ?d AND `reason`= ?d AND `subject` = ?d AND `userId` = ?d', 1, 17, $this->_post['id'][0], User::$id))
return Lang::main('alreadyReport');
else if (User::$id && !$this->_post['reason'] || mb_strlen($this->_post['reason']) < self::REPLY_LENGTH_MIN)
return Lang::main('textTooShort');
else if (User::$id) // only report as outdated
$ok = Util::createReport(1, 17, $this->_post['id'][0], '[Outdated Comment] '.$this->_post['reason']);
else // try to report as outdated
{
$report = new Report(Report::MODE_COMMENT, Report::CO_OUT_OF_DATE, $this->_post['id'][0]);
if ($report->create($this->_post['reason']))
$ok = true; // the script expects the actual characters 'ok' not some json string like "ok"
else
return Lang::main('intError');
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"
if (count($report->getSimilar()) >= 5) // 5 or more reports on the same comment: trigger flag
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags | ?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]);
}
if ($ok)
return 'ok';
else
trigger_error('AjaxComment::handleCommentOutOfDate - failed to update comment in db', E_USER_ERROR);

View File

@@ -6,15 +6,15 @@ if (!defined('AOWOW_REVISION'))
class AjaxContactus extends AjaxHandler
{
protected $_post = array(
'mode' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
'reason' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
'ua' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
'appname' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
'page' => ['filter' => FILTER_SANITIZE_URL],
'desc' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
'id' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
'relatedurl' => ['filter' => FILTER_SANITIZE_URL],
'email' => ['filter' => FILTER_SANITIZE_EMAIL]
'mode' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
'reason' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
'ua' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
'appname' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
'page' => ['filter' => FILTER_SANITIZE_URL ],
'desc' => ['filter' => FILTER_UNSAFE_RAW, 'flags' => FILTER_FLAG_STRIP_AOWOW],
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkInt'],
'relatedurl' => ['filter' => FILTER_SANITIZE_URL ],
'email' => ['filter' => FILTER_SANITIZE_EMAIL ]
);
public function __construct(array $params)
@@ -35,58 +35,13 @@ class AjaxContactus extends AjaxHandler
*/
protected function handleContactUs() : string
{
$mode = $this->_post['mode'];
$rsn = $this->_post['reason'];
$ua = $this->_post['ua'];
$app = $this->_post['appname'];
$url = $this->_post['page'];
$desc = $this->_post['desc'];
$subj = $this->_post['id'];
$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)
{
trigger_error('AjaxContactus::handleContactUs - malformed contact request received', E_USER_ERROR);
return Lang::main('intError');
}
if (!isset($contexts[$mode]) || !in_array($rsn, $contexts[$mode]))
{
trigger_error('AjaxContactus::handleContactUs - report has invalid context (mode:'.$mode.' / reason:'.$rsn.')', E_USER_ERROR);
return Lang::main('intError');
}
if (!$desc)
return 3;
if (mb_strlen($desc) > 500)
return 2;
if (!User::$id && !User::$ip)
{
trigger_error('AjaxContactus::handleContactUs - could not determine IP for anonymous user', E_USER_ERROR);
return Lang::main('intError');
}
// 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, $subj, $field, User::$id ?: User::$ip))
return 7;
if (Util::createReport($mode, $rsn, $subj, $desc, $ua, $app, $url, $this->_post['relatedurl'], $this->_post['email']))
$report = new Report($this->_post['mode'], $this->_post['reason'], $this->_post['id']);
if ($report->create($this->_post['desc'], $this->_post['ua'], $this->_post['appname'], $this->_post['page'], $this->_post['relatedurl'], $this->_post['email']))
return 0;
trigger_error('AjaxContactus::handleContactUs - write to db failed', E_USER_ERROR);
return Lang::main('intError');
else if ($report->errorCode > 0)
return $report->errorCode;
else
return Lang::main('intError');
}
}

View File

@@ -96,6 +96,7 @@ class CommunityContent
{c.replyTo <> ?d AND}
{c.replyTo = ?d AND}
{ur.entry IS ?n AND}
{(c.flags & ?d) AND}
((c.flags & ?d) = 0 OR c.userId = ?d OR ?d)
GROUP BY
c.id
@@ -143,6 +144,7 @@ class CommunityContent
empty($params['replies']) ? DBSIMPLE_SKIP : 0, // i dont know, how to switch the sign around
!empty($params['replies']) ? DBSIMPLE_SKIP : 0,
empty($params['unrated']) ? DBSIMPLE_SKIP : null,
empty($params['flags']) ? DBSIMPLE_SKIP : $params['flags'],
CC_FLAG_DELETED,
User::$id,
User::isInGroup(U_GROUP_COMMENTS_MODERATOR),

View File

@@ -1574,32 +1574,6 @@ abstract class Util
);
}
static function createReport($mode, $reason, $subject, $desc, $userAgent = null, $appName = null, $url = null, $relUrl = null, $email = null)
{
$update = array(
'userId' => User::$id,
'createDate' => time(),
'mode' => $mode,
'reason' => $reason,
'subject' => $subject ?: 0, // not set for utility, tools and misc pages
'ip' => User::$ip,
'description' => $desc,
'userAgent' => $userAgent ?: $_SERVER['HTTP_USER_AGENT'],
'appName' => $appName ?: (get_browser(null, true)['browser'] ?: '')
);
if ($url)
$update['url'] = $url;
if ($relUrl)
$update['relatedurl'] = $relUrl;
if ($email)
$update['email'] = $email;
return DB::Aowow()->query('INSERT INTO ?_reports (?#) VALUES (?a)', array_keys($update), array_values($update));
}
// orientation is 2*M_PI for a full circle, increasing counterclockwise
static function O2Deg($o)
{
@@ -1871,4 +1845,271 @@ abstract class Type
}
}
class Report
{
public const MODE_GENERAL = 0;
public const MODE_COMMENT = 1;
public const MODE_FORUM_POST = 2;
public const MODE_SCREENSHOT = 3;
public const MODE_CHARACTER = 4;
public const MODE_VIDEO = 5;
public const MODE_GUIDE = 6;
public const GEN_FEEDBACK = 1;
public const GEN_BUG_REPORT = 2;
public const GEN_TYPO_TRANSLATION = 3;
public const GEN_OP_ADVERTISING = 4;
public const GEN_OP_PARTNERSHIP = 5;
public const GEN_PRESS_INQUIRY = 6;
public const GEN_MISCELLANEOUS = 7;
public const GEN_MISINFORMATION = 8;
public const CO_ADVERTISING = 15;
public const CO_INACCURATE = 16;
public const CO_OUT_OF_DATE = 17;
public const CO_SPAM = 18;
public const CO_INAPPROPRIATE = 19;
public const CO_MISCELLANEOUS = 20;
public const FO_ADVERTISING = 30;
public const FO_AVATAR = 31;
public const FO_INACCURATE = 32;
public const FO_OUT_OF_DATE = 33;
public const FO_SPAM = 34;
public const FO_STICKY_REQUEST = 35;
public const FO_INAPPROPRIATE = 36;
public const FO_MISCELLANEOUS = 37;
public const SS_INACCURATE = 45;
public const SS_OUT_OF_DATE = 46;
public const SS_INAPPROPRIATE = 47;
public const SS_MISCELLANEOUS = 48;
public const PR_INACCURATE_DATA = 60;
public const PR_MISCELLANEOUS = 61;
public const VI_INACCURATE = 45;
public const VI_OUT_OF_DATE = 46;
public const VI_INAPPROPRIATE = 47;
public const VI_MISCELLANEOUS = 48;
public const AR_INACCURATE = 45;
public const AR_OUT_OF_DATE = 46;
public const AR_MISCELLANEOUS = 48;
private /* array */ $context = array(
self::MODE_GENERAL => array(
self::GEN_FEEDBACK => true,
self::GEN_BUG_REPORT => true,
self::GEN_TYPO_TRANSLATION => true,
self::GEN_OP_ADVERTISING => true,
self::GEN_OP_PARTNERSHIP => true,
self::GEN_PRESS_INQUIRY => true,
self::GEN_MISCELLANEOUS => true,
self::GEN_MISINFORMATION => true
),
self::MODE_COMMENT => array(
self::CO_ADVERTISING => U_GROUP_MODERATOR,
self::CO_INACCURATE => true,
self::CO_OUT_OF_DATE => true,
self::CO_SPAM => U_GROUP_MODERATOR,
self::CO_INAPPROPRIATE => U_GROUP_MODERATOR,
self::CO_MISCELLANEOUS => U_GROUP_MODERATOR
),
self::MODE_FORUM_POST => array(
self::FO_ADVERTISING => U_GROUP_MODERATOR,
self::FO_AVATAR => true,
self::FO_INACCURATE => true,
self::FO_OUT_OF_DATE => U_GROUP_MODERATOR,
self::FO_SPAM => U_GROUP_MODERATOR,
self::FO_STICKY_REQUEST => U_GROUP_MODERATOR,
self::FO_INAPPROPRIATE => U_GROUP_MODERATOR
),
self::MODE_SCREENSHOT => array(
self::SS_INACCURATE => true,
self::SS_OUT_OF_DATE => true,
self::SS_INAPPROPRIATE => U_GROUP_MODERATOR,
self::SS_MISCELLANEOUS => U_GROUP_MODERATOR
),
self::MODE_CHARACTER => array(
self::PR_INACCURATE_DATA => true,
self::PR_MISCELLANEOUS => true
),
self::MODE_VIDEO => array(
self::VI_INACCURATE => true,
self::VI_OUT_OF_DATE => true,
self::VI_INAPPROPRIATE => U_GROUP_MODERATOR,
self::VI_MISCELLANEOUS => U_GROUP_MODERATOR
),
self::MODE_GUIDE => array(
self::AR_INACCURATE => true,
self::AR_OUT_OF_DATE => true,
self::AR_MISCELLANEOUS => true
)
);
private const ERR_NONE = 0; // aka: success
private const ERR_INVALID_CAPTCHA = 1; // captcha not in use
private const ERR_DESC_TOO_LONG = 2;
private const ERR_NO_DESC = 3;
private const ERR_ALREADY_REPORTED = 7;
private const ERR_MISCELLANEOUS = -1;
public const STATUS_OPEN = 0;
public const STATUS_ASSIGNED = 1;
public const STATUS_CLOSED_WONTFIX = 2;
public const STATUS_CLOSED_SOLVED = 3;
private /* int */ $mode = 0;
private /* int */ $reason = 0;
private /* int */ $subject = 0;
public /* readonly int */ $errorCode;
public function __construct(int $mode, int $reason, int $subject = 0)
{
if ($mode < 0 || $reason <= 0 || !$subject)
{
trigger_error('AjaxContactus::handleContactUs - malformed contact request received', E_USER_ERROR);
$this->errorCode = self::ERR_MISCELLANEOUS;
return;
}
if (!isset($this->context[$mode][$reason]))
{
trigger_error('AjaxContactus::handleContactUs - report has invalid context (mode:'.$mode.' / reason:'.$reason.')', E_USER_ERROR);
$this->errorCode = self::ERR_MISCELLANEOUS;
return;
}
if (!User::$id && !User::$ip)
{
trigger_error('AjaxContactus::handleContactUs - could not determine IP for anonymous user', E_USER_ERROR);
$this->errorCode = self::ERR_MISCELLANEOUS;
return;
}
$this->mode = $mode;
$this->reason = $reason;
$this->subject = $subject; // 0 for utility, tools and misc pages?
}
private function checkTargetContext() : int
{
// 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 ?# = ?', $this->mode, $this->reason, $this->subject, $field, User::$id ?: User::$ip))
return self::ERR_ALREADY_REPORTED;
// check targeted post/postOwner staff status
$ctxCheck = $this->context[$this->mode][$this->reason];
if (is_int($ctxCheck))
{
$roles = User::$groups;
if ($this->mode == self::MODE_COMMENT)
$roles = DB::Aowow()->selectCell('SELECT `roles` FROM ?_comments WHERE `id` = ?d', $this->subject);
// else if if ($this->mode == self::MODE_FORUM_POST)
// $roles = DB::Aowow()->selectCell('SELECT `roles` FROM ?_forum_posts WHERE `id` = ?d', $this->subject);
return $roles & $ctxCheck ? self::ERR_NONE : self::ERR_MISCELLANEOUS;
}
else
return $ctxCheck ? self::ERR_NONE : self::ERR_MISCELLANEOUS;
// Forum not in use, else:
// check post owner
// User::$id == post.op && !post.sticky;
// check user custom avatar
// g_users[post.user].avatar == 2 && (post.roles & U_GROUP_MODERATOR) == 0
}
public function create(string $desc, ?string $userAgent = null, ?string $appName = null, ?string $pageUrl = null, ?string $relUrl = null, ?string $email = null) : bool
{
if ($this->errorCode)
return false;
if (!$desc)
{
$this->errorCode = self::ERR_NO_DESC;
return false;
}
if (mb_strlen($desc) > 500)
{
$this->errorCode = self::ERR_DESC_TOO_LONG;
return false;
}
if($err = $this->checkTargetContext())
{
$this->errorCode = $err;
return false;
}
$update = array(
'userId' => User::$id,
'createDate' => time(),
'mode' => $this->mode,
'reason' => $this->reason,
'subject' => $this->subject,
'ip' => User::$ip,
'description' => $desc,
'userAgent' => $userAgent ?: $_SERVER['HTTP_USER_AGENT'],
'appName' => $appName ?: (get_browser(null, true)['browser'] ?: '')
);
if ($pageUrl)
$update['url'] = $pageUrl;
if ($relUrl)
$update['relatedurl'] = $relUrl;
if ($email)
$update['email'] = $email;
return DB::Aowow()->query('INSERT INTO ?_reports (?#) VALUES (?a)', array_keys($update), array_values($update));
}
public function getSimilar(int ...$status) : array
{
if ($this->errorCode)
return [];
foreach ($status as &$s)
if ($s < self::STATUS_OPEN || $s > self::STATUS_CLOSED_SOLVED)
unset($s);
return DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, r.* FROM ?_reports r WHERE {`status` IN (?a) AND }`mode` = ?d AND `reason` = ?d AND `subject` = ?d',
$status ?: DBSIMPLE_SKIP, $this->mode, $this->reason, $this->subject);
}
public function close(int $closeStatus, bool $inclAssigned = false) : bool
{
if ($closeStatus != self::STATUS_CLOSED_SOLVED && $closeStatus != self::STATUS_CLOSED_WONTFIX)
return false;
if (!User::isInGroup(U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD))
return false;
$fromStatus = [self::STATUS_OPEN];
if ($inclAssigned)
$fromStatus[] = self::STATUS_ASSIGNED;
if ($reports = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `userId` FROM ?_reports WHERE `status` IN (?a) AND `mode` = ?d AND `reason` = ?d AND `subject` = ?d',
$fromStatus, $this->mode, $this->reason, $this->subject))
{
DB::Aowow()->query('UPDATE ?_reports SET `status` = ?d, `assigned` = 0 WHERE `id` IN (?a)', $closeStatus, array_keys($reports));
foreach ($reports as $rId => $uId)
Util::gainSiteReputation($uId, $closeStatus == self::STATUS_CLOSED_SOLVED ? SITEREP_ACTION_GOOD_REPORT : SITEREP_ACTION_BAD_REPORT, ['id' => $rId]);
return true;
}
return false;
}
public function reopen(int $assignedTo = 0) : bool
{
// assignedTo = 0 ? status = STATUS_OPEN : status = STATUS_ASSIGNED, userId = assignedTo
return false;
}
}
?>

View File

@@ -65,6 +65,22 @@ class AdminPage extends GenericPage
array_push($this->path, 1, 25);
$this->name = 'Pending Guides';
break;
case 'out-of-date':
$this->reqUGroup = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD;
$this->generator = 'handleOutOfDate';
$this->tpl = 'list-page-generic';
array_push($this->path, 1, 23);
$this->name = 'Out of Date Comments';
break;
case 'reports':
$this->reqUGroup = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_EDITOR | U_GROUP_MOD | U_GROUP_LOCALIZER | U_GROUP_SCREENSHOT | U_GROUP_VIDEO;
$this->generator = 'handleReports';
$this->tpl = 'admin/reports';
array_push($this->path, 5);
$this->name = 'Reports';
break;
default: // error out through unset template
}
@@ -280,6 +296,22 @@ class AdminPage extends GenericPage
), 'guideAdminCol'];
}
private function handleOutOfDate() : void
{
$data = CommunityContent::getCommentPreviews(['flags' => CC_FLAG_OUTDATED]);
$this->lvTabs[] = ['commentpreview', array(
'data' => $data,
'extraCols' => '$_'
), 'commentAdminCol'];
}
private function handleReports() : void
{
// todo: handle reports listing
//
}
private function configAddRow($r)
{
$buff = '<tr>';

View File

@@ -21213,52 +21213,28 @@ var ContactTool = new function() {
[7, true] // Other
],
1: [ // comment
[15, function(post) {
return ((post.roles & U_GROUP_MODERATOR) == 0);
}], // Advertising
[16, true], // Inaccurate
[17, true], // Out of date
[18, function(post) {
return ((post.roles & U_GROUP_MODERATOR) == 0);
}], // Spam
[19, function(post) {
return ((post.roles & U_GROUP_MODERATOR) == 0);
}], // Vulgar/inappropriate
[20, function(post) {
return ((post.roles & U_GROUP_MODERATOR) == 0);
}] // Other
[15, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Advertising
[16, true], // Inaccurate
[17, true], // Out of date
[18, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Spam
[19, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[20, function(post) { return ((post.roles & U_GROUP_MODERATOR) == 0); }] // Other
],
2: [ // forum post
[30, function(post) {
return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0);
}], // Advertising
[37, function(post) {
return ((post.roles & U_GROUP_MODERATOR) == 0 && g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && g_users[post.user].avatar == 2);
}], // Avatar
[31, true], // Inaccurate
[32, true], // Out of date
[33, function(post) {
return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0);
}], // Spam
[34, function(post) {
return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && post.op && !post.sticky);
}], // Sticky request
[35, function(post) {
return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0);
}], // Vulgar/inappropriate
[36, function(post) {
return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0);
}] // Other
[30, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Advertising
[37, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && (post.roles & U_GROUP_MODERATOR) == 0 && g_users[post.user].avatar == 2); }], // Avatar
[31, true], // Inaccurate
[32, true], // Out of date
[33, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Spam
[34, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0 && post.op && !post.sticky); }], // Sticky request
[35, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[36, function(post) { return (g_users && g_users[post.user] && (g_users[post.user].roles & U_GROUP_MODERATOR) == 0);}] // Other
],
3: [ // screenshot
[45, true], // Inaccurate,
[46, true], // Out of date,
[47, function(screen) {
return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0);
}], // Vulgar/inappropriate
[48, function(screen) {
return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0);
}] // Other
[47, function(screen) { return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[48, function(screen) { return (g_users && g_users[screen.user] && (g_users[screen.user].roles & U_GROUP_MODERATOR) == 0); }] // Other
],
4: [ // character
[60, true], // Inaccurate completion data
@@ -21267,14 +21243,10 @@ var ContactTool = new function() {
5: [ // video
[45, true], // Inaccurate,
[46, true], // Out of date,
[47, function(video) {
return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0);
}], // Vulgar/inappropriate
[48, function(video) {
return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0);
}] // Other
[47, function(video) { return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); }], // Vulgar/inappropriate
[48, function(video) { return (g_users && g_users[video.user] && (g_users[video.user].roles & U_GROUP_MODERATOR) == 0); }] // Other
],
6: [ // Guide
6: [ // guide
[45, true], // Inaccurate,
[46, true], // Out of date,
[48, true] // Other
@@ -21323,12 +21295,12 @@ var ContactTool = new function() {
var params = [
'contact=1',
'mode=' + $WH.urlencode(data.mode),
'reason=' + $WH.urlencode(data.reason),
'desc=' + $WH.urlencode(data.description),
'ua=' + $WH.urlencode(navigator.userAgent),
'mode=' + $WH.urlencode(data.mode),
'reason=' + $WH.urlencode(data.reason),
'desc=' + $WH.urlencode(data.description),
'ua=' + $WH.urlencode(navigator.userAgent),
'appname=' + $WH.urlencode(navigator.appName),
'page=' + $WH.urlencode(data.currenturl)
'page=' + $WH.urlencode(data.currenturl)
];
if (data.mode == 0) { // contact us
@@ -21366,30 +21338,27 @@ var ContactTool = new function() {
onSuccess: function(xhr, opt) {
var resp = xhr.responseText;
if (resp == 0) {
if (g_user.name) {
if (g_user.name)
alert($WH.sprintf(LANG.ct_dialog_thanks_user, g_user.name));
}
else {
else
alert(LANG.ct_dialog_thanks);
}
Lightbox.hide();
}
else {
if (errors[resp]) {
if (errors[resp])
alert(errors[resp]);
}
else {
else
alert('Error: ' + resp);
}
}
},
onFailure: function(xhr, opt) {
alert('Failure submitting contact request: ' + xhr.statusText);
},
onComplete: function(xhr, opt) {
for (var i = 0; i < form.elements.length; ++i) {
for (var i = 0; i < form.elements.length; ++i)
form.elements[i].disabled = false;
}
data.submitting = false;
}
});

View File

@@ -106,7 +106,7 @@ var mn_staff = [
// [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} ],
[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}]];

View File

@@ -0,0 +1,50 @@
var _ = [
{
id: 'manage',
name: 'Manage',
type: 'text',
align: 'center',
value: 'subject',
sortable: false,
compute: function(comment, td, tr) {
let wrapper = $WH.ce('div');
let send = function (el, id, status)
{
$.ajax({cache: false, url: '?admin=comment', type: 'POST',
error: function() {
alert('Operation failed.');
},
success: function(json) {
if (json != 1)
alert('Operation failed.');
else
$WH.de(el.parentNode);
},
data: { id: id, status: status }
})
return true;
};
let a = $WH.ce('a');
a.style.fontFamily = 'Verdana, sans-serif';
a.style.marginLeft = '10px';
a.href = '#';
_ = a.cloneNode();
_.className = 'icon-tick';
_.onclick = send.bind(this, td, comment.id, 0);
g_addTooltip(_, LANG.lvcomment_uptodate);
$WH.ae(wrapper, _);
_ = a.cloneNode();
_.className = 'icon-delete';
_.onclick = send.bind(this, td, comment.id, 1);
g_addTooltip(_, LANG.delete);
$WH.ae(wrapper, _);
$WH.ae(td, wrapper);
}
}
];

View File

@@ -0,0 +1,53 @@
<?php $this->brick('header'); ?>
<script type="text/javascript">
</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');
?>
<div class="text">
<h1><?=$this->name;?></h1>
<?php
$this->brick('article');
if (isset($this->extraText)):
?>
<div id="text-generic" class="left"></div>
<script type="text/javascript">//<![CDATA[
Markup.printHtml("<?=Util::jsEscape($this->extraText);?>", "text-generic", {
allow: Markup.CLASS_ADMIN,
dbpage: true
});
//]]></script>
<div class="pad2"></div>
<?php
endif;
if (isset($this->extraHTML)):
echo $this->extraHTML;
endif;
?>
<h2>Edit<span id="wt-name"></span><span id="status-ic" style="float:right;"></span></h2>
<div class="wt-edit">
<div style="display:inline-block; vertical-align:top;"><div class="pad2" style="color: white; font-size: 15px; font-weight: bold;">Icon</div><input type="text" id="wt-icon" size="30" /></div>
<div id="ic-container" style="display: inline-block; clear: left;"></div>
</div>
<div class="wt-edit">
<div class="pad2" style="color: white; font-size: 15px; font-weight: bold;">Scale</div>
<div id="su-container"></div>
</div>
<div id="su-controls" class="wt-edit" style="width:auto;"></div>
</div>
</div><!-- main-contents -->
</div><!-- main -->
<?php $this->brick('footer'); ?>