| @@ -45,8 +45,15 @@ | ||
| 45 | 45 | */ |
| 46 | 46 | public $timezone = null; |
| 47 | 47 | |
| 48 | 48 | /** |
| 49 | + * Last iCalendar keyword parsed. | |
| 50 | + * | |
| 51 | + * @var string | |
| 52 | + */ | |
| 53 | + public $last_keyword; | |
| 54 | + | |
| 55 | + /** | |
| 49 | 56 | * Class constructor |
| 50 | 57 | * |
| 51 | 58 | * @return void |
| 52 | 59 | */ |
| @@ -64,9 +71,8 @@ | ||
| 64 | 71 | $count = (int) $count; |
| 65 | 72 | $transient_id = 'icalendar_vcal_' . md5( $url ) . '_' . $count; |
| 66 | 73 | |
| 67 | 74 | $vcal = get_transient( $transient_id ); |
| 68 | - $vcal = false; | |
| 69 | 75 | if ( ! empty( $vcal ) ) { |
| 70 | 76 | if ( isset( $vcal['TIMEZONE'] ) ) { |
| 71 | 77 | $this->timezone = $this->timezone_from_string( $vcal['TIMEZONE'] ); |
| 72 | 78 | } |
| @@ -146,15 +152,15 @@ | ||
| 146 | 152 | if ( 8 < strlen( $event['DTSTART'] ) ) { |
| 147 | 153 | $start_time = preg_replace( '/Z$/', '', $event['DTSTART'] ); |
| 148 | 154 | $start_time = new DateTime( $start_time, $this->timezone ); |
| 149 | 155 | $start_time->setTimeZone( $timezone ); |
| 150 | - | |
| 151 | - $end_time = preg_replace( '/Z$/', '', $event['DTEND'] ); | |
| 152 | - $end_time = new DateTime( $end_time, $this->timezone ); | |
| 153 | - $end_time->setTimeZone( $timezone ); | |
| 154 | - | |
| 155 | 156 | $event['DTSTART'] = $start_time->format( 'YmdHis\Z' ); |
| 156 | - $event['DTEND'] = $end_time->format( 'YmdHis\Z' ); | |
| 157 | + if ( isset( $event['DTEND'] ) ) { | |
| 158 | + $end_time = preg_replace( '/Z$/', '', $event['DTEND'] ); | |
| 159 | + $end_time = new DateTime( $end_time, $this->timezone ); | |
| 160 | + $end_time->setTimeZone( $timezone ); | |
| 161 | + $event['DTEND'] = $end_time->format( 'YmdHis\Z' ); | |
| 162 | + } | |
| 157 | 163 | } |
| 158 | 164 | |
| 159 | 165 | $offsetted_events[] = $event; |
| 160 | 166 | } |
| @@ -229,12 +235,12 @@ | ||
| 229 | 235 | continue; |
| 230 | 236 | } |
| 231 | 237 | |
| 232 | 238 | // Process events with RRULE before other events. |
| 233 | - $rrule = isset( $event['RRULE'] ) ? $event['RRULE'] : false; | |
| 234 | - $uid = $event['UID']; | |
| 239 | + $rrule = $event['RRULE'] ?? false; | |
| 240 | + $uid = $event['UID'] ?? false; | |
| 235 | 241 | |
| 236 | - if ( $rrule && ! in_array( $uid, $set_recurring_events, true ) ) { | |
| 242 | + if ( $rrule && $uid && ! in_array( $uid, $set_recurring_events, true ) ) { | |
| 237 | 243 | |
| 238 | 244 | // Break down the RRULE into digestible chunks. |
| 239 | 245 | $rrule_array = array(); |
| 240 | 246 | |
| @@ -242,10 +248,10 @@ | ||
| 242 | 248 | list( $rkey, $rvalue ) = explode( '=', $rline, 2 ); |
| 243 | 249 | $rrule_array[ $rkey ] = $rvalue; |
| 244 | 250 | } |
| 245 | 251 | |
| 246 | - $interval = ( isset( $rrule_array['INTERVAL'] ) ) ? $rrule_array['INTERVAL'] : 1; | |
| 247 | - $rrule_count = ( isset( $rrule_array['COUNT'] ) ) ? $rrule_array['COUNT'] : 0; | |
| 252 | + $interval = $rrule_array['INTERVAL'] ?? 1; | |
| 253 | + $rrule_count = $rrule_array['COUNT'] ?? 0; | |
| 248 | 254 | $until = ( isset( $rrule_array['UNTIL'] ) ) ? strtotime( $rrule_array['UNTIL'] ) : strtotime( '+1 year', $current ); |
| 249 | 255 | |
| 250 | 256 | // Used to bound event checks. |
| 251 | 257 | $echo_limit = 10; |
| @@ -268,9 +274,9 @@ | ||
| 268 | 274 | // Interval and count. |
| 269 | 275 | $catchup = floor( ( $current - strtotime( $event['DTSTART'] ) ) / ( $interval * DAY_IN_SECONDS ) ); |
| 270 | 276 | if ( $rrule_count && $catchup > 0 ) { |
| 271 | 277 | if ( $catchup < $rrule_count ) { |
| 272 | - $rrule_count = $rrule_count - $catchup; | |
| 278 | + $rrule_count -= $catchup; | |
| 273 | 279 | $recurring_event_date_start = date( |
| 274 | 280 | 'Ymd', |
| 275 | 281 | strtotime( |
| 276 | 282 | '+ ' . ( $interval * $catchup ) . ' days', |
| @@ -316,9 +322,9 @@ | ||
| 316 | 322 | // Interval and count. |
| 317 | 323 | $catchup = floor( ( $current - strtotime( $event['DTSTART'] ) ) / ( $interval * WEEK_IN_SECONDS ) ); |
| 318 | 324 | if ( $rrule_count && $catchup > 0 ) { |
| 319 | 325 | if ( ( $catchup * count( $bydays ) ) < $rrule_count ) { |
| 320 | - $rrule_count = $rrule_count - ( $catchup * count( $bydays ) ); // Estimate current event count. | |
| 326 | + $rrule_count -= $catchup * count( $bydays ); // Estimate current event count. | |
| 321 | 327 | $recurring_event_date_start = date( 'Ymd', strtotime( '+ ' . ( $interval * $catchup ) . ' weeks', strtotime( $event['DTSTART'] ) ) ) . date( '\THis', strtotime( $event['DTSTART'] ) ); |
| 322 | 328 | } else { |
| 323 | 329 | $noop = true; |
| 324 | 330 | } |
| @@ -340,19 +346,25 @@ | ||
| 340 | 346 | if ( $date_from_ics >= $current ) { |
| 341 | 347 | $recurring_event_date_start = date( 'Ymd\THis', strtotime( $event['DTSTART'] ) ); |
| 342 | 348 | } else { |
| 343 | 349 | // Describe the date in the month. |
| 344 | - if ( isset( $rrule_array['BYDAY'] ) ) { | |
| 345 | - $day_number = substr( $rrule_array['BYDAY'], 0, 1 ); | |
| 346 | - $week_day = substr( $rrule_array['BYDAY'], 1 ); | |
| 347 | - $day_cardinals = array( | |
| 348 | - 1 => 'first', | |
| 349 | - 2 => 'second', | |
| 350 | - 3 => 'third', | |
| 351 | - 4 => 'fourth', | |
| 352 | - 5 => 'fifth', | |
| 350 | + if ( isset( $rrule_array['BYDAY'] ) | |
| 351 | + && preg_match( '/^(-?\d)([A-Z]{2})/', $rrule_array['BYDAY'], $matches ) | |
| 352 | + ) { | |
| 353 | + $day_number = $matches[1]; | |
| 354 | + $week_day = $matches[2]; | |
| 355 | + | |
| 356 | + $day_cardinals = array( | |
| 357 | + -3 => 'third to last', | |
| 358 | + -2 => 'second to last', | |
| 359 | + -1 => 'last', | |
| 360 | + 1 => 'first', | |
| 361 | + 2 => 'second', | |
| 362 | + 3 => 'third', | |
| 363 | + 4 => 'fourth', | |
| 364 | + 5 => 'fifth', | |
| 353 | 365 | ); |
| 354 | - $weekdays = array( | |
| 366 | + $weekdays = array( | |
| 355 | 367 | 'SU' => 'Sunday', |
| 356 | 368 | 'MO' => 'Monday', |
| 357 | 369 | 'TU' => 'Tuesday', |
| 358 | 370 | 'WE' => 'Wednesday', |
| @@ -359,9 +371,12 @@ | ||
| 359 | 371 | 'TH' => 'Thursday', |
| 360 | 372 | 'FR' => 'Friday', |
| 361 | 373 | 'SA' => 'Saturday', |
| 362 | 374 | ); |
| 363 | - $event_date_desc = "{$day_cardinals[$day_number]} {$weekdays[$week_day]} of "; | |
| 375 | + | |
| 376 | + $day_cardinal = $day_cardinals[ $day_number ] ?? ''; | |
| 377 | + $weekday = $weekdays[ $week_day ] ?? ''; | |
| 378 | + $event_date_desc = "$day_cardinal $weekday of "; | |
| 364 | 379 | } else { |
| 365 | 380 | $event_date_desc = date( 'd ', strtotime( $event['DTSTART'] ) ); |
| 366 | 381 | } |
| 367 | 382 | |
| @@ -427,9 +442,9 @@ | ||
| 427 | 442 | $rrule_count = 10; |
| 428 | 443 | } |
| 429 | 444 | |
| 430 | 445 | // Set up EXDATE handling for the event. |
| 431 | - $exdates = ( isset( $event['EXDATE'] ) ) ? $event['EXDATE'] : array(); | |
| 446 | + $exdates = $event['EXDATE'] ?? array(); | |
| 432 | 447 | |
| 433 | 448 | for ( $i = 1; $i <= $echo_limit; $i++ ) { |
| 434 | 449 | |
| 435 | 450 | // Weeks need a daily loop and must check for inclusion in BYDAYS. |
| @@ -542,9 +557,9 @@ | ||
| 542 | 557 | } |
| 543 | 558 | $set_recurring_events[] = $uid; |
| 544 | 559 | |
| 545 | 560 | } |
| 546 | - } elseif ( strtotime( isset( $event['DTEND'] ) ? $event['DTEND'] : $event['DTSTART'] ) >= $current ) { // Process normal events. | |
| 561 | + } elseif ( strtotime( $event['DTEND'] ?? $event['DTSTART'] ) >= $current ) { // Process normal events. | |
| 547 | 562 | $upcoming[] = $event; |
| 548 | 563 | } |
| 549 | 564 | } |
| 550 | 565 | return $upcoming; |
| @@ -564,9 +579,9 @@ | ||
| 564 | 579 | if ( false !== wp_cache_get( $disable_get_key, $cache_group ) ) { |
| 565 | 580 | return false; |
| 566 | 581 | } |
| 567 | 582 | |
| 568 | - // rewrite webcal: URI schem to HTTP. | |
| 583 | + // rewrite webcal: URI scheme to HTTP. | |
| 569 | 584 | $url = preg_replace( '/^webcal/', 'http', $url ); |
| 570 | 585 | // try to fetch. |
| 571 | 586 | $r = wp_safe_remote_get( |
| 572 | 587 | $url, |
| @@ -760,9 +775,9 @@ | ||
| 760 | 775 | $tzid = false; |
| 761 | 776 | if ( 2 === count( $keyword ) ) { |
| 762 | 777 | $tparam = $keyword[1]; |
| 763 | 778 | |
| 764 | - if ( strpos( $tparam, 'TZID' ) !== false ) { | |
| 779 | + if ( str_contains( $tparam, 'TZID' ) ) { | |
| 765 | 780 | $tzid = $this->timezone_from_string( str_replace( 'TZID=', '', $tparam ) ); |
| 766 | 781 | } |
| 767 | 782 | } |
| 768 | 783 | |