mirror of
https://github.com/BillyOutlast/UNIT3D.git
synced 2026-02-06 12:11:21 +01:00
fix: types for livewire comments
This commit is contained in:
@@ -28,6 +28,12 @@ use App\Achievements\UserMade800Comments;
|
||||
use App\Achievements\UserMade900Comments;
|
||||
use App\Achievements\UserMadeComment;
|
||||
use App\Achievements\UserMadeTenComments;
|
||||
use App\Models\Article;
|
||||
use App\Models\Collection;
|
||||
use App\Models\Playlist;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\TorrentRequest;
|
||||
use App\Models\User;
|
||||
use App\Notifications\NewComment;
|
||||
use App\Notifications\NewCommentTag;
|
||||
@@ -35,7 +41,6 @@ use App\Repositories\ChatRepository;
|
||||
use App\Traits\CastLivewireProperties;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Livewire\Component;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
class Comment extends Component
|
||||
{
|
||||
@@ -43,31 +48,28 @@ class Comment extends Component
|
||||
|
||||
protected ChatRepository $chatRepository;
|
||||
|
||||
public $comment;
|
||||
public null|Article|Collection|Playlist|Ticket|Torrent|TorrentRequest $model;
|
||||
|
||||
public \App\Models\Comment $comment;
|
||||
|
||||
public bool $anon = false;
|
||||
|
||||
public ?User $user;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $listeners = [
|
||||
'refresh' => '$refresh',
|
||||
];
|
||||
|
||||
protected $validationAttributes = [
|
||||
'replyState.content' => 'reply',
|
||||
];
|
||||
public bool $isReplying = false;
|
||||
|
||||
public $isReplying = false;
|
||||
public string $replyState = '';
|
||||
|
||||
public $replyState = [
|
||||
'content' => '',
|
||||
];
|
||||
public bool $isEditing = false;
|
||||
|
||||
public $isEditing = false;
|
||||
|
||||
public $editState = [
|
||||
'content' => '',
|
||||
];
|
||||
public string $editState = '';
|
||||
|
||||
final public function boot(ChatRepository $chatRepository): void
|
||||
{
|
||||
@@ -84,93 +86,93 @@ class Comment extends Component
|
||||
$this->castLivewireProperties($field, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
final public function taggedUsers(): array
|
||||
{
|
||||
preg_match_all('/@([\w\-]+)/', implode('', $this->editState), $matches);
|
||||
preg_match_all('/@([\w\-]+)/', $this->editState, $matches);
|
||||
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
final public function updatedIsEditing($isEditing): void
|
||||
final public function updatedIsEditing(bool $isEditing): void
|
||||
{
|
||||
if (!$isEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->editState = [
|
||||
'content' => $this->comment->content,
|
||||
];
|
||||
$this->editState = $this->comment->content;
|
||||
}
|
||||
|
||||
final public function editComment(): void
|
||||
{
|
||||
if (auth()->id() == $this->comment->user_id || auth()->user()->group->is_modo) {
|
||||
$this->comment->update((new AntiXSS())->xss_clean($this->editState));
|
||||
$this->isEditing = false;
|
||||
} else {
|
||||
$this->dispatch('error', type: 'error', message: 'Permission Denied!');
|
||||
}
|
||||
abort_unless(auth()->id() === $this->comment->user_id || auth()->user()->group->is_modo, 403);
|
||||
|
||||
$this->validate([
|
||||
'editState' => 'required'
|
||||
]);
|
||||
|
||||
$this->comment->update([
|
||||
'content' => $this->editState,
|
||||
]);
|
||||
|
||||
$this->isEditing = false;
|
||||
}
|
||||
|
||||
final public function deleteComment(): void
|
||||
{
|
||||
if ((auth()->id() == $this->comment->user_id || auth()->user()->group->is_modo) && $this->comment->children()->doesntExist()) {
|
||||
$this->comment->delete();
|
||||
$this->dispatch('refresh');
|
||||
} else {
|
||||
$this->dispatch('error', type: 'error', message: 'Permission Denied!');
|
||||
}
|
||||
abort_unless((auth()->id() === $this->comment->user_id || auth()->user()->group->is_modo), 403, 'Permission Denied!');
|
||||
|
||||
abort_if($this->comment->children()->exists(), 403);
|
||||
|
||||
$this->comment->delete();
|
||||
}
|
||||
|
||||
final public function postReply(): void
|
||||
{
|
||||
// Set Polymorphic Model Name
|
||||
$modelName = str()->snake(class_basename($this->comment->commentable_type), ' ');
|
||||
abort_if(!$this->model instanceof Ticket && auth()->user()->can_comment === false, 403, __('comment.rights-revoked'));
|
||||
|
||||
if ($modelName !== 'ticket' && auth()->user()->can_comment === false) {
|
||||
$this->dispatch('error', type: 'error', message: __('comment.rights-revoked'));
|
||||
abort_if($this->model instanceof Torrent && $this->model->status !== Torrent::APPROVED, 403, __('comment.torrent-status'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->comment->isParent()) {
|
||||
return;
|
||||
}
|
||||
abort_if($this->comment->isChild(), 403);
|
||||
|
||||
$this->validate([
|
||||
'replyState.content' => 'required',
|
||||
'replyState' => 'required',
|
||||
'anon' => 'bool',
|
||||
]);
|
||||
|
||||
$reply = $this->comment->children()->make((new AntiXSS())->xss_clean($this->replyState));
|
||||
$reply->user()->associate(auth()->user());
|
||||
$reply->commentable()->associate($this->comment->commentable);
|
||||
$reply->anon = $this->anon;
|
||||
$reply->save();
|
||||
$reply = $this->comment->children()->create([
|
||||
'content' => $this->replyState,
|
||||
'user_id' => auth()->id(),
|
||||
'commentable_id' => $this->model->id,
|
||||
'commentable_type' => \get_class($this->model),
|
||||
]);
|
||||
|
||||
// New Comment Notification
|
||||
switch ($modelName) {
|
||||
case 'ticket':
|
||||
$ticket = $this->comment->commentable;
|
||||
switch (true) {
|
||||
case $this->model instanceof Ticket:
|
||||
$ticket = $this->model;
|
||||
|
||||
if ($this->user->id !== $ticket->staff_id && $ticket->staff_id !== null) {
|
||||
User::find($ticket->staff_id)->notify(new NewComment($modelName, $reply));
|
||||
User::find($ticket->staff_id)->notify(new NewComment($this->model, $reply));
|
||||
}
|
||||
|
||||
if ($this->user->id !== $ticket->user_id) {
|
||||
User::find($ticket->user_id)->notify(new NewComment($modelName, $reply));
|
||||
User::find($ticket->user_id)->notify(new NewComment($this->model, $reply));
|
||||
}
|
||||
|
||||
if (!\in_array($this->comment->user_id, [$ticket->staff_id, $ticket->user_id, $this->user->id])) {
|
||||
User::find($this->comment->user_id)->notify(new NewComment($modelName, $reply));
|
||||
User::find($this->comment->user_id)->notify(new NewComment($this->model, $reply));
|
||||
}
|
||||
|
||||
break;
|
||||
case 'article':
|
||||
case 'playlist':
|
||||
case 'torrent request':
|
||||
case 'torrent':
|
||||
if ($this->user->id !== $this->comment->user_id) {
|
||||
User::find($this->comment->user_id)->notify(new NewComment($modelName, $reply));
|
||||
case $this->model instanceof Article:
|
||||
case $this->model instanceof Playlist:
|
||||
case $this->model instanceof TorrentRequest:
|
||||
case $this->model instanceof Torrent:
|
||||
if ($this->user->id !== $this->model->user_id) {
|
||||
User::find($this->model->user_id)?->notify(new NewComment($this->model, $reply));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -178,63 +180,53 @@ class Comment extends Component
|
||||
|
||||
// User Tagged Notification
|
||||
$users = User::whereIn('username', $this->taggedUsers())->get();
|
||||
Notification::sendNow($users, new NewCommentTag($modelName, $reply));
|
||||
Notification::sendNow($users, new NewCommentTag($this->model, $reply));
|
||||
|
||||
// Auto Shout
|
||||
$profileUrl = href_profile($this->user);
|
||||
if (!$this->model instanceof Ticket) {
|
||||
// Auto Shout
|
||||
$username = $reply->anon ? 'An anonymous user' : '[url='.href_profile($this->user).']'.$this->user->username.'[/url]';
|
||||
|
||||
$modelUrl = match ($modelName) {
|
||||
'article' => href_article($this->comment->commentable),
|
||||
'collection' => href_collection($this->comment->commentable),
|
||||
'playlist' => href_playlist($this->comment->commentable),
|
||||
'torrent request' => href_request($this->comment->commentable),
|
||||
'torrent' => href_torrent($this->comment->commentable),
|
||||
default => "#"
|
||||
};
|
||||
switch (true) {
|
||||
case $this->model instanceof Article:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Article [url='.href_article($this->model).']'.$this->model->title.'[/url]');
|
||||
|
||||
if ($modelName !== 'ticket') {
|
||||
if ($reply->anon == 0) {
|
||||
$this->chatRepository->systemMessage(
|
||||
sprintf(
|
||||
'[url=%s]%s[/url] has left a comment on '.$modelName.' [url=%s]%s[/url]',
|
||||
$profileUrl,
|
||||
$this->user->username,
|
||||
$modelUrl,
|
||||
$this->comment->commentable->name ?? $this->comment->commentable->title
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
sprintf(
|
||||
'An anonymous user has left a comment on '.$modelName.' [url=%s]%s[/url]',
|
||||
$modelUrl,
|
||||
$this->comment->commentable->name ?? $this->comment->commentable->title
|
||||
)
|
||||
);
|
||||
break;
|
||||
case $this->model instanceof Collection:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Collection [url='.href_collection($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
case $this->model instanceof Playlist:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Playlist [url='.href_playlist($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
case $this->model instanceof TorrentRequest:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Torrent Request [url='.href_request($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
case $this->model instanceof Torrent:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Torrent [url='.href_torrent($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if (!$reply->anon) {
|
||||
$this->user->unlock(new UserMadeComment());
|
||||
$this->user->addProgress(new UserMadeTenComments(), 1);
|
||||
$this->user->addProgress(new UserMade50Comments(), 1);
|
||||
$this->user->addProgress(new UserMade100Comments(), 1);
|
||||
$this->user->addProgress(new UserMade200Comments(), 1);
|
||||
$this->user->addProgress(new UserMade300Comments(), 1);
|
||||
$this->user->addProgress(new UserMade400Comments(), 1);
|
||||
$this->user->addProgress(new UserMade500Comments(), 1);
|
||||
$this->user->addProgress(new UserMade600Comments(), 1);
|
||||
$this->user->addProgress(new UserMade700Comments(), 1);
|
||||
$this->user->addProgress(new UserMade800Comments(), 1);
|
||||
$this->user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if ($reply->anon == 0 && $modelName !== 'ticket') {
|
||||
$this->user->unlock(new UserMadeComment());
|
||||
$this->user->addProgress(new UserMadeTenComments(), 1);
|
||||
$this->user->addProgress(new UserMade50Comments(), 1);
|
||||
$this->user->addProgress(new UserMade100Comments(), 1);
|
||||
$this->user->addProgress(new UserMade200Comments(), 1);
|
||||
$this->user->addProgress(new UserMade300Comments(), 1);
|
||||
$this->user->addProgress(new UserMade400Comments(), 1);
|
||||
$this->user->addProgress(new UserMade500Comments(), 1);
|
||||
$this->user->addProgress(new UserMade600Comments(), 1);
|
||||
$this->user->addProgress(new UserMade700Comments(), 1);
|
||||
$this->user->addProgress(new UserMade800Comments(), 1);
|
||||
$this->user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
$this->replyState = [
|
||||
'content' => '',
|
||||
];
|
||||
|
||||
$this->isReplying = false;
|
||||
$this->reset('replyState', 'isReplying');
|
||||
|
||||
$this->dispatch('refresh')->self();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,12 @@ use App\Achievements\UserMade800Comments;
|
||||
use App\Achievements\UserMade900Comments;
|
||||
use App\Achievements\UserMadeComment;
|
||||
use App\Achievements\UserMadeTenComments;
|
||||
use App\Models\Article;
|
||||
use App\Models\Collection;
|
||||
use App\Models\Playlist;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\TorrentRequest;
|
||||
use App\Models\User;
|
||||
use App\Notifications\NewComment;
|
||||
use App\Notifications\NewCommentTag;
|
||||
@@ -36,9 +41,9 @@ use App\Repositories\ChatRepository;
|
||||
use App\Traits\CastLivewireProperties;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
class Comments extends Component
|
||||
{
|
||||
@@ -50,22 +55,27 @@ class Comments extends Component
|
||||
|
||||
public ?User $user;
|
||||
|
||||
public $model;
|
||||
public null|Article|Collection|Playlist|Ticket|Torrent|TorrentRequest $model;
|
||||
|
||||
public bool $anon = false;
|
||||
|
||||
public int $perPage = 10;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $listeners = [
|
||||
'refresh' => '$refresh',
|
||||
];
|
||||
|
||||
public $newCommentState = [
|
||||
'content' => '',
|
||||
];
|
||||
#[Validate('required')]
|
||||
public string $newCommentState = '';
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $validationAttributes = [
|
||||
'newCommentState.content' => 'comment',
|
||||
'newCommentState' => 'comment',
|
||||
];
|
||||
|
||||
final public function boot(ChatRepository $chatRepository): void
|
||||
@@ -83,9 +93,12 @@ class Comments extends Component
|
||||
$this->castLivewireProperties($field, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
final public function taggedUsers(): array
|
||||
{
|
||||
preg_match_all('/@([\w\-]+)/', implode('', $this->newCommentState), $matches);
|
||||
preg_match_all('/@([\w\-]+)/', $this->newCommentState, $matches);
|
||||
|
||||
return $matches[1];
|
||||
}
|
||||
@@ -98,50 +111,39 @@ class Comments extends Component
|
||||
/// TODO: Find a better data structure to avoid this mess of exception cases
|
||||
final public function postComment(): void
|
||||
{
|
||||
// Set Polymorhic Model Name
|
||||
$modelName = str()->snake(class_basename($this->model), ' ');
|
||||
// Authorization
|
||||
abort_if(!$this->model instanceof Ticket && $this->user->can_comment === false, 403, __('comment.rights-revoked'));
|
||||
|
||||
if ($modelName !== 'ticket' && $this->user->can_comment === false) {
|
||||
$this->dispatch('error', type: 'error', message: __('comment.rights-revoked'));
|
||||
abort_if($this->model instanceof Torrent && $this->model->status !== Torrent::APPROVED, 403, __('comment.torrent-status'));
|
||||
|
||||
return;
|
||||
}
|
||||
// Validation
|
||||
$this->validate();
|
||||
|
||||
if (strtolower(class_basename($this->model)) === 'torrent' && $this->model->status !== Torrent::APPROVED) {
|
||||
$this->dispatch('error', type: 'error', message: __('comment.torrent-status'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->validate([
|
||||
'newCommentState.content' => 'required',
|
||||
$comment = $this->model->comments()->create([
|
||||
'content' => $this->newCommentState,
|
||||
'user_id' => auth()->id(),
|
||||
]);
|
||||
|
||||
$comment = $this->model->comments()->make((new AntiXSS())->xss_clean($this->newCommentState));
|
||||
$comment->user()->associate($this->user);
|
||||
$comment->anon = $this->anon;
|
||||
$comment->save();
|
||||
|
||||
// New Comment Notification
|
||||
switch ($modelName) {
|
||||
case 'ticket':
|
||||
switch (true) {
|
||||
case $this->model instanceof Ticket:
|
||||
$ticket = $this->model;
|
||||
|
||||
if ($this->user->id !== $ticket->staff_id && $ticket->staff_id !== null) {
|
||||
User::find($ticket->staff_id)->notify(new NewComment($modelName, $comment));
|
||||
User::find($ticket->staff_id)?->notify(new NewComment($this->model, $comment));
|
||||
}
|
||||
|
||||
if ($this->user->id !== $ticket->user_id) {
|
||||
User::find($ticket->user_id)->notify(new NewComment($modelName, $comment));
|
||||
User::find($ticket->user_id)?->notify(new NewComment($this->model, $comment));
|
||||
}
|
||||
|
||||
break;
|
||||
case 'article':
|
||||
case 'playlist':
|
||||
case 'torrent request':
|
||||
case 'torrent':
|
||||
case $this->model instanceof Article:
|
||||
case $this->model instanceof Playlist:
|
||||
case $this->model instanceof TorrentRequest:
|
||||
case $this->model instanceof Torrent:
|
||||
if ($this->user->id !== $this->model->user_id) {
|
||||
User::find($this->model->user_id)->notify(new NewComment($modelName, $comment));
|
||||
User::find($this->model->user_id)?->notify(new NewComment($this->model, $comment));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -149,67 +151,59 @@ class Comments extends Component
|
||||
|
||||
// User Tagged Notification
|
||||
$users = User::whereIn('username', $this->taggedUsers())->get();
|
||||
Notification::sendNow($users, new NewCommentTag($modelName, $comment));
|
||||
Notification::sendNow($users, new NewCommentTag($this->model, $comment));
|
||||
|
||||
// Auto Shout
|
||||
$profileUrl = href_profile($this->user);
|
||||
if (!$this->model instanceof Ticket) {
|
||||
// Auto Shout
|
||||
$username = $comment->anon ? 'An anonymous user' : '[url='.href_profile($this->user).']'.$this->user->username.'[/url]';
|
||||
|
||||
$modelUrl = match ($modelName) {
|
||||
'article' => href_article($this->model),
|
||||
'collection' => href_collection($this->model),
|
||||
'playlist' => href_playlist($this->model),
|
||||
'torrent request' => href_request($this->model),
|
||||
'torrent' => href_torrent($this->model),
|
||||
default => "#"
|
||||
};
|
||||
switch (true) {
|
||||
case $this->model instanceof Article:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Article [url='.href_article($this->model).']'.$this->model->title.'[/url]');
|
||||
|
||||
if ($modelName !== 'ticket') {
|
||||
if ($comment->anon == 0) {
|
||||
$this->chatRepository->systemMessage(
|
||||
sprintf(
|
||||
'[url=%s]%s[/url] has left a comment on '.$modelName.' [url=%s]%s[/url]',
|
||||
$profileUrl,
|
||||
$this->user->username,
|
||||
$modelUrl,
|
||||
$this->model->name ?? $this->model->title
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
sprintf(
|
||||
'An anonymous user has left a comment on '.$modelName.' [url=%s]%s[/url]',
|
||||
$modelUrl,
|
||||
$this->model->name ?? $this->model->title
|
||||
)
|
||||
);
|
||||
break;
|
||||
case $this->model instanceof Collection:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Collection [url='.href_collection($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
case $this->model instanceof Playlist:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Playlist [url='.href_playlist($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
case $this->model instanceof TorrentRequest:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Torrent Request [url='.href_request($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
case $this->model instanceof Torrent:
|
||||
$this->chatRepository->systemMessage($username.' has left a comment on Torrent [url='.href_torrent($this->model).']'.$this->model->name.'[/url]');
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if (!$comment->anon) {
|
||||
$this->user->unlock(new UserMadeComment());
|
||||
$this->user->addProgress(new UserMadeTenComments(), 1);
|
||||
$this->user->addProgress(new UserMade50Comments(), 1);
|
||||
$this->user->addProgress(new UserMade100Comments(), 1);
|
||||
$this->user->addProgress(new UserMade200Comments(), 1);
|
||||
$this->user->addProgress(new UserMade300Comments(), 1);
|
||||
$this->user->addProgress(new UserMade400Comments(), 1);
|
||||
$this->user->addProgress(new UserMade500Comments(), 1);
|
||||
$this->user->addProgress(new UserMade600Comments(), 1);
|
||||
$this->user->addProgress(new UserMade700Comments(), 1);
|
||||
$this->user->addProgress(new UserMade800Comments(), 1);
|
||||
$this->user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon == 0 && $modelName !== 'ticket') {
|
||||
$this->user->unlock(new UserMadeComment());
|
||||
$this->user->addProgress(new UserMadeTenComments(), 1);
|
||||
$this->user->addProgress(new UserMade50Comments(), 1);
|
||||
$this->user->addProgress(new UserMade100Comments(), 1);
|
||||
$this->user->addProgress(new UserMade200Comments(), 1);
|
||||
$this->user->addProgress(new UserMade300Comments(), 1);
|
||||
$this->user->addProgress(new UserMade400Comments(), 1);
|
||||
$this->user->addProgress(new UserMade500Comments(), 1);
|
||||
$this->user->addProgress(new UserMade600Comments(), 1);
|
||||
$this->user->addProgress(new UserMade700Comments(), 1);
|
||||
$this->user->addProgress(new UserMade800Comments(), 1);
|
||||
$this->user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
$this->newCommentState = [
|
||||
'content' => '',
|
||||
];
|
||||
$this->reset('newCommentState');
|
||||
|
||||
$this->gotoPage(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator<Comment>
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator<\App\Models\Comment>
|
||||
*/
|
||||
#[Computed]
|
||||
final public function comments(): \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
|
||||
@@ -23,6 +23,7 @@ use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
/**
|
||||
* App\Models\Comment.
|
||||
@@ -43,14 +44,19 @@ class Comment extends Model
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'content',
|
||||
'user_id',
|
||||
'anon',
|
||||
protected $guarded = [];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'anon' => 'bool',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -100,6 +106,14 @@ class Comment extends Model
|
||||
$builder->whereNull('parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set The Articles Content After Its Been Purified.
|
||||
*/
|
||||
public function setContentAttribute(?string $value): void
|
||||
{
|
||||
$this->attributes['content'] = $value === null ? null : htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Content And Return Valid HTML.
|
||||
*/
|
||||
|
||||
@@ -448,7 +448,7 @@ class Torrent extends Model
|
||||
break;
|
||||
case $payload instanceof Comment:
|
||||
if ($user->acceptsNotification(auth()->user(), $user, 'torrent', 'show_torrent_comment')) {
|
||||
$user->notify(new NewComment('torrent', $payload));
|
||||
$user->notify(new NewComment($this, $payload));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -16,7 +16,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Article;
|
||||
use App\Models\Collection;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Playlist;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\TorrentRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
@@ -27,7 +33,7 @@ class NewComment extends Notification
|
||||
/**
|
||||
* NewComment Constructor.
|
||||
*/
|
||||
public function __construct(public string $type, public Comment $comment)
|
||||
public function __construct(public Torrent|TorrentRequest|Ticket|Playlist|Collection|Article $model, public Comment $comment)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -48,98 +54,39 @@ class NewComment extends Notification
|
||||
*/
|
||||
public function toArray(object $notifiable): array
|
||||
{
|
||||
if ($this->type === 'torrent') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => 'New Torrent Comment Received',
|
||||
'body' => $this->comment->user->username.' has left you a comment on Torrent '.$this->comment->commentable->name,
|
||||
'url' => '/torrents/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
$username = $this->comment->anon ? 'Anonymous' : $this->comment->user->username;
|
||||
|
||||
return [
|
||||
return match (true) {
|
||||
$this->model instanceof Torrent => [
|
||||
'title' => 'New Torrent Comment Received',
|
||||
'body' => 'Anonymous has left you a comment on Torrent '.$this->comment->commentable->name,
|
||||
'body' => $username.' has left you a comment on Torrent '.$this->comment->commentable->name,
|
||||
'url' => '/torrents/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'torrent request') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => 'New Request Comment Received',
|
||||
'body' => $this->comment->user->username.' has left you a comment on Torrent Request '.$this->comment->commentable->name,
|
||||
'url' => '/requests/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
],
|
||||
$this->model instanceof TorrentRequest => [
|
||||
'title' => 'New Request Comment Received',
|
||||
'body' => 'Anonymous has left you a comment on Torrent Request '.$this->comment->commentable->name,
|
||||
'body' => $username.' has left you a comment on Torrent Request '.$this->comment->commentable->name,
|
||||
'url' => '/requests/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'ticket') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => 'New Ticket Comment Received',
|
||||
'body' => $this->comment->user->username.' has left you a comment on Ticket '.$this->comment->commentable->subject,
|
||||
'url' => '/tickets/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
],
|
||||
$this->model instanceof Ticket => [
|
||||
'title' => 'New Ticket Comment Received',
|
||||
'body' => 'Anonymous has left you a comment on Ticket '.$this->comment->commentable->subject,
|
||||
'body' => $username.' has left you a comment on Ticket '.$this->comment->commentable->subject,
|
||||
'url' => '/tickets/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'playlist') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => 'New Playlist Comment Received',
|
||||
'body' => $this->comment->user->username.' has left you a comment on Playlist '.$this->comment->commentable->name,
|
||||
'url' => '/playlists/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
],
|
||||
$this->model instanceof Playlist => [
|
||||
'title' => 'New Playlist Comment Received',
|
||||
'body' => 'Anonymous has left you a comment on Playlist '.$this->comment->commentable->name,
|
||||
'body' => $username.' has left you a comment on Playlist '.$this->comment->commentable->name,
|
||||
'url' => '/playlists/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'collection') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => 'New Collection Comment Received',
|
||||
'body' => $this->comment->user->username.' has left you a comment on Collection '.$this->comment->commentable->name,
|
||||
'url' => '/mediahub/collections/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
],
|
||||
$this->model instanceof Collection => [
|
||||
'title' => 'New Collection Comment Received',
|
||||
'body' => 'Anonymous has left you a comment on Collection '.$this->comment->commentable->name,
|
||||
'body' => $username.' has left you a comment on Collection '.$this->comment->commentable->name,
|
||||
'url' => '/mediahub/collections/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
],
|
||||
$this->model instanceof Article => [
|
||||
'title' => 'New Article Comment Received',
|
||||
'body' => $this->comment->user->username.' has left you a comment on Article '.$this->comment->commentable->title,
|
||||
'body' => $username.' has left you a comment on Article '.$this->comment->commentable->title,
|
||||
'url' => '/articles/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => 'New Article Comment Received',
|
||||
'body' => 'Anonymous has left you a comment on Article '.$this->comment->commentable->title,
|
||||
'url' => '/articles/'.$this->comment->commentable->id,
|
||||
];
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Models\Article;
|
||||
use App\Models\Collection;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Playlist;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\TorrentRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Notification;
|
||||
@@ -28,7 +34,7 @@ class NewCommentTag extends Notification implements ShouldQueue
|
||||
/**
|
||||
* NewCommentTag Constructor.
|
||||
*/
|
||||
public function __construct(public string $type, public Comment $comment)
|
||||
public function __construct(public Torrent|TorrentRequest|Ticket|Playlist|Collection|Article $model, public Comment $comment)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,98 +55,40 @@ class NewCommentTag extends Notification implements ShouldQueue
|
||||
*/
|
||||
public function toArray(object $notifiable): array
|
||||
{
|
||||
if ($this->type === 'torrent') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => $this->comment->user->username.' Has Tagged You',
|
||||
'body' => $this->comment->user->username.' has tagged you in an comment on Torrent '.$this->comment->commentable->name,
|
||||
'url' => '/torrents/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
$username = $this->comment->anon ? 'Anonymous' : $this->comment->user->username;
|
||||
$title = $this->comment->anon ? 'You Have Been Tagged' : $username.' Has Tagged You';
|
||||
|
||||
return [
|
||||
'title' => 'You Have Been Tagged',
|
||||
'body' => 'Anonymous has tagged you in an comment on Torrent '.$this->comment->commentable->name,
|
||||
return match (true) {
|
||||
$this->model instanceof Torrent => [
|
||||
'title' => $title,
|
||||
'body' => $username.' has tagged you in an comment on Torrent '.$this->comment->commentable->name,
|
||||
'url' => '/torrents/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'torrent request') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => $this->comment->user->username.' Has Tagged You',
|
||||
'body' => $this->comment->user->username.' has tagged you in an comment on Torrent Request '.$this->comment->commentable->name,
|
||||
'url' => '/requests/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => 'You Have Been Tagged',
|
||||
'body' => 'Anonymous has tagged you in an comment on Torrent Request '.$this->comment->commentable->name,
|
||||
],
|
||||
$this->model instanceof TorrentRequest => [
|
||||
'title' => $title,
|
||||
'body' => $username.' has tagged you in an comment on Torrent Request '.$this->comment->commentable->name,
|
||||
'url' => '/requests/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'ticket') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => $this->comment->user->username.' Has Tagged You',
|
||||
'body' => $this->comment->user->username.' has tagged you in an comment on Ticket '.$this->comment->commentable->subject,
|
||||
'url' => '/tickets/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => 'You Have Been Tagged',
|
||||
'body' => 'Anonymous has tagged you in an comment on Ticket '.$this->comment->commentable->subject,
|
||||
],
|
||||
$this->model instanceof Ticket => [
|
||||
'title' => $title,
|
||||
'body' => $username.' has tagged you in an comment on Ticket '.$this->comment->commentable->subject,
|
||||
'url' => '/tickets/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'playlist') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => $this->comment->user->username.' Has Tagged You',
|
||||
'body' => $this->comment->user->username.' has tagged you in an comment on Playlist '.$this->comment->commentable->name,
|
||||
'url' => '/playlists/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => 'You Have Been Tagged',
|
||||
'body' => 'Anonymous has tagged you in an comment on Playlist '.$this->comment->commentable->name,
|
||||
],
|
||||
$this->model instanceof Playlist => [
|
||||
'title' => $title,
|
||||
'body' => $username.' has tagged you in an comment on Playlist '.$this->comment->commentable->name,
|
||||
'url' => '/playlists/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->type === 'collection') {
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => $this->comment->user->username.' Has Tagged You',
|
||||
'body' => $this->comment->user->username.' has tagged you in an comment on Collection '.$this->comment->commentable->name,
|
||||
'url' => '/mediahub/collections/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => 'You Have Been Tagged',
|
||||
'body' => 'Anonymous has tagged you in an comment on Collection '.$this->comment->commentable->name,
|
||||
],
|
||||
$this->model instanceof Collection => [
|
||||
'title' => $title,
|
||||
'body' => $username.' has tagged you in an comment on Collection '.$this->comment->commentable->name,
|
||||
'url' => '/mediahub/collections/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->comment->anon == 0) {
|
||||
return [
|
||||
'title' => $this->comment->user->username.' Has Tagged You',
|
||||
'body' => $this->comment->user->username.' has tagged you in an comment on Article '.$this->comment->commentable->title,
|
||||
],
|
||||
$this->model instanceof Article => [
|
||||
'title' => $title,
|
||||
'body' => $username.' has tagged you in an comment on Article '.$this->comment->commentable->title,
|
||||
'url' => '/articles/'.$this->comment->commentable->id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => 'You Have Been Tagged',
|
||||
'body' => 'Anonymous has tagged you in an comment on Article '.$this->comment->commentable->title,
|
||||
'url' => '/articles/'.$this->comment->commentable->id,
|
||||
];
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,96 +645,6 @@ parameters:
|
||||
count: 1
|
||||
path: app/Http/Livewire/BlockIpAddress.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method App\\\\Models\\\\User\\|Illuminate\\\\Database\\\\Eloquent\\\\Collection\\<int, App\\\\Models\\\\User\\>\\:\\:notify\\(\\)\\.$#"
|
||||
count: 4
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Http\\\\Livewire\\\\Comment\\:\\:taggedUsers\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Http\\\\Livewire\\\\Comment\\:\\:updatedIsEditing\\(\\) has parameter \\$isEditing with no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comment\\:\\:\\$comment has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comment\\:\\:\\$editState has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comment\\:\\:\\$isEditing has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comment\\:\\:\\$isReplying has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comment\\:\\:\\$listeners has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comment\\:\\:\\$replyState has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comment\\:\\:\\$validationAttributes has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Unable to resolve the template type TXssCleanInput in call to method voku\\\\helper\\\\AntiXSS\\:\\:xss_clean\\(\\)$#"
|
||||
count: 2
|
||||
path: app/Http/Livewire/Comment.php
|
||||
|
||||
-
|
||||
message: "#^Call to an undefined method App\\\\Models\\\\User\\|Illuminate\\\\Database\\\\Eloquent\\\\Collection\\<int, App\\\\Models\\\\User\\>\\:\\:notify\\(\\)\\.$#"
|
||||
count: 3
|
||||
path: app/Http/Livewire/Comments.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Http\\\\Livewire\\\\Comments\\:\\:taggedUsers\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comments.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comments\\:\\:\\$listeners has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comments.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comments\\:\\:\\$model has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comments.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comments\\:\\:\\$newCommentState has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comments.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Http\\\\Livewire\\\\Comments\\:\\:\\$validationAttributes has no type specified\\.$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comments.php
|
||||
|
||||
-
|
||||
message: "#^Unable to resolve the template type TXssCleanInput in call to method voku\\\\helper\\\\AntiXSS\\:\\:xss_clean\\(\\)$#"
|
||||
count: 1
|
||||
path: app/Http/Livewire/Comments.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Http\\\\Livewire\\\\InviteLogSearch\\:\\:updatingGroupBy\\(\\) has parameter \\$value with no type specified\\.$#"
|
||||
count: 1
|
||||
|
||||
@@ -84,17 +84,17 @@
|
||||
id="edit-comment"
|
||||
class="form__textarea"
|
||||
aria-describedby="edit-comment__textarea-hint"
|
||||
wire:model="editState.content"
|
||||
wire:model="editState"
|
||||
required
|
||||
></textarea>
|
||||
<label for="edit-comment" class="form__label form__label--floating">
|
||||
@error('editState.content')
|
||||
@error('editState')
|
||||
<strong>{{ __('common.error') }}:</strong>
|
||||
@enderror
|
||||
|
||||
Edit your comment...
|
||||
</label>
|
||||
@error('editState.content')
|
||||
@error('editState')
|
||||
<span class="form__hint" id="edit-comment__textarea-hint">
|
||||
{{ $message }}
|
||||
</span>
|
||||
@@ -139,18 +139,18 @@
|
||||
id="reply-comment"
|
||||
class="form__textarea"
|
||||
aria-describedby="reply-comment__textarea-hint"
|
||||
wire:model="replyState.content"
|
||||
wire:model="replyState"
|
||||
required
|
||||
x-on:focus="toggleOn"
|
||||
></textarea>
|
||||
<label for="reply-comment" class="form__label form__label--floating">
|
||||
@error('editState.content')
|
||||
@error('editState')
|
||||
<strong>{{ __('common.error') }}:</strong>
|
||||
@enderror
|
||||
|
||||
Reply to parent comment...
|
||||
</label>
|
||||
@error('replyState.content')
|
||||
@error('replyState')
|
||||
<span class="form__hint" id="reply-comment__textarea-hint">
|
||||
{{ $message }}
|
||||
</span>
|
||||
|
||||
@@ -11,18 +11,18 @@
|
||||
id="new-comment__textarea"
|
||||
class="form__textarea"
|
||||
aria-describedby="new-comment__textarea-hint"
|
||||
wire:model="newCommentState.content"
|
||||
wire:model="newCommentState"
|
||||
required
|
||||
x-on:focus="toggleOn"
|
||||
></textarea>
|
||||
<label for="new-comment__textarea" class="form__label form__label--floating">
|
||||
@error('newCommentState.content')
|
||||
@error('newCommentState')
|
||||
<strong>{{ __('common.error') }}:</strong>
|
||||
@enderror
|
||||
|
||||
Add a comment...
|
||||
</label>
|
||||
@error('newCommentState.content')
|
||||
@error('newCommentState')
|
||||
<span class="form__hint" id="new-comment__textarea-hint">{{ $message }}</span>
|
||||
@enderror
|
||||
</p>
|
||||
@@ -39,7 +39,7 @@
|
||||
</form>
|
||||
<ol class="comment-list">
|
||||
@forelse ($comments as $comment)
|
||||
<livewire:comment :comment="$comment" :key="$comment->id" />
|
||||
<livewire:comment :model="$model" :comment="$comment" :key="$comment->id" />
|
||||
@empty
|
||||
<li>
|
||||
<i class="{{ config('other.font-awesome') }} fa-frown"></i>
|
||||
|
||||
Reference in New Issue
Block a user