diff --git a/app/Helpers/CacheHelper.php b/app/Helpers/CacheHelper.php index 155e044..cde2cee 100644 --- a/app/Helpers/CacheHelper.php +++ b/app/Helpers/CacheHelper.php @@ -2,6 +2,7 @@ namespace App\Helpers; +use App\Models\Comment; use App\Models\Episode; use App\Models\Hentai; use App\Models\PopularMonthly; @@ -126,7 +127,7 @@ class CacheHelper public static function getLatestComments() { return Cache::remember("latest_comments", now()->addMinutes(60), function () { - return DB::table('comments')->latest()->take(10)->get(); + return Comment::latest()->take(10)->get(); }); } } diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 4d77ea2..c58ece8 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -3,8 +3,6 @@ namespace App\Http\Controllers; use App\Models\Episode; -use App\Models\Playlist; -use App\Models\PlaylistEpisode; use App\Models\User; use App\Http\Requests\ProfileUpdateRequest; use Illuminate\Http\RedirectResponse; @@ -84,7 +82,7 @@ class ProfileController extends Controller public function comments(Request $request): View { return view('profile.comments', [ - 'user' => $request->user(), + 'user' => $request->user(), ]); } diff --git a/app/Livewire/Comment.php b/app/Livewire/Comment.php new file mode 100644 index 0000000..9fe9bf8 --- /dev/null +++ b/app/Livewire/Comment.php @@ -0,0 +1,166 @@ + '' + ]; + + public $isEditing = false; + + public $editState = [ + 'body' => '' + ]; + + protected $listeners = [ + 'refresh' => '$refresh' + ]; + + protected $validationAttributes = [ + 'replyState.body' => 'reply' + ]; + + public function updatedIsEditing($isEditing) + { + if (! $isEditing) { + return; + } + + $this->editState = [ + 'body' => $this->comment->body + ]; + } + + public function editComment() + { + $this->authorize('update', $this->comment); + + $this->comment->update($this->editState); + + $this->isEditing = false; + } + + public function deleteComment() + { + $this->authorize('destroy', $this->comment); + + $this->comment->delete(); + + $this->dispatch('refresh'); + } + + public function postReply() + { + if (!($this->comment->depth() < 2)) { + $this->addError('replyState.body', "Too many sub comments."); + return; + } + + $user = auth()->user(); + $rateLimitKey = "send-comment:{$user->id}"; + $rateLimitMinutes = 60 * 5; // 5 minutes + + if (RateLimiter::tooManyAttempts($rateLimitKey, 1)) { + $seconds = RateLimiter::availableIn($rateLimitKey); + + $this->addError('replyState.body', "Too many comments. Try again in {$seconds} seconds."); + return; + } + + RateLimiter::hit($rateLimitKey, $rateLimitMinutes); + + $this->validate([ + 'replyState.body' => 'required' + ]); + + $reply = $this->comment->children()->make($this->replyState); + $reply->user()->associate($user); + $reply->commentable()->associate($this->comment->commentable); + + $reply->save(); + + // Notify if Episode and if not the same user + if ($reply->commentable_type == Episode::class && $user->id !== $reply->parent->user->id) { + $episode = Episode::where('id', $reply->commentable_id) + ->firstOrFail(); + + $url = route('hentai.index', ['title' => $episode->slug]); + + $reply->parent->user->notify( + new CommentNotification( + "{$user->name} replied to your comment.", + Str::limit($reply->body, 50), + "{$url}#comment-{$reply->id}" + ) + ); + } + + $this->replyState = [ + 'body' => '' + ]; + + $this->isReplying = false; + + $this->dispatch('refresh')->self(); + } + + public function like() + { + if (! Auth::check()) { + return; + } + + Like::toggle($this->comment, User::where('id', Auth::user()->id)->firstOrFail()); + + Cache::forget('commentLikes'.$this->comment->id); + + if ($this->liked) { + $this->liked = false; + $this->likeCount--; + return; + } + + $this->liked = true; + $this->likeCount++; + } + + public function mount() + { + if (Auth::check()) { + $this->likeCount = $this->comment->likeCount(); + $this->liked = Like::has($this->comment, User::where('id', Auth::user()->id)->firstOrFail()); + } + } + + public function render() + { + return view('livewire.comment'); + } +} \ No newline at end of file diff --git a/app/Livewire/Comments.php b/app/Livewire/Comments.php new file mode 100644 index 0000000..156ef60 --- /dev/null +++ b/app/Livewire/Comments.php @@ -0,0 +1,71 @@ + '' + ]; + + protected $validationAttributes = [ + 'newCommentState.body' => 'comment' + ]; + + protected $listeners = [ + 'refresh' => '$refresh' + ]; + + public function postComment() + { + $this->validate([ + 'newCommentState.body' => 'required' + ]); + + $user = auth()->user(); + $rateLimitKey = "send-comment:{$user->id}"; + $rateLimitMinutes = 60 * 5; // 5 minutes + + if (RateLimiter::tooManyAttempts($rateLimitKey, 1)) { + $seconds = RateLimiter::availableIn($rateLimitKey); + + $this->addError('newCommentState.body', "Too many comments. Try again in {$seconds} seconds."); + return; + } + + RateLimiter::hit($rateLimitKey, $rateLimitMinutes); + + $comment = $this->model->comments()->make($this->newCommentState); + $comment->user()->associate($user); + $comment->save(); + + $this->newCommentState = [ + 'body' => '' + ]; + + $this->resetPage(); + } + + public function render() + { + $comments = $this->model + ->comments() + ->with('user', 'children.user', 'children.children') + ->parent() + ->latest() + ->paginate(50); + + return view('livewire.comments', [ + 'comments' => $comments + ]); + } +} \ No newline at end of file diff --git a/app/Livewire/UserComments.php b/app/Livewire/UserComments.php new file mode 100644 index 0000000..010dfbb --- /dev/null +++ b/app/Livewire/UserComments.php @@ -0,0 +1,49 @@ +order) { + case 'created_at_desc': + $orderby = 'created_at'; + $orderdirection = 'desc'; + break; + case 'created_at_asc': + $orderby = 'created_at'; + $orderdirection = 'asc'; + break; + default: + $orderby = 'created_at'; + $orderdirection = 'desc'; + } + + + $comments = Comment::where('user_id', $this->model->id) + ->when($this->commentSearch != '', fn ($query) => $query->where('body', 'like', '%'.$this->commentSearch.'%')) + ->orderBy($orderby, $orderdirection) + ->paginate(10); + + return view('livewire.user-comments', [ + 'comments' => $comments + ]); + } +} diff --git a/app/Models/Comment.php b/app/Models/Comment.php new file mode 100644 index 0000000..cc92d83 --- /dev/null +++ b/app/Models/Comment.php @@ -0,0 +1,76 @@ +belongsTo(User::class); + } + + public function scopeParent(Builder $builder) + { + $builder->whereNull('parent_id'); + } + + public function children() + { + return $this->hasMany(Comment::class, 'parent_id')->oldest(); + } + + public function commentable() + { + return $this->morphTo(); + } + + public function parent() + { + return $this->hasOne(Comment::class, 'id', 'parent_id'); + } + + // Recursevly calculates how deep the nesting is + public function depth(): int + { + return $this->parent + ? $this->parent->depth() + 1 + : 0; + } + + /** + * Get cached like count + */ + public function likeCount(): int + { + return cache()->remember('commentLikes' . $this->id, 300, fn() => $this->likes->count()); + } +} diff --git a/app/Models/Episode.php b/app/Models/Episode.php index eef658e..31ef83d 100644 --- a/app/Models/Episode.php +++ b/app/Models/Episode.php @@ -8,7 +8,6 @@ use App\Models\PopularWeekly; use App\Models\PopularDaily; use Conner\Tagging\Taggable; -use Laravelista\Comments\Commentable; use Laravel\Scout\Searchable; use Maize\Markable\Markable; use Maize\Markable\Models\Like; @@ -26,7 +25,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; class Episode extends Model implements Sitemapable { - use Commentable, Markable, Taggable; + use Markable, Taggable; use HasFactory; use Searchable; @@ -161,6 +160,11 @@ class Episode extends Model implements Sitemapable return cache()->remember('episodeComments' . $this->id, 300, fn() => $this->comments->count()); } + public function comments() + { + return $this->morphMany(Comment::class, 'commentable'); + } + public function getProblematicTags(): string { $problematicTags = ['Gore', 'Scat', 'Horror']; diff --git a/app/Models/Hentai.php b/app/Models/Hentai.php index f17bd6f..2c5430a 100644 --- a/app/Models/Hentai.php +++ b/app/Models/Hentai.php @@ -10,11 +10,10 @@ use Illuminate\Support\Carbon; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Conner\Tagging\Taggable; -use Laravelista\Comments\Commentable; class Hentai extends Model implements Sitemapable { - use Commentable, Taggable; + use Taggable; use HasFactory; /** @@ -37,6 +36,11 @@ class Hentai extends Model implements Sitemapable return $this->episodes->first()->title; } + public function comments() + { + return $this->morphMany(Comment::class, 'commentable'); + } + /** * Has a Gallery. */ diff --git a/app/Models/Presenters/CommentPresenter.php b/app/Models/Presenters/CommentPresenter.php new file mode 100644 index 0000000..645f85f --- /dev/null +++ b/app/Models/Presenters/CommentPresenter.php @@ -0,0 +1,28 @@ +comment = $comment; + } + + public function markdownBody() + { + return Str::of($this->comment->body)->markdown([ + 'html_input' => 'strip', + ]); + } + + public function relativeCreatedAt() + { + return $this->comment->created_at->diffForHumans(); + } +} \ No newline at end of file diff --git a/app/Models/User.php b/app/Models/User.php index e2c7754..d9de512 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -9,13 +9,11 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Illuminate\Support\Facades\Storage; -use Laravelista\Comments\Commenter; - use Illuminate\Support\Facades\DB; class User extends Authenticatable { - use HasFactory, Notifiable, Commenter; + use HasFactory, Notifiable; /** * The attributes that are mass assignable. @@ -91,9 +89,17 @@ class User extends Authenticatable /** * Has Many Comments. */ + public function comments() + { + return $this->hasMany(Comment::class, 'user_id'); + } + + /** + * Get Comment Count. + */ public function commentCount(): int { - return DB::table('comments')->where('commenter_id', $this->id)->count(); + return cache()->remember('userComments' . $this->id, 300, fn() => $this->comments->count()); } /** diff --git a/app/Override/Comments/CommentPolicy.php b/app/Override/Comments/CommentPolicy.php deleted file mode 100644 index 5d473d0..0000000 --- a/app/Override/Comments/CommentPolicy.php +++ /dev/null @@ -1,56 +0,0 @@ -getKey() == $comment->commenter_id) || $user->is_admin; - } - - /** - * Can user update the comment - * - * @param $user - * @param Comment $comment - * @return bool - */ - public function update($user, Comment $comment) : bool - { - return $user->getKey() == $comment->commenter_id; - } - - /** - * Can user reply to the comment - * - * @param $user - * @param Comment $comment - * @return bool - */ - public function reply($user, Comment $comment) : bool - { - return $user->getKey() != $comment->commenter_id; - } -} - diff --git a/app/Override/Comments/CommentService.php b/app/Override/Comments/CommentService.php deleted file mode 100644 index b72f260..0000000 --- a/app/Override/Comments/CommentService.php +++ /dev/null @@ -1,138 +0,0 @@ - 'required|string|max:255', - 'guest_email' => 'required|string|email|max:255', - ]; - } - - // Merge guest rules, if any, with normal validation rules. - Validator::make($request->all(), array_merge($guest_rules ?? [], [ - 'commentable_type' => 'required|string', - 'commentable_id' => 'required|string|min:1', - 'message' => 'required|string' - ]))->validate(); - - $model = $request->commentable_type::findOrFail($request->commentable_id); - - $commentClass = Config::get('comments.model'); - $comment = new $commentClass; - - if (!Auth::check()) { - $comment->guest_name = $request->guest_name; - $comment->guest_email = $request->guest_email; - } else { - $comment->commenter()->associate(Auth::user()); - } - - $comment->commentable()->associate($model); - $comment->comment = $request->message; - $comment->approved = !Config::get('comments.approval_required'); - $comment->save(); - - return $comment; - } - - /** - * Handles updating the message of the comment. - * @return mixed the configured comment-model - */ - public function update(Request $request, Comment $comment) - { - Gate::authorize('edit-comment', $comment); - - Validator::make($request->all(), [ - 'message' => 'required|string' - ])->validate(); - - $comment->update([ - 'comment' => $request->message - ]); - - return $comment; - } - - /** - * Handles deleting a comment. - * @return mixed the configured comment-model - */ - public function destroy(Comment $comment): void - { - Gate::authorize('delete-comment', $comment); - - if (Config::get('comments.soft_deletes') == true) { - $comment->delete(); - } else { - $comment->delete(); - } - } - - /** - * Handles creating a reply "comment" to a comment. - * @return mixed the configured comment-model - */ - public function reply(Request $request, Comment $comment) - { - Gate::authorize('reply-to-comment', $comment); - - Validator::make($request->all(), [ - 'message' => 'required|string' - ])->validate(); - - $commentClass = Config::get('comments.model'); - $reply = new $commentClass; - $reply->commenter()->associate(Auth::user()); - $reply->commentable()->associate($comment->commentable); - $reply->parent()->associate($comment); - $reply->comment = $request->message; - $reply->approved = !Config::get('comments.approval_required'); - $reply->save(); - - // Notify - if ($comment->commentable_type == 'App\Models\Episode') { - $episode = Episode::where('id', $comment->commentable_id)->firstOrFail(); - $url = '/hentai/' . $episode->slug . '#comment-' . $reply->id; - - $user = Auth::user(); - - $parentCommentUser = User::where('id', $comment->commenter_id)->firstOrFail(); - $parentCommentUser->notify( - new CommentNotification( - "{$user->name} replied to your comment.", - Str::limit($reply->comment, 50), - $url - ) - ); - } - - return $reply; - } -} diff --git a/app/Policies/CommentPolicy.php b/app/Policies/CommentPolicy.php new file mode 100644 index 0000000..4f52686 --- /dev/null +++ b/app/Policies/CommentPolicy.php @@ -0,0 +1,22 @@ +id === $comment->user_id; + } + + public function destroy(User $user, Comment $comment): bool + { + return $user->id === $comment->user_id; + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index d0233f2..d59ce9d 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,6 @@ "laravel/scout": "^10.20", "laravel/socialite": "^5.24", "laravel/tinker": "^2.10", - "laravelista/comments": "dev-l11-compatibility", "livewire/livewire": "^3.6.4", "maize-tech/laravel-markable": "^2.3.0", "meilisearch/meilisearch-php": "^1.16", @@ -50,19 +49,13 @@ } ], "autoload": { - "exclude-from-classmap": [ - "vendor/laravelista/comments/src/CommentPolicy.php", - "vendor/laravelista/comments/src/CommentService.php" - ], + "exclude-from-classmap": [], "psr-4": { "App\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" }, - "files": [ - "app/Override/Comments/CommentPolicy.php", - "app/Override/Comments/CommentService.php" - ] + "files": [] }, "autoload-dev": { "psr-4": { diff --git a/composer.lock b/composer.lock index cedb267..68a4f97 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "749225dc4ea2aca06f1639bef889cc59", + "content-hash": "cf750c98603544d91cf1bdb428866a8f", "packages": [ { "name": "brick/math", @@ -581,56 +581,6 @@ ], "time": "2025-03-06T22:45:56+00:00" }, - { - "name": "erusev/parsedown", - "version": "1.7.4", - "source": { - "type": "git", - "url": "https://github.com/erusev/parsedown.git", - "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", - "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35" - }, - "type": "library", - "autoload": { - "psr-0": { - "Parsedown": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Emanuil Rusev", - "email": "hello@erusev.com", - "homepage": "http://erusev.com" - } - ], - "description": "Parser for Markdown.", - "homepage": "http://parsedown.org", - "keywords": [ - "markdown", - "parser" - ], - "support": { - "issues": "https://github.com/erusev/parsedown/issues", - "source": "https://github.com/erusev/parsedown/tree/1.7.x" - }, - "time": "2019-12-30T22:54:17+00:00" - }, { "name": "firebase/php-jwt", "version": "v7.0.2", @@ -2266,70 +2216,6 @@ }, "time": "2025-01-27T14:24:01+00:00" }, - { - "name": "laravelista/comments", - "version": "dev-l11-compatibility", - "source": { - "type": "git", - "url": "https://github.com/renatokira/comments.git", - "reference": "490764a774d520a4d9e43395b472d0f9bf802ef6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/renatokira/comments/zipball/490764a774d520a4d9e43395b472d0f9bf802ef6", - "reference": "490764a774d520a4d9e43395b472d0f9bf802ef6", - "shasum": "" - }, - "require": { - "erusev/parsedown": "^1.7", - "illuminate/database": "^9.0|^10.0|^11.0", - "illuminate/http": "^9.0|^10.0|^11.0", - "illuminate/pagination": "^9.0|^10.0|^11.0", - "illuminate/queue": "^9.0|^10.0|^11.0", - "illuminate/routing": "^9.0|^10.0|^11.0", - "illuminate/support": "^9.0|^10.0|^11.0", - "php": "^8.0", - "spatie/laravel-honeypot": "^4.5" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Laravelista\\Comments\\ServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Laravelista\\Comments\\": "src/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mario Bašić", - "email": "mario@laravelista.hr", - "homepage": "https://laravelista.hr" - } - ], - "description": "Comments for Laravel.", - "keywords": [ - "comments", - "laravel" - ], - "support": { - "source": "https://github.com/renatokira/comments/tree/l11-compatibility" - }, - "funding": [ - { - "type": "patreon", - "url": "https://www.patreon.com/laravelista" - } - ], - "time": "2024-03-16T14:14:11+00:00" - }, { "name": "league/commonmark", "version": "2.7.1", @@ -5817,82 +5703,6 @@ ], "time": "2025-05-20T08:42:52+00:00" }, - { - "name": "spatie/laravel-honeypot", - "version": "4.6.1", - "source": { - "type": "git", - "url": "https://github.com/spatie/laravel-honeypot.git", - "reference": "38d164f14939e943b92771859fc206c74cba8397" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-honeypot/zipball/38d164f14939e943b92771859fc206c74cba8397", - "reference": "38d164f14939e943b92771859fc206c74cba8397", - "shasum": "" - }, - "require": { - "illuminate/contracts": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/encryption": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/http": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0", - "illuminate/validation": "^8.0|^9.0|^10.0|^11.0|^12.0", - "nesbot/carbon": "^2.0|^3.0", - "php": "^8.0", - "spatie/laravel-package-tools": "^1.9", - "symfony/http-foundation": "^5.1.2|^6.0|^7.0" - }, - "require-dev": { - "livewire/livewire": "^2.10|^3.0", - "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0", - "pestphp/pest-plugin-livewire": "^1.0|^2.1|^3.0", - "phpunit/phpunit": "^9.6|^10.5|^11.5", - "spatie/pest-plugin-snapshots": "^1.1|^2.1", - "spatie/phpunit-snapshot-assertions": "^4.2|^5.1", - "spatie/test-time": "^1.2.1" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Spatie\\Honeypot\\HoneypotServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "Spatie\\Honeypot\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", - "homepage": "https://spatie.be", - "role": "Developer" - } - ], - "description": "Preventing spam submitted through forms", - "homepage": "https://github.com/spatie/laravel-honeypot", - "keywords": [ - "laravel-honeypot", - "spatie" - ], - "support": { - "source": "https://github.com/spatie/laravel-honeypot/tree/4.6.1" - }, - "funding": [ - { - "url": "https://spatie.be/open-source/support-us", - "type": "custom" - } - ], - "time": "2025-05-05T13:50:37+00:00" - }, { "name": "spatie/laravel-package-tools", "version": "1.92.7", @@ -11900,9 +11710,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "laravelista/comments": 20 - }, + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { diff --git a/database/migrations/2026_01_10_120521_migrate_comments_table.php b/database/migrations/2026_01_10_120521_migrate_comments_table.php new file mode 100644 index 0000000..94278fc --- /dev/null +++ b/database/migrations/2026_01_10_120521_migrate_comments_table.php @@ -0,0 +1,75 @@ +dropForeign(['child_id']); + $table->dropIndex(['commenter_id', 'commenter_type']); + }); + + // Rename and Drop columns + Schema::table('comments', function (Blueprint $table) { + $table->renameColumn('commenter_id', 'user_id'); + $table->dropColumn('commenter_type'); + $table->dropColumn('guest_name'); + $table->dropColumn('guest_email'); + $table->renameColumn('child_id', 'parent_id'); + $table->renameColumn('comment', 'body'); + $table->dropColumn('approved'); + }); + + // Add Foreign Keys + Schema::table('comments', function (Blueprint $table) { + // Ensure the column is unsigned + $table->bigInteger('user_id')->unsigned()->change(); + + // Add the foreign key constraint + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->foreign('parent_id')->references('id')->on('comments')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // Drop Foreign Keys + Schema::table('comments', function (Blueprint $table) { + $table->dropForeign(['parent_id']); + $table->dropForeign(['user_id']); + }); + + // Rename and Re-Add Columns + Schema::table('comments', function (Blueprint $table) { + $table->renameColumn('user_id', 'commenter_id'); + $table->string('commenter_type')->nullable()->after('commenter_id'); + $table->string('guest_name')->nullable()->after('commenter_type'); + $table->string('guest_email')->nullable()->after('guest_name'); + $table->renameColumn('parent_id', 'child_id'); + $table->renameColumn('body', 'comment'); + $table->boolean('approved')->default(true)->after('comment'); + }); + + DB::table('comments')->update([ + 'commenter_type' => 'App\Models\User', + ]); + + // Re-Add foreign key constraint and index + Schema::table('comments', function (Blueprint $table) { + $table->foreign('child_id')->references('id')->on('comments')->onDelete('cascade'); + $table->index(["commenter_id", "commenter_type"]); + }); + } +}; diff --git a/resources/views/home/partials/comments.blade.php b/resources/views/home/partials/comments.blade.php index 5ed6af4..3edbe96 100644 --- a/resources/views/home/partials/comments.blade.php +++ b/resources/views/home/partials/comments.blade.php @@ -2,14 +2,14 @@ {{ __('home.latest-comments') }}
-
{{ $episode->title }} - +
{{ $episode->title }} - {{ $episode->episode }}
+
{{ $hentai->episodes->first()->title }}
{{ $comment->user->name }}
+ @if($comment->user->is_admin) + + @endif + @if($comment->user->is_patreon) + + @endif +Comments
+Log in to comment.
+ @endguest +No comments yet.
+ @endif ++ {{ $episode->viewCountFormatted() }} + {{ $episode->likeCount() }} + {{ $episode->commentCount() }} +
+ +{{ $user->name }} - {{ \Carbon\Carbon::parse($comment->created_at)->diffForHumans() }}
- @else -{{ $user->name }} - {{ \Carbon\Carbon::parse($comment->created_at)->diffForHumans() }}
- @endif +{{ $comment->user->name }}
+ @if($comment->user->is_admin) + + @endif + @if($comment->user->is_patreon) + + @endif +- {{ $episode->getResolution() }}
-- {{ $episode->viewCountFormatted() }} {{ $episode->likeCount() }} - {{ $episode->commentCount() }} -
-- {{ $episode->title }} - {{ $episode->episode }}
-- {{ $episode->title }} - {{ $episode->episode }}
-- {{ __('home.latest-comments') }} -
- @comments(['model' => $hentai]) -- {{ __('home.latest-comments') }} -
- @comments(['model' => $episode]) -{{ $comment->commenter->name }} - {{ $comment->created_at->diffForHumans() }}
- @else -{{ $comment->commenter->name }} - {{ $comment->created_at->diffForHumans() }}
- @endif -{{-- Margin bottom --}} - - - - {{-- Recursion for children --}} - @if($grouped_comments->has($comment->getKey()) && $indentationLevel <= $maxIndentationLevel) - {{-- TODO: Don't repeat code. Extract to a new file and include it. --}} - @foreach($grouped_comments[$comment->getKey()] as $child) -
diff --git a/resources/views/vendor/comments/components/comments.blade.php b/resources/views/vendor/comments/components/comments.blade.php deleted file mode 100644 index d02a0e0..0000000 --- a/resources/views/vendor/comments/components/comments.blade.php +++ /dev/null @@ -1,80 +0,0 @@ -@php - if (isset($approved) and $approved == true) { - $comments = $model->approvedComments; - } else { - $comments = $model->comments; - } -@endphp - -@if($comments->count() < 1) -
@lang('comments::comments.authentication_required')
-@lang('comments::comments.you_must_login_to_post_a_comment')
-- - Login - -