104 lines
2.6 KiB
PHP
104 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
|
|
|
class PhotoRead extends Model
|
|
{
|
|
public $timestamps = false;
|
|
|
|
protected $fillable = [
|
|
'photo_id',
|
|
'actor_guard',
|
|
'actor_id',
|
|
'read_at',
|
|
];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'read_at' => 'datetime',
|
|
];
|
|
}
|
|
|
|
public function photo(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Photo::class);
|
|
}
|
|
|
|
public static function mark(Photo $photo, string $guard, int $actorId): void
|
|
{
|
|
static::query()->firstOrCreate(
|
|
[
|
|
'photo_id' => $photo->id,
|
|
'actor_guard' => $guard,
|
|
'actor_id' => $actorId,
|
|
],
|
|
['read_at' => now()],
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param list<int> $photoIds
|
|
* @return list<int>
|
|
*/
|
|
public static function readPhotoIds(string $guard, int $actorId, array $photoIds): array
|
|
{
|
|
if ($photoIds === []) {
|
|
return [];
|
|
}
|
|
|
|
return static::query()
|
|
->where('actor_guard', $guard)
|
|
->where('actor_id', $actorId)
|
|
->whereIn('photo_id', $photoIds)
|
|
->pluck('photo_id')
|
|
->map(static fn ($id) => (int) $id)
|
|
->all();
|
|
}
|
|
|
|
public static function applyFilter(Builder|Relation $q, string $guard, int $actorId, string $photoIdColumn, mixed $read): void
|
|
{
|
|
$flag = self::parseReadFilter($read);
|
|
if ($flag === null) {
|
|
return;
|
|
}
|
|
|
|
$exists = function ($sub) use ($guard, $actorId, $photoIdColumn) {
|
|
$sub->from('photo_reads')
|
|
->whereColumn('photo_reads.photo_id', $photoIdColumn)
|
|
->where('photo_reads.actor_guard', $guard)
|
|
->where('photo_reads.actor_id', $actorId);
|
|
};
|
|
|
|
if ($flag) {
|
|
$q->whereExists($exists);
|
|
} else {
|
|
$q->whereNotExists($exists);
|
|
}
|
|
}
|
|
|
|
public static function parseReadFilter(mixed $raw): ?bool
|
|
{
|
|
if ($raw === null) {
|
|
return null;
|
|
}
|
|
$value = is_string($raw) ? strtolower(trim($raw)) : $raw;
|
|
if ($value === '' || $value === 'all') {
|
|
return null;
|
|
}
|
|
if ($value === 0 || $value === '0' || $value === 'unread') {
|
|
return false;
|
|
}
|
|
if ($value === 1 || $value === '1' || $value === 'read') {
|
|
return true;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|