byos_laravel/app/Models/Playlist.php
2025-12-29 22:16:29 +01:00

116 lines
3.3 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;
class Playlist extends Model
{
use HasFactory;
protected $guarded = ['id'];
protected $casts = [
'is_active' => 'boolean',
'weekdays' => 'array',
'active_from' => 'datetime:H:i',
'active_until' => 'datetime:H:i',
'refresh_time' => 'integer',
];
public function device(): BelongsTo
{
return $this->belongsTo(Device::class);
}
public function items(): HasMany
{
return $this->hasMany(PlaylistItem::class);
}
public function isActiveNow(): bool
{
if (! $this->is_active) {
return false;
}
// Get user's timezone or fall back to app timezone
$timezone = $this->device->user->timezone ?? config('app.timezone');
$now = now($timezone);
// Check weekday (using timezone-aware time)
if ($this->weekdays !== null && ! in_array($now->dayOfWeek, $this->weekdays)) {
return false;
}
if ($this->active_from !== null && $this->active_until !== null) {
// Create timezone-aware datetime objects for active_from and active_until
$activeFrom = $now->copy()
->setTimeFrom($this->active_from)
->timezone($timezone);
$activeUntil = $now->copy()
->setTimeFrom($this->active_until)
->timezone($timezone);
// Handle time ranges that span across midnight
if ($activeFrom > $activeUntil) {
// Time range spans midnight (e.g., 09:01 to 03:58)
if ($now >= $activeFrom || $now <= $activeUntil) {
return true;
}
} elseif ($now >= $activeFrom && $now <= $activeUntil) {
return true;
}
return false;
}
return true;
}
public function getNextPlaylistItem(): ?PlaylistItem
{
if (! $this->isActiveNow()) {
return null;
}
// Get active playlist items ordered by display order
/** @var \Illuminate\Support\Collection|PlaylistItem[] $playlistItems */
$playlistItems = $this->items()
->where('is_active', true)
->orderBy('order')
->get();
if ($playlistItems->isEmpty()) {
return null;
}
// Get the last displayed item
$lastDisplayed = $playlistItems
->sortByDesc('last_displayed_at')
->first();
if (! $lastDisplayed || ! $lastDisplayed->last_displayed_at) {
// If no item has been displayed yet, return the first one
return $playlistItems->first();
}
// Find the next item in sequence
$currentOrder = $lastDisplayed->order;
$nextItem = $playlistItems
->where('order', '>', $currentOrder)
->first();
// If there's no next item, loop back to the first one
if (! $nextItem) {
return $playlistItems->first();
}
return $nextItem;
}
}