*/ protected $fillable = [ 'name', 'email', 'password', 'settings', ]; /** * The attributes that should be hidden for serialization. * * @var list */ protected $hidden = [ 'password', 'remember_token', ]; protected $attributes = [ 'settings' => "{timezone:'UTC'}", ]; /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', 'settings' => 'array', ]; } public function favourites(): BelongsToMany { return $this->belongsToMany(Comic::class, 'user_favourite')->withTimestamps(); } public function readingHistories(): BelongsToMany { return $this->belongsToMany(Chapter::class, 'reading_histories')->withTimestamps(); } public function cleanUpReadingHistories(): array { // Get the user's ID $userId = $this->id; // Step 1: Identify records to keep $idsToKeep = ReadingHistory::query()->select('reading_histories.id') ->joinSub( ReadingHistory::query() ->select('comic_id', 'user_id', 'chapter_id', DB::raw('MIN(created_at) as earliest_created_at')) ->where('user_id', $userId)->groupBy('comic_id', 'user_id', 'chapter_id'), 'b', function (JoinClause $join) { $join->on('reading_histories.comic_id', '=', 'b.comic_id') ->on('reading_histories.user_id', '=', 'b.user_id') // Disambiguate user_id ->on('reading_histories.chapter_id', '=', 'b.chapter_id') ->on('reading_histories.created_at', '=', 'b.earliest_created_at'); } )->where('reading_histories.user_id', $userId)->pluck('id'); // Step 2: Delete duplicates for the user $deletedCount = ReadingHistory::where('user_id', $userId)->whereNotIn('id', $idsToKeep)->delete(); // Return the result as an array return [ 'user_id' => $userId, 'kept_ids' => $idsToKeep, 'deleted_count' => $deletedCount, ]; } }