Scheduler::isOccurring()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 2
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Adlogix\EventScheduler;
6
7
use Adlogix\EventScheduler\DateRange\DateRange;
8
use Adlogix\EventScheduler\DateRange\DateRangeIterator;
9
use Adlogix\EventScheduler\DateRange\DateRangeReverseIterator;
10
use Adlogix\EventScheduler\TemporalExpression\TemporalExpressionInterface;
11
use DateInterval;
12
use DateTimeImmutable;
13
use DateTimeInterface;
14
use Traversable;
15
16
/**
17
 * @author Toni Van de Voorde <[email protected]>
18
 */
19
final class Scheduler implements SchedulerInterface
20
{
21
    /**
22
     * @var SchedulableEventCollection
23
     */
24
    private $scheduledEvents;
25
26 12
    public function __construct()
27
    {
28 12
        $this->scheduledEvents = new SchedulableEventCollection();
29 12
    }
30
31
    /**
32
     * {@inheritdoc}
33
     */
34 8
    public function schedule(
35
        EventInterface $event,
36
        TemporalExpressionInterface $temporalExpression
37
    ): SchedulableEvent {
38 8
        $schedulableEvent = new SchedulableEvent($event, $temporalExpression);
39 8
        $this->scheduledEvents->add($schedulableEvent);
40
41 8
        return $schedulableEvent;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 2
    public function cancel(SchedulableEvent $schedulableEvent): void
48
    {
49 2
        $this->scheduledEvents->remove($schedulableEvent);
50 1
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 1
    public function isScheduled(EventInterface $event): bool
56
    {
57 1
        $scheduledEvents = $this->scheduledEvents->filterByEvent($event);
58
59 1
        return count($scheduledEvents) > 0;
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65 10
    public function isOccurring(EventInterface $event, DateTimeInterface $date): bool
66
    {
67 10
        $scheduledEvents = $this->scheduledEvents->filterByEvent($event);
68 10
        foreach ($scheduledEvents as $scheduledEvent) {
69 7
            if ($scheduledEvent->isOccurring($event, $date)) {
70 7
                return true;
71
            }
72
        }
73
74 9
        return false;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80 1
    public function eventsForDate(DateTimeInterface $date): Traversable
81
    {
82 1
        foreach ($this->scheduledEvents as $scheduledEvent) {
83 1
            $event = $scheduledEvent->event();
84 1
            if ($this->isOccurring($event, $date)) {
85 1
                yield $event;
86
            }
87
        }
88 1
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93 1
    public function dates(EventInterface $event, DateRange $range): Traversable
94
    {
95 1
        $iterator = $this->createDateRangeIterator($range);
96
97 1
        while ($iterator->valid()) {
98
99 1
            if ($this->isOccurring($event, $iterator->current())) {
100 1
                $foundDates = $iterator->current();
101 1
                yield $foundDates;
102
            }
103 1
            $iterator->next();
104
        }
105 1
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110 3
    public function nextOccurrence(
111
        EventInterface $event,
112
        DateRange $range
113
    ): DateTimeImmutable {
114 3
        return $this->findNextOccurrenceInIterator(
115 3
            $event,
116 3
            $this->createDateRangeIterator($range)
117
        );
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123 2
    public function previousOccurrence(
124
        EventInterface $event,
125
        DateRange $range
126
    ): DateTimeImmutable {
127 2
        return $this->findNextOccurrenceInIterator(
128 2
            $event,
129 2
            $this->createDateRangeReverseIterator($range)
130
        );
131
    }
132
133
    /**
134
     * @param DateRange $range
135
     * @return DateRangeIterator
136
     * @throws \Exception
137
     */
138 4
    private function createDateRangeIterator(
139
        DateRange $range
140
    ): DateRangeIterator {
141 4
        return new DateRangeIterator($range, new DateInterval('P1D'));
142
    }
143
144
    /**
145
     * @param DateRange $range
146
     * @return DateRangeReverseIterator
147
     * @throws \Exception
148
     */
149 2
    private function createDateRangeReverseIterator(
150
        DateRange $range
151
    ): DateRangeReverseIterator {
152 2
        return new DateRangeReverseIterator($range, new DateInterval('P1D'));
153
    }
154
155
    /**
156
     * @param EventInterface $event
157
     * @param Traversable    $dates
158
     * @return DateTimeImmutable
159
     */
160 5
    private function findNextOccurrenceInIterator(EventInterface $event, Traversable $dates): DateTimeImmutable
161
    {
162 5
        foreach ($dates as $date) {
163 5
            if ($this->isOccurring($event, $date)) {
164 5
                return $date;
165
            }
166
        }
167
168 3
        throw Exception\NotFoundEventOccurrenceException::create();
169
    }
170
}
171