<?php
namespace App\Calendar;
use App\Calendar\Event\EventContext;
use App\Calendar\Model\CalendarEvent;
use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonPeriod;
class Calendar
{
protected $events;
protected $month;
protected $eventContext;
public function __construct(EventContext $eventContext)
{
$this->eventContext = $eventContext;
}
public function getEvents()
{
return $this->events;
}
public function setEvents($events)
{
$this->events = $events;
}
public function getMonth()
{
return $this->month;
}
public function setMonth(CarbonImmutable $month)
{
$this->month = $month;
}
public function generateEvents(array $objects)
{
$this->events = array_map(function ($event) {
return $this->eventContext->handle($event);
}, $objects);
return $this->events;
}
public function getEventsForWeek(CarbonPeriod $week)
{
$events = [];
foreach ($this->events as $event) {
$gridPosition = $this->getGridPositionForEventInWeek($event, $week);
if (!$gridPosition) {
continue;
}
$events[] = [
'event' => $event,
'grid' => $gridPosition,
];
}
return $events;
}
public function getGridPositionForEventInWeek(CalendarEvent $event, CarbonPeriod $week)
{
$eventPeriod = $event->getPeriod();
if (!$eventPeriod->overlaps($week)) {
return null;
}
$latestStartDate = new CarbonImmutable(max($eventPeriod->getStartDate(), $week->getStartDate()));
$firstEndDate = new CarbonImmutable(min($eventPeriod->calculateEnd(), $week->calculateEnd()));
return [
'start' => $latestStartDate->dayOfWeekIso,
'end' => $firstEndDate->dayOfWeekIso,
];
}
public function getWeeksWithEvents()
{
$calendarStart = $this->month->startOfMonth()->startOfWeek(Carbon::MONDAY);
$weeks = [];
$weekWalker = new Carbon($calendarStart);
for ($i = 0; $i < 5; ++$i) {
$weekPeriod = CarbonPeriod::create($weekWalker->startOfWeek()->copy(), $weekWalker->endOfWeek()->copy());
$weeks[$weekWalker->weekOfYear] = [
'period' => $weekPeriod,
'events' => $this->getEventsForWeek($weekPeriod),
];
$weekWalker->addWeek();
}
return $weeks;
}
public function getDaysWithEvents()
{
$calendarStart = $this->month->startOfMonth()->startOfWeek(Carbon::MONDAY);
$calendarEnd = $this->month->endOfMonth()->endOfWeek(Carbon::MONDAY);
$calendarPeriod = new CarbonPeriod($calendarStart, $calendarEnd);
$entries = [];
foreach ($calendarPeriod as $day) {
$entry = [
'day' => $day,
];
foreach ($this->events as $event) {
if ($day->between($event->start->startOfDay(), $event->end)) {
$entry['events'][] = $event;
}
}
if (array_key_exists('events', $entry)) {
$entries[] = $entry;
}
}
return $entries;
}
}