PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.5.21
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.5.21
2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 1.7.2 All 33 releases
fluent-booking / app / Services / Libs / RRule / RRuleTrait.php

RRuleTrait.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.5.21, at app/Services/Libs/RRule/RRuleTrait.php

232 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Licensed under the MIT license.
5 *
6 * For the full copyright and license information, please view the LICENSE file.
7 *
8 * @author Rémi Lanvin <remi@cloudconnected.fr>
9 * @link https://github.com/rlanvin/php-rrule
10 */
11
12 namespace FluentBooking\App\Services\Libs\RRule;
13
14 /**
15 * Implement the common methods of the RRuleInterface used by RRule and RSet
16 *
17 * @internal
18 */
19 trait RRuleTrait
20 {
21 /**
22 * Return all the occurrences in an array of \DateTime.
23 *
24 * @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
25 * @return array An array of \DateTime objects
26 */
27 public function getOccurrences($limit = null)
28 {
29 if (! $limit && $this->isInfinite()) {
30 throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
31 }
32 if ($limit !== null && $limit !== false && $limit < 0) {
33 throw new \InvalidArgumentException('$limit cannot be negative');
34 }
35
36 // cached version already computed
37 $iterator = $this;
38 if ($this->total !== null) {
39 $iterator = $this->cache;
40 }
41
42 $res = array();
43 $n = 0;
44 foreach ($iterator as $occurrence) {
45 $res[] = clone $occurrence; // we have to clone because DateTime is not immutable
46 $n += 1;
47 if ($limit && $n >= $limit) {
48 break;
49 }
50 }
51 return $res;
52 }
53
54 /**
55 * Return all the ocurrences after a date, before a date, or between two dates.
56 *
57 * @param mixed $begin Can be null to return all occurrences before $end
58 * @param mixed $end Can be null to return all occurrences after $begin
59 * @param int $limit Limit the resultset to n occurrences (0, null or false = everything)
60 * @return array An array of \DateTime objects
61 */
62 public function getOccurrencesBetween($begin, $end, $limit = null)
63 {
64 if ($begin !== null) {
65 $begin = self::parseDate($begin);
66 }
67
68 if ($end !== null) {
69 $end = self::parseDate($end);
70 }
71 elseif (! $limit && $this->isInfinite()) {
72 throw new \LogicException('Cannot get all occurrences of an infinite recurrence rule.');
73 }
74
75 if ($limit !== null && $limit !== false && $limit < 0) {
76 throw new \InvalidArgumentException('$limit cannot be negative');
77 }
78
79 $iterator = $this;
80 if ($this->total !== null) {
81 $iterator = $this->cache;
82 }
83
84 $res = array();
85 $n = 0;
86 foreach ($iterator as $occurrence) {
87 if ($begin !== null && $occurrence < $begin) {
88 continue;
89 }
90 if ($end !== null && $occurrence > $end) {
91 break;
92 }
93 $res[] = clone $occurrence;
94 $n += 1;
95 if ($limit && $n >= $limit) {
96 break;
97 }
98 }
99 return $res;
100 }
101
102 public function getOccurrencesAfter($date, $inclusive = false, $limit = null)
103 {
104 if ($inclusive || ! $this->occursAt($date)) {
105 return $this->getOccurrencesBetween($date, null, $limit);
106 }
107
108 if ($limit !== null) {
109 $limit += 1;
110 }
111 $occurrences = $this->getOccurrencesBetween($date, null, $limit);
112 return array_slice($occurrences, 1);
113 }
114
115 public function getNthOccurrenceAfter($date, $index)
116 {
117 if ($index <= 0) {
118 throw new \InvalidArgumentException("Index must be a positive integer");
119 }
120
121 $occurrences = $this->getOccurrencesAfter($date, false, $index);
122
123 return isset($occurrences[$index-1]) ? $occurrences[$index-1] : null;
124 }
125
126 public function getOccurrencesBefore($date, $inclusive = false, $limit = null)
127 {
128 // we need to get everything
129 $occurrences = $this->getOccurrencesBetween(null, $date);
130
131 if (! $inclusive && $this->occursAt($date)) {
132 array_pop($occurrences);
133 }
134
135 // the limit is counted from $date
136 if ($limit) {
137 $occurrences = array_slice($occurrences, -1 * $limit);
138 }
139
140 return $occurrences;
141 }
142
143 public function getNthOccurrenceBefore($date, $index)
144 {
145 if ($index <= 0) {
146 throw new \InvalidArgumentException("Index must be a positive integer");
147 }
148
149 $occurrences = $this->getOccurrencesBefore($date, false, $index);
150
151 if (sizeof($occurrences) < $index) {
152 return null;
153 }
154
155 return $occurrences[0];
156 }
157
158 public function getNthOccurrenceFrom($date, $index)
159 {
160 if (! is_numeric($index)) {
161 throw new \InvalidArgumentException('Malformed index (must be a numeric)');
162 }
163
164 if ($index == 0) {
165 return $this->occursAt($date) ? self::parseDate($date) : null;
166 }
167 elseif ($index > 0) {
168 return $this->getNthOccurrenceAfter($date, $index);
169 }
170 else {
171 return $this->getNthOccurrenceBefore($date, -1*$index);
172 }
173 }
174 /**
175 * Convert any date into a DateTime object.
176 *
177 * @param mixed $date
178 * @return \DateTimeInterface Returns a DateTimeImmutable if a DateTimeImmutable is passed, or DateTime otherwise
179 *
180 * @throws \InvalidArgumentException on error
181 */
182 static public function parseDate($date)
183 {
184 // DateTimeInterface is only on PHP 5.5+, and includes DateTimeImmutable
185 if (! $date instanceof \DateTime && ! $date instanceof \DateTimeInterface) {
186 try {
187 if (is_integer($date)) {
188 $date = \DateTime::createFromFormat('U',$date);
189 $date->setTimezone(new \DateTimeZone('UTC')); // default is +00:00 (see issue #15)
190 }
191 else {
192 $date = new \DateTime($date);
193 }
194 } catch (\Exception $e) { // PHP 5.6
195 throw new \InvalidArgumentException(
196 sprintf(
197 "Failed to parse the date (%s)",
198 wp_kses_post($e->getMessage())
199 )
200 );
201 } catch (\Throwable $e) { // PHP 7+
202 throw new \InvalidArgumentException(
203 sprintf(
204 "Failed to parse the date (%s)",
205 wp_kses_post($e->getMessage())
206 )
207 );
208 }
209 }
210 else {
211 $date = clone $date; // avoid reference problems
212 }
213
214 // ensure there is no microseconds in the DateTime object even if
215 // the input contained microseconds, to avoid date comparison issues
216 // (see #104)
217 if (version_compare(PHP_VERSION, '7.1.0') < 0) {
218 $date = new \DateTime($date->format('Y-m-d H:i:s'), $date->getTimezone());
219 }
220 else {
221 $date = $date->setTime(
222 $date->format('H'),
223 $date->format('i'),
224 $date->format('s'),
225 0
226 );
227 }
228
229 return $date;
230 }
231 }
232