77 lines
2.6 KiB
PHP
77 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Domains\Event\Services;
|
|
|
|
use App\Domains\Event\Enums\EventDateChangeType;
|
|
use App\Domains\Event\Models\EventDate;
|
|
use App\Domains\Event\Models\EventDateChange;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class EventDateInfoFormatter
|
|
{
|
|
/** @param Collection<int, EventDateChange> $changes */
|
|
public function format(EventDate $eventDate, Collection $changes): ?string
|
|
{
|
|
$messages = collect();
|
|
|
|
if ($eventDate->suspended_at !== null) {
|
|
$messages->push('Esta fecha fue cancelada.');
|
|
}
|
|
|
|
$sourceDates = $this->reschedulesEndingAt($eventDate, $changes)
|
|
->pluck('previous_date')
|
|
->filter()
|
|
->map(fn ($date): string => $date->format('d/m/Y'))
|
|
->unique()
|
|
->values();
|
|
|
|
if ($sourceDates->isNotEmpty()) {
|
|
$verb = $sourceDates->count() === 1 ? 'se reprogramó' : 'se reprogramaron';
|
|
$messages->push("{$sourceDates->join(', ', ' y ')} {$verb} para este día.");
|
|
}
|
|
|
|
return $messages->isEmpty() ? null : $messages->join(' ');
|
|
}
|
|
|
|
/**
|
|
* Includes direct and intermediate reschedules that ultimately end at the
|
|
* displayed event date, while preserving the original change order.
|
|
*
|
|
* @param Collection<int, EventDateChange> $changes
|
|
* @return Collection<int, EventDateChange>
|
|
*/
|
|
private function reschedulesEndingAt(EventDate $eventDate, Collection $changes): Collection
|
|
{
|
|
$eventDateId = $eventDate->getKey();
|
|
$reschedules = $changes->where('change_type', EventDateChangeType::Rescheduled);
|
|
|
|
if ($eventDateId === null) {
|
|
return $reschedules->where('destination_event_date_id', null);
|
|
}
|
|
|
|
$destinationIds = [(int) $eventDateId => true];
|
|
|
|
do {
|
|
$foundAncestor = false;
|
|
|
|
foreach ($reschedules as $change) {
|
|
$destinationId = $change->destination_event_date_id;
|
|
$sourceId = $change->source_event_date_id;
|
|
|
|
if ($destinationId === null || $sourceId === null) {
|
|
continue;
|
|
}
|
|
|
|
if (isset($destinationIds[(int) $destinationId]) && ! isset($destinationIds[(int) $sourceId])) {
|
|
$destinationIds[(int) $sourceId] = true;
|
|
$foundAncestor = true;
|
|
}
|
|
}
|
|
} while ($foundAncestor);
|
|
|
|
return $reschedules
|
|
->filter(fn (EventDateChange $change): bool => $change->destination_event_date_id !== null
|
|
&& isset($destinationIds[(int) $change->destination_event_date_id]));
|
|
}
|
|
}
|