This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the eluceo/iCal package. |
||
5 | * |
||
6 | * (c) Markus Poerschke <[email protected]> |
||
7 | * |
||
8 | * This source file is subject to the MIT license that is bundled |
||
9 | * with this source code in the file LICENSE. |
||
10 | */ |
||
11 | |||
12 | namespace Eluceo\iCal\Property\Event; |
||
13 | |||
14 | use Eluceo\iCal\ParameterBag; |
||
15 | use Eluceo\iCal\Property\ValueInterface; |
||
16 | use InvalidArgumentException; |
||
17 | |||
18 | /** |
||
19 | * Implementation of Recurrence Rule. |
||
20 | * |
||
21 | * @see https://tools.ietf.org/html/rfc5545#section-3.8.5.3 |
||
22 | */ |
||
23 | class RecurrenceRule implements ValueInterface |
||
24 | { |
||
25 | const FREQ_YEARLY = 'YEARLY'; |
||
26 | const FREQ_MONTHLY = 'MONTHLY'; |
||
27 | const FREQ_WEEKLY = 'WEEKLY'; |
||
28 | const FREQ_DAILY = 'DAILY'; |
||
29 | const FREQ_HOURLY = 'HOURLY'; |
||
30 | const FREQ_MINUTELY = 'MINUTELY'; |
||
31 | const FREQ_SECONDLY = 'SECONDLY'; |
||
32 | |||
33 | const WEEKDAY_SUNDAY = 'SU'; |
||
34 | const WEEKDAY_MONDAY = 'MO'; |
||
35 | const WEEKDAY_TUESDAY = 'TU'; |
||
36 | const WEEKDAY_WEDNESDAY = 'WE'; |
||
37 | const WEEKDAY_THURSDAY = 'TH'; |
||
38 | const WEEKDAY_FRIDAY = 'FR'; |
||
39 | const WEEKDAY_SATURDAY = 'SA'; |
||
40 | |||
41 | /** |
||
42 | * The frequency of an Event. |
||
43 | * |
||
44 | * @var string |
||
45 | */ |
||
46 | protected $freq = self::FREQ_YEARLY; |
||
47 | |||
48 | /** |
||
49 | * BYSETPOS must require use of other BY*. |
||
50 | * |
||
51 | * @var bool |
||
52 | */ |
||
53 | protected $canUseBySetPos = false; |
||
54 | |||
55 | /** |
||
56 | * @var int|null |
||
57 | */ |
||
58 | protected $interval = 1; |
||
59 | |||
60 | /** |
||
61 | * @var int|null |
||
62 | */ |
||
63 | protected $count = null; |
||
64 | |||
65 | /** |
||
66 | * @var \DateTimeInterface|null |
||
67 | */ |
||
68 | protected $until = null; |
||
69 | |||
70 | /** |
||
71 | * @var string|null |
||
72 | */ |
||
73 | protected $wkst; |
||
74 | |||
75 | /** |
||
76 | * @var array|null |
||
77 | */ |
||
78 | protected $bySetPos = null; |
||
79 | |||
80 | /** |
||
81 | * @var string|null |
||
82 | */ |
||
83 | protected $byMonth; |
||
84 | |||
85 | /** |
||
86 | * @var string|null |
||
87 | */ |
||
88 | protected $byWeekNo; |
||
89 | |||
90 | /** |
||
91 | * @var string|null |
||
92 | */ |
||
93 | protected $byYearDay; |
||
94 | |||
95 | /** |
||
96 | * @var string|null |
||
97 | */ |
||
98 | protected $byMonthDay; |
||
99 | |||
100 | /** |
||
101 | * @var string|null |
||
102 | */ |
||
103 | protected $byDay; |
||
104 | |||
105 | /** |
||
106 | * @var string|null |
||
107 | */ |
||
108 | protected $byHour; |
||
109 | |||
110 | /** |
||
111 | * @var string|null |
||
112 | */ |
||
113 | protected $byMinute; |
||
114 | |||
115 | /** |
||
116 | * @var string|null |
||
117 | */ |
||
118 | protected $bySecond; |
||
119 | |||
120 | 11 | public function getEscapedValue(): string |
|
121 | { |
||
122 | 11 | return $this->buildParameterBag()->toString(); |
|
123 | } |
||
124 | |||
125 | /** |
||
126 | * @return ParameterBag |
||
127 | */ |
||
128 | 11 | protected function buildParameterBag() |
|
129 | { |
||
130 | 11 | $parameterBag = new ParameterBag(); |
|
131 | |||
132 | 11 | $parameterBag->setParam('FREQ', $this->freq); |
|
133 | |||
134 | 11 | if (null !== $this->interval) { |
|
135 | 10 | $parameterBag->setParam('INTERVAL', $this->interval); |
|
136 | } |
||
137 | |||
138 | 11 | if (null !== $this->count) { |
|
139 | 1 | $parameterBag->setParam('COUNT', $this->count); |
|
140 | } |
||
141 | |||
142 | 11 | if (null != $this->until) { |
|
143 | 1 | $parameterBag->setParam('UNTIL', $this->until->format('Ymd\THis\Z')); |
|
144 | } |
||
145 | |||
146 | 11 | if (null !== $this->wkst) { |
|
147 | 1 | $parameterBag->setParam('WKST', $this->wkst); |
|
148 | } |
||
149 | |||
150 | 11 | if (null !== $this->bySetPos && $this->canUseBySetPos) { |
|
151 | $parameterBag->setParam('BYSETPOS', $this->bySetPos); |
||
152 | } |
||
153 | |||
154 | 11 | if (null !== $this->byMonth) { |
|
155 | 1 | $parameterBag->setParam('BYMONTH', explode(',', $this->byMonth)); |
|
156 | } |
||
157 | |||
158 | 11 | if (null !== $this->byWeekNo) { |
|
159 | 1 | $parameterBag->setParam('BYWEEKNO', explode(',', $this->byWeekNo)); |
|
160 | } |
||
161 | |||
162 | 11 | if (null !== $this->byYearDay) { |
|
163 | 1 | $parameterBag->setParam('BYYEARDAY', explode(',', $this->byYearDay)); |
|
164 | } |
||
165 | |||
166 | 11 | if (null !== $this->byMonthDay) { |
|
167 | 1 | $parameterBag->setParam('BYMONTHDAY', explode(',', $this->byMonthDay)); |
|
168 | } |
||
169 | |||
170 | 11 | if (null !== $this->byDay) { |
|
171 | 1 | $parameterBag->setParam('BYDAY', explode(',', $this->byDay)); |
|
172 | } |
||
173 | |||
174 | 11 | if (null !== $this->byHour) { |
|
175 | 1 | $parameterBag->setParam('BYHOUR', explode(',', $this->byHour)); |
|
176 | } |
||
177 | |||
178 | 11 | if (null !== $this->byMinute) { |
|
179 | 1 | $parameterBag->setParam('BYMINUTE', explode(',', $this->byMinute)); |
|
180 | } |
||
181 | |||
182 | 11 | if (null !== $this->bySecond) { |
|
183 | 1 | $parameterBag->setParam('BYSECOND', explode(',', $this->bySecond)); |
|
184 | } |
||
185 | |||
186 | 11 | return $parameterBag; |
|
187 | } |
||
188 | |||
189 | /** |
||
190 | * @param int|null $count |
||
191 | * |
||
192 | * @return $this |
||
193 | */ |
||
194 | 1 | public function setCount($count) |
|
195 | { |
||
196 | 1 | $this->count = $count; |
|
197 | |||
198 | 1 | return $this; |
|
199 | } |
||
200 | |||
201 | /** |
||
202 | * @return int|null |
||
203 | */ |
||
204 | 2 | public function getCount() |
|
205 | { |
||
206 | 2 | return $this->count; |
|
207 | } |
||
208 | |||
209 | /** |
||
210 | * @return $this |
||
211 | */ |
||
212 | 2 | public function setUntil(\DateTimeInterface $until = null) |
|
213 | { |
||
214 | 2 | $this->until = $until; |
|
215 | |||
216 | 2 | return $this; |
|
217 | } |
||
218 | |||
219 | /** |
||
220 | * @return \DateTimeInterface|null |
||
221 | */ |
||
222 | 1 | public function getUntil() |
|
223 | { |
||
224 | 1 | return $this->until; |
|
225 | } |
||
226 | |||
227 | /** |
||
228 | * The FREQ rule part identifies the type of recurrence rule. This |
||
229 | * rule part MUST be specified in the recurrence rule. Valid values |
||
230 | * include. |
||
231 | * |
||
232 | * SECONDLY, to specify repeating events based on an interval of a second or more; |
||
233 | * MINUTELY, to specify repeating events based on an interval of a minute or more; |
||
234 | * HOURLY, to specify repeating events based on an interval of an hour or more; |
||
235 | * DAILY, to specify repeating events based on an interval of a day or more; |
||
236 | * WEEKLY, to specify repeating events based on an interval of a week or more; |
||
237 | * MONTHLY, to specify repeating events based on an interval of a month or more; |
||
238 | * YEARLY, to specify repeating events based on an interval of a year or more. |
||
239 | * |
||
240 | * @param string $freq |
||
241 | * |
||
242 | * @return $this |
||
243 | * |
||
244 | * @throws \InvalidArgumentException |
||
245 | */ |
||
246 | 4 | public function setFreq($freq) |
|
247 | { |
||
248 | 4 | if (@constant('static::FREQ_' . $freq) !== null) { |
|
249 | 3 | $this->freq = $freq; |
|
250 | } else { |
||
251 | 1 | throw new \InvalidArgumentException("The Frequency {$freq} is not supported."); |
|
252 | } |
||
253 | |||
254 | 3 | return $this; |
|
255 | } |
||
256 | |||
257 | /** |
||
258 | * @return string |
||
259 | */ |
||
260 | 1 | public function getFreq() |
|
261 | { |
||
262 | 1 | return $this->freq; |
|
263 | } |
||
264 | |||
265 | /** |
||
266 | * The INTERVAL rule part contains a positive integer representing at |
||
267 | * which intervals the recurrence rule repeats. |
||
268 | * |
||
269 | * @param int|null $interval |
||
270 | * |
||
271 | * @return $this |
||
272 | */ |
||
273 | 3 | public function setInterval($interval) |
|
274 | { |
||
275 | 3 | $this->interval = $interval; |
|
276 | |||
277 | 3 | return $this; |
|
278 | } |
||
279 | |||
280 | /** |
||
281 | * @return int|null |
||
282 | */ |
||
283 | 1 | public function getInterval() |
|
284 | { |
||
285 | 1 | return $this->interval; |
|
286 | } |
||
287 | |||
288 | /** |
||
289 | * The WKST rule part specifies the day on which the workweek starts. |
||
290 | * Valid values are MO, TU, WE, TH, FR, SA, and SU. |
||
291 | * |
||
292 | * @param string $value |
||
293 | * |
||
294 | * @return $this |
||
295 | */ |
||
296 | 1 | public function setWkst($value) |
|
297 | { |
||
298 | 1 | $this->wkst = $value; |
|
299 | |||
300 | 1 | return $this; |
|
301 | } |
||
302 | |||
303 | /** |
||
304 | * The BYSETPOS filters one interval of events by the specified position. |
||
305 | * A positive position will start from the beginning and go forward while |
||
306 | * a negative position will start at the end and move backward. |
||
307 | * |
||
308 | * Valid values are a comma separated string or an array of integers |
||
309 | * from 1 to 366 or negative integers from -1 to -366. |
||
310 | * |
||
311 | * @param int|string|array|null $value |
||
312 | * |
||
313 | * @throws InvalidArgumentException |
||
314 | * |
||
315 | * @return $this |
||
316 | */ |
||
317 | public function setBySetPos($value) |
||
318 | { |
||
319 | if (null === $value) { |
||
320 | $this->bySetPos = $value; |
||
321 | |||
322 | return $this; |
||
323 | } |
||
324 | |||
325 | if (!(is_string($value) || is_array($value) || is_int($value))) { |
||
326 | throw new InvalidArgumentException('Invalid value for BYSETPOS'); |
||
327 | } |
||
328 | |||
329 | $list = $value; |
||
330 | |||
331 | if (is_int($value)) { |
||
332 | if ($value === 0 || $value < -366 || $value > 366) { |
||
333 | throw new InvalidArgumentException('Invalid value for BYSETPOS'); |
||
334 | } |
||
335 | $this->bySetPos = [$value]; |
||
336 | |||
337 | return $this; |
||
338 | } |
||
339 | |||
340 | if (is_string($value)) { |
||
341 | $list = explode(',', $value); |
||
342 | } |
||
343 | |||
344 | $output = []; |
||
345 | |||
346 | foreach ($list as $item) { |
||
0 ignored issues
–
show
|
|||
347 | if (is_string($item)) { |
||
348 | if (!preg_match('/^ *-?[0-9]* *$/', $item)) { |
||
349 | throw new InvalidArgumentException('Invalid value for BYSETPOS'); |
||
350 | } |
||
351 | $item = intval($item); |
||
352 | } |
||
353 | |||
354 | if (!is_int($item) || $item === 0 || $item < -366 || $item > 366) { |
||
355 | throw new InvalidArgumentException('Invalid value for BYSETPOS'); |
||
356 | } |
||
357 | |||
358 | $output[] = $item; |
||
359 | } |
||
360 | |||
361 | $this->bySetPos = $output; |
||
362 | |||
363 | return $this; |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | * The BYMONTH rule part specifies a COMMA-separated list of months of the year. |
||
368 | * Valid values are 1 to 12. |
||
369 | * |
||
370 | * @param int $month |
||
371 | * |
||
372 | * @throws \InvalidArgumentException |
||
373 | * |
||
374 | * @return $this |
||
375 | */ |
||
376 | 6 | public function setByMonth($month) |
|
377 | { |
||
378 | 6 | if (!is_integer($month) || $month <= 0 || $month > 12) { |
|
379 | 5 | throw new InvalidArgumentException('Invalid value for BYMONTH'); |
|
380 | } |
||
381 | |||
382 | 1 | $this->byMonth = $month; |
|
0 ignored issues
–
show
It seems like
$month of type integer is incompatible with the declared type string|null of property $byMonth .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
383 | |||
384 | 1 | $this->canUseBySetPos = true; |
|
385 | |||
386 | 1 | return $this; |
|
387 | } |
||
388 | |||
389 | /** |
||
390 | * The BYWEEKNO rule part specifies a COMMA-separated list of ordinals specifying weeks of the year. |
||
391 | * Valid values are 1 to 53 or -53 to -1. |
||
392 | * |
||
393 | * @param int $value |
||
394 | * |
||
395 | * @throws \InvalidArgumentException |
||
396 | * |
||
397 | * @return $this |
||
398 | */ |
||
399 | 5 | View Code Duplication | public function setByWeekNo($value) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
400 | { |
||
401 | 5 | if (!is_integer($value) || $value > 53 || $value < -53 || $value === 0) { |
|
402 | 4 | throw new InvalidArgumentException('Invalid value for BYWEEKNO'); |
|
403 | } |
||
404 | |||
405 | 1 | $this->byWeekNo = $value; |
|
0 ignored issues
–
show
It seems like
$value of type integer is incompatible with the declared type string|null of property $byWeekNo .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
406 | |||
407 | 1 | $this->canUseBySetPos = true; |
|
408 | |||
409 | 1 | return $this; |
|
410 | } |
||
411 | |||
412 | /** |
||
413 | * The BYYEARDAY rule part specifies a COMMA-separated list of days of the year. |
||
414 | * Valid values are 1 to 366 or -366 to -1. |
||
415 | * |
||
416 | * @param int $day |
||
417 | * |
||
418 | * @throws \InvalidArgumentException |
||
419 | * |
||
420 | * @return $this |
||
421 | */ |
||
422 | 5 | View Code Duplication | public function setByYearDay($day) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
423 | { |
||
424 | 5 | if (!is_integer($day) || $day > 366 || $day < -366 || $day === 0) { |
|
425 | 4 | throw new InvalidArgumentException('Invalid value for BYYEARDAY'); |
|
426 | } |
||
427 | |||
428 | 1 | $this->byYearDay = $day; |
|
0 ignored issues
–
show
It seems like
$day of type integer is incompatible with the declared type string|null of property $byYearDay .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
429 | |||
430 | 1 | $this->canUseBySetPos = true; |
|
431 | |||
432 | 1 | return $this; |
|
433 | } |
||
434 | |||
435 | /** |
||
436 | * The BYMONTHDAY rule part specifies a COMMA-separated list of days of the month. |
||
437 | * Valid values are 1 to 31 or -31 to -1. |
||
438 | * |
||
439 | * @param int $day |
||
440 | * |
||
441 | * @return $this |
||
442 | * |
||
443 | * @throws \InvalidArgumentException |
||
444 | */ |
||
445 | 5 | View Code Duplication | public function setByMonthDay($day) |
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
446 | { |
||
447 | 5 | if (!is_integer($day) || $day > 31 || $day < -31 || $day === 0) { |
|
448 | 4 | throw new InvalidArgumentException('Invalid value for BYMONTHDAY'); |
|
449 | } |
||
450 | |||
451 | 1 | $this->byMonthDay = $day; |
|
0 ignored issues
–
show
It seems like
$day of type integer is incompatible with the declared type string|null of property $byMonthDay .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
452 | |||
453 | 1 | $this->canUseBySetPos = true; |
|
454 | |||
455 | 1 | return $this; |
|
456 | } |
||
457 | |||
458 | /** |
||
459 | * The BYDAY rule part specifies a COMMA-separated list of days of the week;. |
||
460 | * |
||
461 | * SU indicates Sunday; MO indicates Monday; TU indicates Tuesday; |
||
462 | * WE indicates Wednesday; TH indicates Thursday; FR indicates Friday; and SA indicates Saturday. |
||
463 | * |
||
464 | * Each BYDAY value can also be preceded by a positive (+n) or negative (-n) integer. |
||
465 | * If present, this indicates the nth occurrence of a specific day within the MONTHLY or YEARLY "RRULE". |
||
466 | * |
||
467 | * @return $this |
||
468 | */ |
||
469 | 1 | public function setByDay(string $day) |
|
470 | { |
||
471 | 1 | $this->byDay = $day; |
|
472 | |||
473 | 1 | $this->canUseBySetPos = true; |
|
474 | |||
475 | 1 | return $this; |
|
476 | } |
||
477 | |||
478 | /** |
||
479 | * The BYHOUR rule part specifies a COMMA-separated list of hours of the day. |
||
480 | * Valid values are 0 to 23. |
||
481 | * |
||
482 | * @param int $value |
||
483 | * |
||
484 | * @return $this |
||
485 | * |
||
486 | * @throws \InvalidArgumentException |
||
487 | */ |
||
488 | 4 | public function setByHour($value) |
|
489 | { |
||
490 | 4 | if (!is_integer($value) || $value < 0 || $value > 23) { |
|
491 | 3 | throw new \InvalidArgumentException('Invalid value for BYHOUR'); |
|
492 | } |
||
493 | |||
494 | 1 | $this->byHour = $value; |
|
0 ignored issues
–
show
It seems like
$value of type integer is incompatible with the declared type string|null of property $byHour .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
495 | |||
496 | 1 | $this->canUseBySetPos = true; |
|
497 | |||
498 | 1 | return $this; |
|
499 | } |
||
500 | |||
501 | /** |
||
502 | * The BYMINUTE rule part specifies a COMMA-separated list of minutes within an hour. |
||
503 | * Valid values are 0 to 59. |
||
504 | * |
||
505 | * @param int $value |
||
506 | * |
||
507 | * @return $this |
||
508 | * |
||
509 | * @throws \InvalidArgumentException |
||
510 | */ |
||
511 | 4 | public function setByMinute($value) |
|
512 | { |
||
513 | 4 | if (!is_integer($value) || $value < 0 || $value > 59) { |
|
514 | 3 | throw new \InvalidArgumentException('Invalid value for BYMINUTE'); |
|
515 | } |
||
516 | |||
517 | 1 | $this->byMinute = $value; |
|
0 ignored issues
–
show
It seems like
$value of type integer is incompatible with the declared type string|null of property $byMinute .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
518 | |||
519 | 1 | $this->canUseBySetPos = true; |
|
520 | |||
521 | 1 | return $this; |
|
522 | } |
||
523 | |||
524 | /** |
||
525 | * The BYSECOND rule part specifies a COMMA-separated list of seconds within a minute. |
||
526 | * Valid values are 0 to 60. |
||
527 | * |
||
528 | * @param int $value |
||
529 | * |
||
530 | * @return $this |
||
531 | * |
||
532 | * @throws \InvalidArgumentException |
||
533 | */ |
||
534 | 4 | public function setBySecond($value) |
|
535 | { |
||
536 | 4 | if (!is_integer($value) || $value < 0 || $value > 60) { |
|
537 | 3 | throw new \InvalidArgumentException('Invalid value for BYSECOND'); |
|
538 | } |
||
539 | |||
540 | 1 | $this->bySecond = $value; |
|
0 ignored issues
–
show
It seems like
$value of type integer is incompatible with the declared type string|null of property $bySecond .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
541 | |||
542 | 1 | $this->canUseBySetPos = true; |
|
543 | |||
544 | 1 | return $this; |
|
545 | } |
||
546 | } |
||
547 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.