mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Template/Update (Part 15)
* convert comment/reply ajax (add, edit, delete, vote, report and management) and redirects (comment/reply > db-page) * update roles when updating own comment/reply
This commit is contained in:
51
endpoints/admin/comment.php
Normal file
51
endpoints/admin/comment.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class AdminCommentResponse extends TextResponse
|
||||
{
|
||||
private const /* int */ ERR_NONE = 1;
|
||||
private const /* int */ ERR_WRITE_DB = 0;
|
||||
private const /* int */ ERR_MISCELLANEOUS = 999;
|
||||
|
||||
protected int $requiredUserGroup = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'status' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 0, 'max_range' => 1]]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id', 'status'))
|
||||
{
|
||||
trigger_error('AdminCommentResponse - malformed request received', E_USER_ERROR);
|
||||
$this->result = self::ERR_MISCELLANEOUS;
|
||||
return;
|
||||
}
|
||||
|
||||
// check if is marked as outdated CC_FLAG_OUTDATED?
|
||||
|
||||
$ok = false;
|
||||
if ($this->_post['status']) // 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);
|
||||
}
|
||||
else // 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);
|
||||
}
|
||||
|
||||
$this->result = $ok ? self::ERR_NONE : self::ERR_WRITE_DB;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
34
endpoints/admin/out-of-date.php
Normal file
34
endpoints/admin/out-of-date.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class AdminOutofdateResponse extends TemplateResponse
|
||||
{
|
||||
protected int $requiredUserGroup = U_GROUP_ADMIN | U_GROUP_BUREAU | U_GROUP_MOD;
|
||||
|
||||
protected string $template = 'list-page-generic';
|
||||
protected string $pageName = 'out-of-date';
|
||||
protected ?int $activeTab = parent::TAB_STAFF;
|
||||
protected array $breadcrumb = [4, 1, 23]; // Staff > Content > Out of Date Comments
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
$this->h1 = 'Out of Date Comments';
|
||||
array_unshift($this->title, $this->h1);
|
||||
|
||||
$this->lvTabs = new Tabs(['parent' => "\$\$WH.ge('tabs-generic')"]);
|
||||
|
||||
parent::generate();
|
||||
|
||||
$this->lvTabs->addListviewTab(new Listview(array(
|
||||
'data' => CommunityContent::getCommentPreviews(['flags' => CC_FLAG_OUTDATED]),
|
||||
'extraCols' => '$_'
|
||||
), 'commentpreview', 'commentAdminCol'));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
51
endpoints/comment/add-reply.php
Normal file
51
endpoints/comment/add-reply.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// returns all replies on success
|
||||
// must have non-200 header on error
|
||||
class CommentAddreplyResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'commentId' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'replyId' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'body' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextBlob']]
|
||||
);
|
||||
|
||||
protected function generate(): void
|
||||
{
|
||||
if (!$this->assertPOST('commentId', 'replyId', 'body'))
|
||||
{
|
||||
trigger_error('CommentAddreplyResponse - malformed request received', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'request malformed' : '');
|
||||
}
|
||||
|
||||
if (!User::canReply())
|
||||
$this->generate404(Lang::main('cannotComment'));
|
||||
|
||||
if (!$this->_post['commentId'] || !DB::Aowow()->selectCell('SELECT 1 FROM ?_comments WHERE `id` = ?d', $this->_post['commentId']))
|
||||
{
|
||||
trigger_error('CommentAddreplyResponse - parent comment #'.$this->_post['commentId'].' does not exist', E_USER_ERROR);
|
||||
$this->generate404(Lang::main('intError'));
|
||||
}
|
||||
|
||||
if (mb_strlen($this->_post['body']) < CommunityContent::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > CommunityContent::REPLY_LENGTH_MAX)
|
||||
$this->generate404(Lang::main('textLength', [mb_strlen($this->_post['body']), CommunityContent::REPLY_LENGTH_MIN, CommunityContent::REPLY_LENGTH_MAX]));
|
||||
|
||||
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']))
|
||||
{
|
||||
trigger_error('CommentAddreplyResponse - write to db failed', E_USER_ERROR);
|
||||
$this->generate404(Lang::main('intError'));
|
||||
}
|
||||
|
||||
$this->result = Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
79
endpoints/comment/add.php
Normal file
79
endpoints/comment/add.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class CommentAddResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'commentbody' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextBlob']]
|
||||
);
|
||||
protected array $expectedGET = array(
|
||||
'type' => ['filter' => FILTER_VALIDATE_INT],
|
||||
'typeid' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
// 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 generate() : void
|
||||
{
|
||||
if (!$this->assertGET('type', 'typeid') || !$this->assertPOST('commentbody') || !Type::validateIds($this->_get['type'], $this->_get['typeid']))
|
||||
{
|
||||
trigger_error('CommentAddResponse - malforemd request received', E_USER_ERROR);
|
||||
return; // whatever, we cant even send him back
|
||||
}
|
||||
|
||||
// we now have a valid return target
|
||||
$idOrUrl = $this->_get['typeid'];
|
||||
if ($this->_get['type'] == Type::GUIDE)
|
||||
if ($_ = DB::Aowow()->selectCell('SELECT `url` FROM ?_guides WHERE `id` = ?d', $this->_get['typeid']))
|
||||
$idOrUrl = $_;
|
||||
|
||||
$this->redirectTo = '?'.Type::getFileString($this->_get['type']).'='.$idOrUrl.'#comments';
|
||||
|
||||
// this type cannot be commented on
|
||||
if (!Type::checkClassAttrib($this->_get['type'], 'contribute', CONTRIBUTE_CO))
|
||||
{
|
||||
trigger_error('CommentAddResponse - tried to comment on unsupported type: '.Type::getFileString($this->_get['type']), E_USER_ERROR);
|
||||
$_SESSION['error']['co'] = Lang::main('intError');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!User::canComment())
|
||||
{
|
||||
$_SESSION['error']['co'] = Lang::main('cannotComment');
|
||||
return;
|
||||
}
|
||||
|
||||
$len = mb_strlen($this->_post['commentbody']);
|
||||
|
||||
if ((!User::isInGroup(U_GROUP_MODERATOR) && $len < CommunityContent::COMMENT_LENGTH_MIN) || ($len > CommunityContent::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)))
|
||||
{
|
||||
$_SESSION['error']['co'] = Lang::main('textLength', [$len, CommunityContent::COMMENT_LENGTH_MIN, CommunityContent::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($postId = 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' => $postId]);
|
||||
|
||||
// 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 ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, 0, 1)', RATING_COMMENT, $postId);
|
||||
|
||||
// flag target with hasComment
|
||||
if ($tbl = Type::getClassAttrib($this->_get['type'], 'dataTable'))
|
||||
DB::Aowow()->query('UPDATE ?# SET `cuFlags` = `cuFlags` | ?d WHERE `id` = ?d', $tbl, CUSTOM_HAS_COMMENT, $this->_get['typeid']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
trigger_error('CommentAddResponse - write to db failed', E_USER_ERROR);
|
||||
$_SESSION['error']['co'] = Lang::main('intError');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
44
endpoints/comment/delete-reply.php
Normal file
44
endpoints/comment/delete-reply.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// expects non-200 header on error
|
||||
class CommentDeletereplyResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentDeletereplyResponse - malformed request received', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'request malformed' : '');
|
||||
}
|
||||
|
||||
// flag as deleted (unset sticky (can a reply even be sticky?)
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` & ~?d | ?d, `deleteUserId` = ?d, `deleteDate` = UNIX_TIMESTAMP() WHERE `id` = ?d { AND `userId` = ?d }',
|
||||
CC_FLAG_STICKY, CC_FLAG_DELETED,
|
||||
User::$id,
|
||||
$this->_post['id'],
|
||||
User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id
|
||||
);
|
||||
|
||||
if ($ok)
|
||||
DB::Aowow()->query('DELETE FROM ?_user_ratings WHERE `type` = ?d AND `entry` = ?d', RATING_COMMENT, $this->_post['id']);
|
||||
else
|
||||
{
|
||||
trigger_error('CommentDeletereplyResponse - deleting reply #'.$this->_post['id'].' by user #'.User::$id.' from db failed', E_USER_ERROR);
|
||||
$this->generate404(Lang::main('intError'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
53
endpoints/comment/delete.php
Normal file
53
endpoints/comment/delete.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class CommentDeleteResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkIdListUnsigned']],
|
||||
// 'username' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine'] ]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentDeleteResponse - malformed request received', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// in theory, there is a username passed alongside if executed from userpage... 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
|
||||
);
|
||||
|
||||
// unflag subject: hasComment
|
||||
if ($ok)
|
||||
{
|
||||
$coInfo = DB::Aowow()->select(
|
||||
'SELECT IF(BIT_OR(~b.`flags`) & ?d, 1, 0) AS "0", b.`type` AS "1", b.`typeId` AS "2" 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']
|
||||
);
|
||||
|
||||
foreach ($coInfo as [$hasMore, $type, $typeId])
|
||||
if (!$hasMore && ($tbl = Type::getClassAttrib($type, 'dataTable')))
|
||||
DB::Aowow()->query('UPDATE ?# SET `cuFlags` = `cuFlags` & ~?d WHERE `id` = ?d', $tbl, CUSTOM_HAS_COMMENT, $typeId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
trigger_error('CommentDeleteResponse - user #'.User::$id.' could not flag comment(s) #'.implode(', ', $this->_post['id']).' as deleted', E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
30
endpoints/comment/detach-reply.php
Normal file
30
endpoints/comment/detach-reply.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// expects non-200 header on error
|
||||
class CommentDetachreplyResponse extends TextResponse
|
||||
{
|
||||
protected int $requiredUserGroup = U_GROUP_MODERATOR;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentDetachreplyResponse - malformed request received', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'request malformed' : '');
|
||||
}
|
||||
|
||||
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']);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
61
endpoints/comment/downvote-reply.php
Normal file
61
endpoints/comment/downvote-reply.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// expects non-200 header on error
|
||||
class CommentDownvotereplyResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentDownvotereplyResponse - malformed request received', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'request malformed' : '');
|
||||
}
|
||||
|
||||
if (!User::canDownvote())
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'cannot downvote' : '');
|
||||
|
||||
$comment = DB::Aowow()->selectRow('SELECT `userId`, IF(`flags` & ?d, 1, 0) AS "deleted" FROM ?_comments WHERE `id` = ?d', CC_FLAG_DELETED, $this->_post['id']);
|
||||
if (!$comment)
|
||||
{
|
||||
trigger_error('CommentDownvotereplyResponse - comment #'.$this->_post['id'].' not found in db', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'replyID not found' : '');
|
||||
}
|
||||
|
||||
if (User::$id == $comment['userId']) // not worth logging?
|
||||
$this->generate404('LANG.voteself_tip');
|
||||
|
||||
if ($comment['deleted'])
|
||||
$this->generate404('LANG.votedeleted_tip');
|
||||
|
||||
$ok = DB::Aowow()->query(
|
||||
'INSERT INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)',
|
||||
RATING_COMMENT,
|
||||
$this->_post['id'],
|
||||
User::$id,
|
||||
User::canSupervote() ? -2 : -1
|
||||
);
|
||||
|
||||
if (!$ok)
|
||||
{
|
||||
trigger_error('CommentDownvotereplyResponse - write to db failed', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'write to db failed' : '');
|
||||
}
|
||||
|
||||
Util::gainSiteReputation($comment['userId'], SITEREP_ACTION_DOWNVOTED, ['id' => $this->_post['id'], 'voterId' => User::$id]);
|
||||
User::decrementDailyVotes();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
62
endpoints/comment/edit-reply.php
Normal file
62
endpoints/comment/edit-reply.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// returns all replies on success
|
||||
// must have non-200 header on error
|
||||
class CommentEditreplyResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'commentId' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'replyId' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'body' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextBlob']]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('commentId', 'replyId', 'body'))
|
||||
{
|
||||
trigger_error('CommentEditreplyResponse - malformed request received', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'request malformed' : '');
|
||||
}
|
||||
|
||||
$ownerId = DB::Aowow()->selectCell('SELECT `userId` FROM ?_comments WHERE `id` = ?d AND `replyTo` = ?d', $this->_post['replyId'], $this->_post['commentId']);
|
||||
|
||||
if (!User::canReply() || (User::$id != $ownerId && !User::isInGroup(U_GROUP_MODERATOR)))
|
||||
$this->generate404(Lang::main('cannotComment'));
|
||||
|
||||
if (!$ownerId)
|
||||
{
|
||||
trigger_error('CommentEditreplyResponse - comment #'.$this->_post['commentId'].' or reply #'.$this->_post['replyId'].' does not exist', E_USER_ERROR);
|
||||
$this->generate404(Lang::main('intError'));
|
||||
}
|
||||
|
||||
if (mb_strlen($this->_post['body']) < CommunityContent::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > CommunityContent::REPLY_LENGTH_MAX)
|
||||
$this->generate404(Lang::main('textLength', [mb_strlen($this->_post['body']), CommunityContent::REPLY_LENGTH_MIN, CommunityContent::REPLY_LENGTH_MAX]));
|
||||
|
||||
$update = array(
|
||||
'body' => $this->_post['body'],
|
||||
'editUserId' => User::$id,
|
||||
'editDate' => time()
|
||||
);
|
||||
if (User::$id == $ownerId)
|
||||
$update['roles'] = User::$groups;
|
||||
|
||||
if (!DB::Aowow()->query('UPDATE ?_comments SET `editCount` = `editCount` + 1, ?a WHERE `id` = ?d AND `replyTo` = ?d { AND `userId` = ?d }',
|
||||
$update, $this->_post['replyId'], $this->_post['commentId'], User::isInGroup(U_GROUP_MODERATOR) ? DBSIMPLE_SKIP : User::$id))
|
||||
{
|
||||
trigger_error('CommentEditreplyResponse - write to db failed', E_USER_ERROR);
|
||||
$this->generate404(Lang::main('intError'));
|
||||
}
|
||||
|
||||
$this->result = Util::toJSON(CommunityContent::getCommentReplies($this->_post['commentId']));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
63
endpoints/comment/edit.php
Normal file
63
endpoints/comment/edit.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class CommentEditResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'body' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextBlob']],
|
||||
'response' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextBlob']]
|
||||
);
|
||||
protected array $expectedGET = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertGET('id') || !$this->assertPOST('body'))
|
||||
{
|
||||
trigger_error('CommentEditResponse - malforemd request received', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$ownerId = DB::Aowow()->selectCell('SELECT `userId` FROM ?_comments WHERE `id` = ?d', $this->_get['id']);
|
||||
|
||||
if (!User::canComment() || (User::$id != $ownerId && !User::isInGroup(U_GROUP_MODERATOR)))
|
||||
{
|
||||
trigger_error('CommentEditResponse - user #'.User::$id.' not allowed to edit comment #'.$this->_get['id'], E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!User::isInGroup(U_GROUP_MODERATOR) && mb_strlen($this->_post['body']) < CommunityContent::COMMENT_LENGTH_MIN)
|
||||
return; // no point in reporting this trifle
|
||||
|
||||
// trim to max length
|
||||
if (!User::isInGroup(U_GROUP_MODERATOR))
|
||||
$this->_post['body'] = mb_substr($this->_post['body'], 0, (CommunityContent::COMMENT_LENGTH_MAX * (User::isPremium() ? 3 : 1)));
|
||||
|
||||
$update = array(
|
||||
'body' => $this->_post['body'],
|
||||
'editUserId' => User::$id,
|
||||
'editDate' => time()
|
||||
);
|
||||
if (User::$id == $ownerId)
|
||||
$update['roles'] = User::$groups;
|
||||
|
||||
if (User::isInGroup(U_GROUP_MODERATOR))
|
||||
{
|
||||
$update['responseBody'] = $this->_post['response'] ?? '';
|
||||
$update['responseUserId'] = User::$id;
|
||||
$update['responseRoles'] = User::$groups;
|
||||
}
|
||||
|
||||
DB::Aowow()->query('UPDATE ?_comments SET `editCount` = `editCount` + 1, ?a WHERE `id` = ?d', $update, $this->_get['id']);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
45
endpoints/comment/flag-reply.php
Normal file
45
endpoints/comment/flag-reply.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// expects non-200 header on error
|
||||
class CommentFlagreplyResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentFlagreplyResponse - malformed request received', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'request malformed' : '');
|
||||
}
|
||||
|
||||
$replyOwner = DB::Aowow()->selectCell('SELECT `userId` FROM ?_commments WHERE `id` = ?d', $this->_post['id']);
|
||||
if (!$replyOwner)
|
||||
{
|
||||
trigger_error('CommentFlagreplyResponse - reply not found', E_USER_ERROR);
|
||||
$this->generate404(Lang::main('intError'));
|
||||
}
|
||||
|
||||
// ui element should not be present
|
||||
if ($replyOwner == User::$id)
|
||||
$this->generate404();
|
||||
|
||||
$report = new Report(Report::MODE_COMMENT, Report::CO_INAPPROPRIATE, $this->_post['id']);
|
||||
if (!$report->create('Report Reply Button Click'))
|
||||
$this->generate404('LANG.ct_resp_error'.$report->getError());
|
||||
else if (count($report->getSimilar()) >= CommunityContent::REPORT_THRESHOLD_AUTO_DELETE)
|
||||
DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` | ?d WHERE `id` = ?d', CC_FLAG_DELETED, $this->_post['id']);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
58
endpoints/comment/out-of-date.php
Normal file
58
endpoints/comment/out-of-date.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// toggle flag
|
||||
class CommentOutofdateResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'remove' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 1, 'max_range' => 1]],
|
||||
'reason' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextBlob'] ]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentOutofdateResponse - malformed request received', E_USER_ERROR);
|
||||
if (User::isInGroup(U_GROUP_STAFF))
|
||||
$this->result = 'malformed request received';
|
||||
}
|
||||
|
||||
$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` | ?d WHERE `id` = ?d', CC_FLAG_OUTDATED, $this->_post['id']);
|
||||
else
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` & ~?d WHERE `id` = ?d', CC_FLAG_OUTDATED, $this->_post['id']);
|
||||
}
|
||||
else // try to report as outdated
|
||||
{
|
||||
$report = new Report(Report::MODE_COMMENT, Report::CO_OUT_OF_DATE, $this->_post['id']);
|
||||
if (!$report->create($this->_post['reason']))
|
||||
$this->result = Lang::main('intError');
|
||||
|
||||
if (count($report->getSimilar()) >= CommunityContent::REPORT_THRESHOLD_AUTO_OUT_OF_DATE)
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` | ?d WHERE `id` = ?d', CC_FLAG_OUTDATED, $this->_post['id']);
|
||||
}
|
||||
|
||||
if (!$ok)
|
||||
{
|
||||
trigger_error('CommentOutofdateResponse - failed to update comment in db', E_USER_ERROR);
|
||||
$this->result = Lang::main('intError');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->result = 'ok'; // the js expects the actual characters 'ok' on success, not some json string like '"ok"'
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
31
endpoints/comment/rating.php
Normal file
31
endpoints/comment/rating.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// up/down - distribution
|
||||
class CommentRatingResponse extends TextResponse
|
||||
{
|
||||
protected array $expectedGET = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertGET('id'))
|
||||
{
|
||||
$this->result = Util::toJSON(['success' => 0]);
|
||||
return;
|
||||
}
|
||||
|
||||
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 ?_user_ratings WHERE `type` = ?d AND `entry` = ?d AND `userId` <> 0 GROUP BY `entry`', RATING_COMMENT, $this->_get['id']))
|
||||
$this->result = Util::toJSON($votes);
|
||||
else
|
||||
$this->result = Util::toJSON(['success' => 1, 'up' => 0, 'down' => 0]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
24
endpoints/comment/show-replies.php
Normal file
24
endpoints/comment/show-replies.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class CommentShowrepliesResponse extends TextResponse
|
||||
{
|
||||
protected array $expectedGET = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertGET('id'))
|
||||
$this->result = Util::toJSON([]);
|
||||
else
|
||||
$this->result = Util::toJSON(CommunityContent::getCommentReplies($this->_get['id']));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
34
endpoints/comment/sticky.php
Normal file
34
endpoints/comment/sticky.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// toggle flag
|
||||
class CommentStickyResponse extends TextResponse
|
||||
{
|
||||
protected int $requiredUserGroup = U_GROUP_MODERATOR;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'sticky' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => 0, 'max_range' => 1]]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id', 'sticky'))
|
||||
{
|
||||
trigger_error('CommentStickyResponse - malformed request received', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->_post['sticky'])
|
||||
DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` | ?d WHERE `id` = ?d', CC_FLAG_STICKY, $this->_post['id']);
|
||||
else
|
||||
DB::Aowow()->query('UPDATE ?_comments SET `flags` = `flags` & ~?d WHERE `id` = ?d', CC_FLAG_STICKY, $this->_post['id']);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
48
endpoints/comment/undelete.php
Normal file
48
endpoints/comment/undelete.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class CommentUndeleteResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkIdListUnsigned']],
|
||||
// 'username' => ['filter' => FILTER_CALLBACK, 'options' => [self::class, 'checkTextLine'] ]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentUndeleteResponse - malformed request received', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// in theory, there is a username passed alongside if executed from userpage... 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
|
||||
);
|
||||
|
||||
// unflag subject: hasComment
|
||||
if ($ok)
|
||||
{
|
||||
$coInfo = DB::Aowow()->select('SELECT `type` AS "0", `typeId` AS "1" FROM ?_comments WHERE `id` IN (?a) GROUP BY `type`, `typeId`', $this->_post['id']);
|
||||
foreach ($coInfo as [$type, $typeId])
|
||||
if ($tbl = Type::getClassAttrib($type, 'dataTable'))
|
||||
DB::Aowow()->query('UPDATE ?# SET `cuFlags` = `cuFlags` | ?d WHERE `id` = ?d', $tbl, CUSTOM_HAS_COMMENT, $typeId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
trigger_error('CommentUndeleteResponse - user #'.User::$id.' could not unflag comment(s) #'.implode(', ', $this->_post['id']).' from deleted', E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
61
endpoints/comment/upvote-reply.php
Normal file
61
endpoints/comment/upvote-reply.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// expects non-200 header on error
|
||||
class CommentUpvotereplyResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedPOST = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertPOST('id'))
|
||||
{
|
||||
trigger_error('CommentUpvotereplyResponse - malformed request received', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'request malformed' : '');
|
||||
}
|
||||
|
||||
if (!User::canUpvote())
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'cannot upvote' : '');
|
||||
|
||||
$comment = DB::Aowow()->selectRow('SELECT `userId`, IF(`flags` & ?d, 1, 0) AS "deleted" FROM ?_comments WHERE `id` = ?d', CC_FLAG_DELETED, $this->_post['id']);
|
||||
if (!$comment)
|
||||
{
|
||||
trigger_error('CommentUpvotereplyResponse - comment #'.$this->_post['id'].' not found in db', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'replyID not found' : '');
|
||||
}
|
||||
|
||||
if (User::$id == $comment['userId']) // not worth logging?
|
||||
$this->generate404('LANG.voteself_tip');
|
||||
|
||||
if ($comment['deleted'])
|
||||
$this->generate404('LANG.votedeleted_tip');
|
||||
|
||||
$ok = DB::Aowow()->query(
|
||||
'INSERT INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)',
|
||||
RATING_COMMENT,
|
||||
$this->_post['id'],
|
||||
User::$id,
|
||||
User::canSupervote() ? 2 : 1
|
||||
);
|
||||
|
||||
if (!$ok)
|
||||
{
|
||||
trigger_error('CommentUpvotereplyResponse - write to db failed', E_USER_ERROR);
|
||||
$this->generate404(User::isInGroup(U_GROUP_STAFF) ? 'write to db failed' : '');
|
||||
}
|
||||
|
||||
Util::gainSiteReputation($comment['userId'], SITEREP_ACTION_UPVOTED, ['id' => $this->_post['id'], 'voterId' => User::$id]);
|
||||
User::decrementDailyVotes();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
84
endpoints/comment/vote.php
Normal file
84
endpoints/comment/vote.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
// up, down and remove
|
||||
class CommentVoteResponse extends TextResponse
|
||||
{
|
||||
protected bool $requiresLogin = true;
|
||||
|
||||
protected array $expectedGET = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT ],
|
||||
'rating' => ['filter' => FILTER_VALIDATE_INT, 'options' => ['min_range' => -2, 'max_range' => 2]]
|
||||
);
|
||||
|
||||
protected function generate(): void
|
||||
{
|
||||
if (!$this->assertGET('id', 'rating'))
|
||||
{
|
||||
trigger_error('CommentVoteResponse - malformed request received', E_USER_ERROR);
|
||||
$this->result = Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (User::getCurrentDailyVotes() <= 0)
|
||||
{
|
||||
$this->result = Util::toJSON(['error' => 1, 'message' => Lang::main('tooManyVotes')]);
|
||||
return;
|
||||
}
|
||||
|
||||
$target = DB::Aowow()->selectRow(
|
||||
'SELECT c.`userId` AS "owner", ur.`value`, IF(c.`flags` & ?d, 1, 0) AS "deleted" FROM ?_comments c LEFT JOIN ?_user_ratings ur ON ur.`type` = ?d AND ur.`entry` = c.id AND ur.`userId` = ?d WHERE c.id = ?d',
|
||||
CC_FLAG_DELETED, RATING_COMMENT, User::$id, $this->_get['id']
|
||||
);
|
||||
if (!$target)
|
||||
{
|
||||
trigger_error('CommentVoteResponse - target comment #'.$this->_get['id'].' not found', E_USER_ERROR);
|
||||
$this->result = Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
return;
|
||||
}
|
||||
|
||||
$val = User::canSupervote() ? 2 : 1;
|
||||
if ($this->_get['rating'] < 0)
|
||||
$val *= -1;
|
||||
|
||||
if (User::$id == $target['owner'] || $val != $this->_get['rating'] || $target['deleted'])
|
||||
{
|
||||
// circumvented the checks in JS
|
||||
$this->result = Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (($val > 0 && !User::canUpvote()) || ($val < 0 && !User::canDownvote()))
|
||||
{
|
||||
$this->result = Util::toJSON(['error' => 1, 'message' => Lang::main('bannedRating')]);
|
||||
return;
|
||||
}
|
||||
|
||||
$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 ?_user_ratings WHERE `type` = ?d AND `entry` = ?d AND `userId` = ?d', RATING_COMMENT, $this->_get['id'], User::$id);
|
||||
else // replace, because we may be overwriting an old, opposing vote
|
||||
if ($ok = DB::Aowow()->query('REPLACE INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)', RATING_COMMENT, $this->_get['id'], User::$id, $val))
|
||||
User::decrementDailyVotes(); // do not refund retracted votes!
|
||||
|
||||
if ($ok)
|
||||
{
|
||||
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]);
|
||||
|
||||
$this->result = Util::toJSON(['error' => 0]);
|
||||
}
|
||||
else
|
||||
$this->result = Util::toJSON(['error' => 1, 'message' => Lang::main('intError')]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
42
endpoints/go-to-comment/go-to-comment.php
Normal file
42
endpoints/go-to-comment/go-to-comment.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class GotocommentBaseResponse extends TextResponse
|
||||
{
|
||||
protected ?string $redirectTo = '.'; // go home, you're drunk
|
||||
protected array $expectedGET = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertGET('id'))
|
||||
{
|
||||
trigger_error('GotocommentBaseResponse - malformed request received', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// type <> 0 AND typeId <> 0 AND replyTo = 0 for comments
|
||||
$comment = DB::Aowow()->selectRow('SELECT `id`, `type`, `typeId` FROM ?_comments WHERE `replyTo` = 0 AND `id` = ?d', $this->_get['id']);
|
||||
if (!$comment)
|
||||
{
|
||||
trigger_error('GotocommentBaseResponse - comment #'.$this->_get['id'].' not found', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Type::validateIds($comment['type'], $comment['typeId']))
|
||||
{
|
||||
trigger_error('GotocommentBaseResponse - comment #'.$this->_get['id'].' belongs to nonexistent type/typeID combo '.$comment['type'].'/'.$comment['typeId'], E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->redirectTo = sprintf('?%s=%d#comments:id=%d', Type::getFileString($comment['type']), $comment['typeId'], $comment['id']);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
42
endpoints/go-to-reply/go-to-reply.php
Normal file
42
endpoints/go-to-reply/go-to-reply.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
|
||||
class GotoreplyBaseResponse extends TextResponse
|
||||
{
|
||||
protected ?string $redirectTo = '.'; // go home, you're drunk
|
||||
protected array $expectedGET = array(
|
||||
'id' => ['filter' => FILTER_VALIDATE_INT]
|
||||
);
|
||||
|
||||
protected function generate() : void
|
||||
{
|
||||
if (!$this->assertGET('id'))
|
||||
{
|
||||
trigger_error('GotoreplyBaseResponse - malformed request received', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// type = typeId = 0 AND replyTo <> 0 for replies
|
||||
$reply = DB::Aowow()->selectRow('SELECT c.`id`, r.`id` AS "reply", c.`type`, c.`typeId` FROM ?_comments r JOIN ?_comments c ON r.`replyTo` = c.`id` WHERE r.`id` = ?d', $this->_get['id']);
|
||||
if (!$reply)
|
||||
{
|
||||
trigger_error('GotoreplyBaseResponse - reply #'.$this->_get['id'].' not found', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Type::validateIds($reply['type'], $reply['typeId']))
|
||||
{
|
||||
trigger_error('GotoreplyBaseResponse - parent comment #'.$reply['id'].' belongs to nonexistent type/typeID combo '.$reply['type'].'/'.$reply['typeId'], E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->redirectTo = sprintf('?%s=%d#comments:id=%d:reply=%d', Type::getFileString($reply['type']), $reply['typeId'], $reply['id'], $reply['reply']);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,485 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal 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' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkIdListUnsigned'],
|
||||
'body' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkTextBlob' ],
|
||||
'commentbody' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkTextBlob' ],
|
||||
'response' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkTextBlob' ],
|
||||
'reason' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkTextBlob' ],
|
||||
'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
|
||||
'commentId' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
|
||||
'replyId' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
|
||||
'sticky' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
|
||||
// 'username' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkTextLine' ]
|
||||
);
|
||||
|
||||
protected $_get = array(
|
||||
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkInt'],
|
||||
'type' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkInt'],
|
||||
'typeid' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkInt'],
|
||||
'rating' => ['filter' => FILTER_SANITIZE_NUMBER_INT ]
|
||||
);
|
||||
|
||||
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() : string
|
||||
{
|
||||
if (!$this->_get['typeid'] || !$this->_get['type'] || !Type::exists($this->_get['type']))
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentAdd - malforemd request received', E_USER_ERROR);
|
||||
return ''; // whatever, we cant even send him back
|
||||
}
|
||||
|
||||
// this type cannot be commented on
|
||||
if (!Type::checkClassAttrib($this->_get['type'], 'contribute', CONTRIBUTE_CO))
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentAdd - tried to comment on unsupported type #'.$this->_get['type'], E_USER_ERROR);
|
||||
return '';
|
||||
}
|
||||
|
||||
// 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())
|
||||
{
|
||||
if (!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 ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, 0, 1)', RATING_COMMENT, $postIdx);
|
||||
|
||||
// flag target with hasComment
|
||||
if ($tbl = Type::getClassAttrib($this->_get['type'], 'dataTable'))
|
||||
DB::Aowow()->query('UPDATE '.$tbl.' SET cuFlags = cuFlags | ?d WHERE id = ?d', CUSTOM_HAS_COMMENT, $this->_get['typeid']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$_SESSION['error']['co'] = Lang::main('intError');
|
||||
trigger_error('AjaxComment::handleCommentAdd - write to db failed', E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
else
|
||||
$_SESSION['error']['co'] = Lang::main('textLength', [mb_strlen($this->_post['commentbody']), self::COMMENT_LENGTH_MIN, self::COMMENT_LENGTH_MAX]);
|
||||
}
|
||||
else
|
||||
$_SESSION['error']['co'] = Lang::main('cannotComment');
|
||||
|
||||
$this->doRedirect = true;
|
||||
|
||||
$idOrUrl = $this->_get['typeid'];
|
||||
if ($this->_get['type'] == Type::GUIDE)
|
||||
if ($_ = DB::Aowow()->selectCell('SELECT `url` FROM ?_guides WHERE `id` = ?d', $this->_get['typeid']))
|
||||
$idOrUrl = $_;
|
||||
|
||||
return '?'.Type::getFileString($this->_get['type']).'='.$idOrUrl.'#comments';
|
||||
}
|
||||
|
||||
protected function handleCommentEdit() : void
|
||||
{
|
||||
if (!User::canComment() && !User::isInGroup(U_GROUP_MODERATOR))
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentEdit - user #'.User::$id.' not allowed to edit', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->_get['id'] || !$this->_post['body'])
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentEdit - malforemd request received', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mb_strlen($this->_post['body']) < self::COMMENT_LENGTH_MIN)
|
||||
return; // no point in reporting this trifle
|
||||
|
||||
// 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() : void
|
||||
{
|
||||
if (!$this->_post['id'] || !User::isLoggedIn())
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentDelete - commentId empty or user not logged in', E_USER_ERROR);
|
||||
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()->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']
|
||||
);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected function handleCommentUndelete() : void
|
||||
{
|
||||
if (!$this->_post['id'] || !User::isLoggedIn())
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentUndelete - commentId empty or user not logged in', E_USER_ERROR);
|
||||
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()->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);
|
||||
}
|
||||
|
||||
protected function handleCommentRating() : string
|
||||
{
|
||||
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 ?_user_ratings WHERE `type` = ?d AND `entry` = ?d AND userId <> 0 GROUP BY `entry`', RATING_COMMENT, $this->_get['id']))
|
||||
return Util::toJSON($votes);
|
||||
else
|
||||
return Util::toJSON(['success' => 1, 'up' => 0, 'down' => 0]);
|
||||
}
|
||||
|
||||
protected function handleCommentVote() : string
|
||||
{
|
||||
if (!User::isLoggedIn() || !$this->_get['id'] || !$this->_get['rating'])
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
|
||||
$target = DB::Aowow()->selectRow('SELECT c.`userId` AS owner, ur.`value` FROM ?_comments c LEFT JOIN ?_user_ratings ur ON ur.`type` = ?d AND ur.`entry` = c.id AND ur.`userId` = ?d WHERE c.id = ?d', RATING_COMMENT, User::$id, $this->_get['id']);
|
||||
$val = User::canSupervote() ? 2 : 1;
|
||||
if ($this->_get['rating'] < 0)
|
||||
$val *= -1;
|
||||
|
||||
if (User::getCurrentDailyVotes() <= 0)
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('tooManyVotes')]);
|
||||
else if (!$target || $val != $this->_get['rating'])
|
||||
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);
|
||||
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 ?_user_ratings WHERE `type` = ?d AND `entry` = ?d AND `userId` = ?d', RATING_COMMENT, $this->_get['id'], User::$id);
|
||||
else // replace, because we may be overwriting an old, opposing vote
|
||||
if ($ok = DB::Aowow()->query('REPLACE INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)', RATING_COMMENT, (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() : void
|
||||
{
|
||||
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentSticky - commentId empty or user #'.User::$id.' not moderator', E_USER_ERROR);
|
||||
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() : string
|
||||
{
|
||||
$this->contentType = MIME_TYPE_TEXT;
|
||||
|
||||
if (!$this->_post['id'])
|
||||
{
|
||||
trigger_error('AjaxComment::handleCommentOutOfDate - commentId empty', E_USER_ERROR);
|
||||
return Lang::main('intError');
|
||||
}
|
||||
|
||||
$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 | ?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]);
|
||||
else
|
||||
$ok = DB::Aowow()->query('UPDATE ?_comments SET flags = flags & ~?d WHERE id = ?d', CC_FLAG_OUTDATED, $this->_post['id'][0]);
|
||||
}
|
||||
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 (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);
|
||||
|
||||
return Lang::main('intError');
|
||||
}
|
||||
|
||||
protected function handleCommentShowReplies() : string
|
||||
{
|
||||
return Util::toJSON(!$this->_get['id'] ? [] : CommunityContent::getCommentReplies($this->_get['id']));
|
||||
}
|
||||
|
||||
protected function handleReplyAdd() : string
|
||||
{
|
||||
$this->contentType = MIME_TYPE_TEXT;
|
||||
|
||||
if (!User::canComment())
|
||||
return Lang::main('cannotComment');
|
||||
|
||||
if (!$this->_post['commentId'] || !DB::Aowow()->selectCell('SELECT 1 FROM ?_comments WHERE id = ?d', $this->_post['commentId']))
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyAdd - comment #'.$this->_post['commentId'].' does not exist', E_USER_ERROR);
|
||||
return Lang::main('intError');
|
||||
}
|
||||
|
||||
if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
|
||||
return Lang::main('textLength', [mb_strlen($this->_post['body']), self::REPLY_LENGTH_MIN, self::REPLY_LENGTH_MAX]);
|
||||
|
||||
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']));
|
||||
|
||||
trigger_error('AjaxComment::handleReplyAdd - write to db failed', E_USER_ERROR);
|
||||
return Lang::main('intError');
|
||||
}
|
||||
|
||||
protected function handleReplyEdit() : string
|
||||
{
|
||||
$this->contentType = MIME_TYPE_TEXT;
|
||||
|
||||
if (!User::canComment())
|
||||
return Lang::main('cannotComment');
|
||||
|
||||
if ((!$this->_post['replyId'] || !$this->_post['commentId']) && DB::Aowow()->selectCell('SELECT COUNT(1) FROM ?_comments WHERE id IN (?a)', [$this->_post['replyId'], $this->_post['commentId']]))
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyEdit - comment #'.$this->_post['commentId'].' or reply #'.$this->_post['replyId'].' does not exist', E_USER_ERROR);
|
||||
return Lang::main('intError');
|
||||
}
|
||||
|
||||
if (!$this->_post['body'] || mb_strlen($this->_post['body']) < self::REPLY_LENGTH_MIN || mb_strlen($this->_post['body']) > self::REPLY_LENGTH_MAX)
|
||||
return Lang::main('textLength', [mb_strlen($this->_post['body']), self::REPLY_LENGTH_MIN, 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']));
|
||||
|
||||
trigger_error('AjaxComment::handleReplyEdit - write to db failed', E_USER_ERROR);
|
||||
return Lang::main('intError');
|
||||
}
|
||||
|
||||
protected function handleReplyDetach() : void
|
||||
{
|
||||
if (!$this->_post['id'] || !User::isInGroup(U_GROUP_MODERATOR))
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyDetach - commentId empty or user #'.User::$id.' not moderator', E_USER_ERROR);
|
||||
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() : void
|
||||
{
|
||||
if (!User::isLoggedIn() || !$this->_post['id'])
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyDelete - commentId empty or user not logged in', E_USER_ERROR);
|
||||
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 ?_user_ratings WHERE `type` = ?d AND `entry` = ?d', RATING_COMMENT, $this->_post['id'][0]);
|
||||
else
|
||||
trigger_error('AjaxComment::handleReplyDelete - deleting comment #'.$this->_post['id'][0].' by user #'.User::$id.' from db failed', E_USER_ERROR);
|
||||
}
|
||||
|
||||
protected function handleReplyFlag() : void
|
||||
{
|
||||
if (!User::isLoggedIn() || !$this->_post['id'])
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyFlag - commentId empty or user not logged in', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$report = new Report(Report::MODE_COMMENT, Report::CO_INAPPROPRIATE, $this->_post['id'][0]);
|
||||
$report->create('Report Reply Button Click');
|
||||
}
|
||||
|
||||
protected function handleReplyUpvote() : void
|
||||
{
|
||||
if (!$this->_post['id'] || !User::canUpvote())
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyUpvote - commentId empty or user not allowed to vote', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
||||
if (!$owner)
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyUpvote - comment #'.$this->_post['id'][0].' not found in db', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$ok = DB::Aowow()->query(
|
||||
'INSERT INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)',
|
||||
RATING_COMMENT,
|
||||
$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();
|
||||
}
|
||||
else
|
||||
trigger_error('AjaxComment::handleReplyUpvote - write to db failed', E_USER_ERROR);
|
||||
}
|
||||
|
||||
protected function handleReplyDownvote() : void
|
||||
{
|
||||
if (!$this->_post['id'] || !User::canDownvote())
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyDownvote - commentId empty or user not allowed to vote', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$owner = DB::Aowow()->selectCell('SELECT userId FROM ?_comments WHERE id = ?d', $this->_post['id'][0]);
|
||||
if (!$owner)
|
||||
{
|
||||
trigger_error('AjaxComment::handleReplyDownvote - comment #'.$this->_post['id'][0].' not found in db', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
$ok = DB::Aowow()->query(
|
||||
'INSERT INTO ?_user_ratings (`type`, `entry`, `userId`, `value`) VALUES (?d, ?d, ?d, ?d)',
|
||||
RATING_COMMENT,
|
||||
$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();
|
||||
}
|
||||
else
|
||||
trigger_error('AjaxComment::handleReplyDownvote - write to db failed', E_USER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Aowow;
|
||||
|
||||
if (!defined('AOWOW_REVISION'))
|
||||
die('illegal access');
|
||||
|
||||
class AjaxGotocomment extends AjaxHandler
|
||||
{
|
||||
protected $_get = array(
|
||||
'id' => ['filter' => FILTER_CALLBACK, 'options' => 'Aowow\AjaxHandler::checkInt']
|
||||
);
|
||||
|
||||
public function __construct(array $params)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
// always this one
|
||||
$this->handler = 'handleGoToComment';
|
||||
$this->doRedirect = true;
|
||||
}
|
||||
|
||||
/* responses
|
||||
header()
|
||||
*/
|
||||
protected function handleGoToComment() : string
|
||||
{
|
||||
if (!$this->_get['id'])
|
||||
return '.'; // go home
|
||||
|
||||
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 '?'.Type::getFileString(intVal($_['type'])).'='.$_['typeId'].'#comments:id='.$_['id'].($_['id'] != $this->_get['id'] ? ':reply='.$this->_get['id'] : null);
|
||||
else
|
||||
trigger_error('AjaxGotocomment::handleGoToComment - could not find comment #'.$this->_get['id'], E_USER_ERROR);
|
||||
|
||||
return '.';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -20,6 +20,14 @@ if (!defined('AOWOW_REVISION'))
|
||||
|
||||
class CommunityContent
|
||||
{
|
||||
public const /* int */ COMMENT_LENGTH_MIN = 10;
|
||||
public const /* int */ COMMENT_LENGTH_MAX = 7500;
|
||||
public const /* int */ REPLY_LENGTH_MIN = 15;
|
||||
public const /* int */ REPLY_LENGTH_MAX = 600;
|
||||
|
||||
public const /* int */ REPORT_THRESHOLD_AUTO_DELETE = 10;
|
||||
public const /* int */ REPORT_THRESHOLD_AUTO_OUT_OF_DATE = 5;
|
||||
|
||||
private static array $jsGlobals = [];
|
||||
private static array $subjCache = [];
|
||||
|
||||
@@ -63,7 +71,7 @@ class CommunityContent
|
||||
FROM ?_videos v
|
||||
LEFT JOIN ?_account a ON v.`userIdOwner` = a.`id`
|
||||
WHERE { v.`userIdOwner` = ?d AND }{ v.`type` = ? AND }{ v.`typeId` = ? AND } v.`status` & ?d AND (v.`status` & ?d) = 0
|
||||
{ ORDER BY ?# DESC }
|
||||
{ ORDER BY ?# ASC }
|
||||
{ LIMIT ?d }';
|
||||
|
||||
private static string $previewQuery =
|
||||
@@ -117,17 +125,19 @@ class CommunityContent
|
||||
*/
|
||||
|
||||
// add default values
|
||||
$opt += ['user' => 0, 'unrated' => 0, 'comments' => 0, 'replies' => 0];
|
||||
$opt += ['user' => 0, 'unrated' => 0, 'comments' => 0, 'replies' => 0, 'flags' => 0];
|
||||
|
||||
$w = [];
|
||||
if ($opt['user'])
|
||||
$w[] = sprintf('c.userId = %d AND', $opt['user']);
|
||||
$w[] = sprintf('c.`userId` = %d AND', $opt['user']);
|
||||
if ($opt['unrated'])
|
||||
$w[] = 'ur.entry IS NULL AND';
|
||||
$w[] = 'ur.`entry` IS NULL AND';
|
||||
if ($opt['flags'])
|
||||
$w[] = sprintf('(c.`flags` & %d) > 0 AND', $opt['flags']);
|
||||
if ($opt['comments'] && !$opt['replies'])
|
||||
$w[] = 'c.replyTo = 0 AND';
|
||||
$w[] = 'c.`replyTo` = 0 AND';
|
||||
else if (!$opt['comments'] && $opt['replies'])
|
||||
$w[] = 'c.replyTo <> 0 AND';
|
||||
$w[] = 'c.`replyTo` <> 0 AND';
|
||||
// else
|
||||
// pick both and no extra constraint needed for that
|
||||
|
||||
@@ -178,7 +188,7 @@ class CommunityContent
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error('Comment '.$c['id'].' belongs to nonexistant subject.', E_USER_NOTICE);
|
||||
trigger_error('Comment '.$c['id'].' belongs to nonexistent subject.', E_USER_NOTICE);
|
||||
unset($comments[$idx]);
|
||||
}
|
||||
}
|
||||
@@ -335,7 +345,7 @@ class CommunityContent
|
||||
{
|
||||
if (empty($p['name']))
|
||||
{
|
||||
trigger_error('Screenshot linked to nonexistant type/typeId combination: '.$p['type'].'/'.$p['typeId'], E_USER_NOTICE);
|
||||
trigger_error('Screenshot linked to nonexistent type/typeId combination: '.$p['type'].'/'.$p['typeId'], E_USER_NOTICE);
|
||||
unset($p);
|
||||
}
|
||||
else
|
||||
@@ -417,7 +427,7 @@ class CommunityContent
|
||||
$typeOrUser > 0 ? $typeId : DBSIMPLE_SKIP,
|
||||
CC_FLAG_APPROVED,
|
||||
CC_FLAG_DELETED,
|
||||
!$typeOrUser ? 'date' : DBSIMPLE_SKIP,
|
||||
!$typeOrUser ? 'date' : 'pos',
|
||||
!$typeOrUser ? Cfg::get('SQL_LIMIT_SEARCH') : DBSIMPLE_SKIP
|
||||
);
|
||||
|
||||
@@ -431,7 +441,7 @@ class CommunityContent
|
||||
$typeOrUser > 0 ? $typeId : DBSIMPLE_SKIP,
|
||||
CC_FLAG_APPROVED,
|
||||
CC_FLAG_DELETED,
|
||||
!$typeOrUser ? 'date' : DBSIMPLE_SKIP,
|
||||
!$typeOrUser ? 'date' : 'pos',
|
||||
DBSIMPLE_SKIP
|
||||
);
|
||||
|
||||
|
||||
@@ -3244,7 +3244,6 @@ var LANG = {
|
||||
upvote_tip: "Dieser Kommentat ist hilfreich (klickt, um rückgängig zu machen)",
|
||||
upvoted_tip: "Ihr habt diesen Kommentar positiv bewertet; klickt, um dies rückgängig zu machen",
|
||||
downvote_tip: "Dieser Kommentar ist nicht hilfreich (klickt, um rückgängig zu machen)",
|
||||
downvote_tip: "Dieser Kommentar ist nicht hilfreich (klickt, um rückgängig zu machen)",
|
||||
commentdeleted_tip: "Dieser Kommentar wurde gelöscht; er kann nur noch von Euch und Morderatoren gesehen werden.",
|
||||
addreply: "Antwort hinzufügen",
|
||||
replylength1_format: "Gebt mindestens $1 Zeichen ein",
|
||||
|
||||
@@ -3293,7 +3293,6 @@ var LANG = {
|
||||
upvote_tip: "This comment is helpful (click again to undo)",
|
||||
upvoted_tip: "You have upvoted this comment; click again to undo",
|
||||
downvote_tip: "This comment is not helpful (click again to undo)",
|
||||
downvote_tip: "This comment is not helpful (click again to undo)",
|
||||
commentdeleted_tip: "This comment has been deleted; it is now visible only to you and to moderators.",
|
||||
addreply: "Add reply",
|
||||
replylength1_format: "Enter at least $1 characters",
|
||||
|
||||
@@ -3244,7 +3244,6 @@ var LANG = {
|
||||
upvote_tip: "Este comentario es útil (haz clic de nuevo para deshacer)",
|
||||
upvoted_tip: "Has dado este comentario una valoración positiva; haz clic de nuevo para deshacerla.",
|
||||
downvote_tip: "Este comentario no es útil (haz clic de nuevo para deshacer)",
|
||||
downvote_tip: "Este comentario no es útil (haz clic de nuevo para deshacer)",
|
||||
commentdeleted_tip: "Este comentario ha sido borrado; ahora sólo les es visible a ti y a los moderadores.",
|
||||
addreply: "Añadir respuesta",
|
||||
replylength1_format: "Introduce al menos $1 caracteres",
|
||||
|
||||
@@ -3245,7 +3245,6 @@ var LANG = {
|
||||
upvote_tip: "Ce commentaire est utile (cliquez à nouveau pour annuler)",
|
||||
upvoted_tip: "Vous avez émis un vote positif pour ce commentaire ; cliquez à nouveau pour annuler",
|
||||
downvote_tip: "Ce commentaire n'est pas utile (cliquez à nouveau pour annuler)",
|
||||
downvote_tip: "Ce commentaire n'est pas utile (cliquez à nouveau pour annuler)",
|
||||
commentdeleted_tip: "Ce commentaire a été effacé ; il n'est plus visible que par vous et par les modérateurs.",
|
||||
addreply: "Ajouter une réponse",
|
||||
replylength1_format: "Entrez au moins $1 caractères",
|
||||
|
||||
@@ -3245,7 +3245,6 @@ var LANG = {
|
||||
upvote_tip: "Этот комментарий полезен (нажмите еще раз, чтобы отменить)",
|
||||
upvoted_tip: "Вы проголосовали за повышение этого комментария, нажмите снова для отмены",
|
||||
downvote_tip: "Этот комментарий бесполезен (нажмите снова для отмены)",
|
||||
downvote_tip: "Этот комментарий бесполезен (нажмите снова для отмены)",
|
||||
commentdeleted_tip: "Этот комментарий был удален, теперь он видим только вам и модераторам.",
|
||||
addreply: "Ответить",
|
||||
replylength1_format: "Введите еще по меньшей мере $1 символов",
|
||||
|
||||
@@ -27,7 +27,9 @@ var _ = [
|
||||
return true;
|
||||
};
|
||||
|
||||
let a = $WH.ce('a');
|
||||
td.onclick = $WH.sp;
|
||||
|
||||
let a = $WH.ce('span');
|
||||
a.style.fontFamily = 'Verdana, sans-serif';
|
||||
a.style.marginLeft = '10px';
|
||||
a.href = '#';
|
||||
|
||||
Reference in New Issue
Block a user