diff options
Diffstat (limited to 'modules-available/locationinfo/inc/icalparser.inc.php')
-rw-r--r-- | modules-available/locationinfo/inc/icalparser.inc.php | 151 |
1 files changed, 54 insertions, 97 deletions
diff --git a/modules-available/locationinfo/inc/icalparser.inc.php b/modules-available/locationinfo/inc/icalparser.inc.php index 0be8777b..eacb67b1 100644 --- a/modules-available/locationinfo/inc/icalparser.inc.php +++ b/modules-available/locationinfo/inc/icalparser.inc.php @@ -23,7 +23,6 @@ class ICalParser const ICAL_DATE_TIME_TEMPLATE = 'TZID=%s:'; const ISO_8601_WEEK_START = 'MO'; const RECURRENCE_EVENT = 'Generated recurrence event'; - const TIME_FORMAT = 'His'; const TIME_ZONE_UTC = 'UTC'; const UNIX_FORMAT = 'U'; @@ -481,15 +480,12 @@ class ICalParser /** * Creates the ICal object * - * @param mixed $files * @param array $options * @return void * @throws Exception */ public function __construct(array $options = array()) { - ini_set('auto_detect_line_endings', '1'); - foreach ($options as $option => $value) { if (in_array($option, self::$configurableOptions)) { $this->{$option} = $value; @@ -501,10 +497,7 @@ class ICalParser $this->defaultTimeZone = date_default_timezone_get(); } - // Ideally you would use `PHP_INT_MIN` from PHP 7 - $php_int_min = -2147483648; - - $this->windowMinTimestamp = is_null($this->filterDaysBefore) ? $php_int_min : (new DateTime('now'))->sub(new DateInterval('P' . $this->filterDaysBefore . 'D'))->getTimestamp(); + $this->windowMinTimestamp = is_null($this->filterDaysBefore) ? PHP_INT_MIN : (new DateTime('now'))->sub(new DateInterval('P' . $this->filterDaysBefore . 'D'))->getTimestamp(); $this->windowMaxTimestamp = is_null($this->filterDaysAfter) ? PHP_INT_MAX : (new DateTime('now'))->add(new DateInterval('P' . $this->filterDaysAfter . 'D'))->getTimestamp(); $this->shouldFilterByWindow = !is_null($this->filterDaysBefore) || !is_null($this->filterDaysAfter); @@ -516,7 +509,7 @@ class ICalParser * * @param string $data */ - public function feedData($data) + public function feedData(string $data) { $this->feedBuffer .= $data; $start = 0; @@ -581,7 +574,7 @@ class ICalParser * * @return bool */ - public function isValid() + public function isValid(): bool { return $this->hasSeenStart; } @@ -591,7 +584,7 @@ class ICalParser * * @param string $line */ - protected function handleLine($line) + protected function handleLine(string $line) { $line = rtrim($line); // Trim trailing whitespace $line = $this->removeUnprintableChars($line); @@ -602,18 +595,18 @@ class ICalParser $add = $this->keyValueFromString($line); - if ($add === false) { + if ($add === null) { return; } - $keyword = $add[0]; + $keyword = $add[0]; // string $values = $add[1]; // May be an array containing multiple values if (!is_array($values)) { if (!empty($values)) { $values = array($values); // Make an array as not already $blankArray = array(); // Empty placeholder array - array_push($values, $blankArray); + $values[] = $blankArray; } else { $values = array(); // Use blank array to ignore this line } @@ -752,16 +745,9 @@ class ICalParser foreach ($events as $key => $anEvent) { if ($anEvent === null) { unset($events[$key]); - - continue; - } - - if ($this->doesEventStartOutsideWindow($anEvent)) { + } elseif ($this->doesEventStartOutsideWindow($anEvent)) { $this->eventCount--; - unset($events[$key]); - - continue; } } @@ -776,7 +762,7 @@ class ICalParser * @param array $event * @return boolean */ - protected function doesEventStartOutsideWindow(array $event) + protected function doesEventStartOutsideWindow(array $event): bool { return !isset($event['DTSTART']) || !$this->isValidDate($event['DTSTART']) || $this->isOutOfRange($event['DTSTART'], $this->windowMinTimestamp, $this->windowMaxTimestamp); @@ -790,7 +776,7 @@ class ICalParser * @param integer $maxTimestamp * @return boolean */ - protected function isOutOfRange($calendarDate, $minTimestamp, $maxTimestamp) + protected function isOutOfRange(string $calendarDate, int $minTimestamp, int $maxTimestamp): bool { $timestamp = strtotime(explode('T', $calendarDate)[0]); @@ -798,36 +784,15 @@ class ICalParser } /** - * Unfolds an iCal file in preparation for parsing - * (https://icalendar.org/iCalendar-RFC-5545/3-1-content-lines.html) - * - * @param array $lines - * @return array - */ - protected function unfold(array $lines) - { - $string = implode(PHP_EOL, $lines); - $string = preg_replace('/' . PHP_EOL . '[ \t]/', '', $string); - - $lines = explode(PHP_EOL, $string); - - return $lines; - } - - /** * Add one key and value pair to the `$this->cal` array * * @param string $component - * @param string|boolean $keyword - * @param string $value + * @param string $keyword + * @param string|string[] $value * @return void */ - protected function addCalendarComponentWithKeyAndValue($component, $keyword, $value) + protected function addCalendarComponentWithKeyAndValue(string $component, string $keyword, $value) { - if ($keyword == false) { - $keyword = $this->lastKeyword; - } - switch ($component) { case 'VALARM': $key1 = 'VEVENT'; @@ -840,7 +805,7 @@ class ICalParser if (is_array($value)) { // Add array of properties to the end - array_push($this->cal[$key1][$key2][$key3]["{$keyword}_array"], $value); + $this->cal[$key1][$key2][$key3]["{$keyword}_array"][] = $value; } else { if (!isset($this->cal[$key1][$key2][$key3][$keyword])) { $this->cal[$key1][$key2][$key3][$keyword] = $value; @@ -862,7 +827,7 @@ class ICalParser if (is_array($value)) { // Add array of properties to the end - array_push($this->cal[$key1][$key2]["{$keyword}_array"], $value); + $this->cal[$key1][$key2]["{$keyword}_array"][] = $value; } else { if (!isset($this->cal[$key1][$key2][$keyword])) { $this->cal[$key1][$key2][$keyword] = $value; @@ -882,7 +847,7 @@ class ICalParser if ($keyword === 'DURATION') { try { $duration = new DateInterval($value); - array_push($this->cal[$key1][$key2]["{$keyword}_array"], $duration); + $this->cal[$key1][$key2]["{$keyword}_array"][] = $duration; } catch (Exception $e) { error_log('Ignoring invalid duration ' . $value); } @@ -928,6 +893,7 @@ class ICalParser break; } + // Remove? $this->lastKeyword = $keyword; } @@ -935,9 +901,9 @@ class ICalParser * Gets the key value pair from an iCal string * * @param string $text - * @return array|boolean + * @return ?array */ - protected function keyValueFromString($text) + protected function keyValueFromString(string $text): ?array { $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8'); @@ -974,14 +940,14 @@ class ICalParser } if (count($matches) === 0) { - return false; + return null; } - if (preg_match('/^([A-Z-]+)([;][\w\W]*)?$/', $matches[1])) { + if (preg_match('/^([A-Z-]+)(;[\w\W]*)?$/', $matches[1])) { $matches = array_splice($matches, 1, 2); // Remove first match and re-align ordering // Process properties - if (preg_match('/([A-Z-]+)[;]([\w\W]*)/', $matches[0], $properties)) { + if (preg_match('/([A-Z-]+);([\w\W]*)/', $matches[0], $properties)) { // Remove first match array_shift($properties); // Fix to ignore everything in keyword after a ; (e.g. Language, TZID, etc.) @@ -1023,9 +989,8 @@ class ICalParser } return $matches; - } else { - return false; // Ignore this match } + return null; // Ignore this match } /** @@ -1034,7 +999,7 @@ class ICalParser * @param string $icalDate * @return DateTime */ - public function iCalDateToDateTime($icalDate) + public function iCalDateToDateTime(string $icalDate): DateTime { /** * iCal times may be in 3 formats, (https://www.kanzaki.com/docs/ical/dateTime.html) @@ -1091,7 +1056,7 @@ class ICalParser * @param string $icalDate * @return integer */ - public function iCalDateToUnixTimestamp($icalDate) + public function iCalDateToUnixTimestamp(string $icalDate): int { return $this->iCalDateToDateTime($icalDate)->getTimestamp(); } @@ -1104,7 +1069,7 @@ class ICalParser * @param string $format * @return string|boolean */ - public function iCalDateWithTimeZone(array $event, $key, $format = self::DATE_TIME_FORMAT) + public function iCalDateWithTimeZone(array $event, string $key, string $format = self::DATE_TIME_FORMAT) { if (!isset($event["{$key}_array"]) || !isset($event[$key])) { return false; @@ -1141,7 +1106,6 @@ class ICalParser if (empty($this->cal['VEVENT'])) return; $events =& $this->cal['VEVENT']; - $checks = null; foreach ($events as $key => $anEvent) { foreach (array('DTSTART', 'DTEND', 'RECURRENCE-ID') as $type) { @@ -1175,23 +1139,20 @@ class ICalParser $eventKeysToRemove = array(); foreach ($events as $key => $event) { - $checks[] = !isset($event['RECURRENCE-ID']); - $checks[] = isset($event['UID']); - $checks[] = isset($event['UID']) && isset($this->alteredRecurrenceInstances[$event['UID']]); + $checks = !isset($event['RECURRENCE-ID']) + && isset($event['UID']) && isset($this->alteredRecurrenceInstances[$event['UID']]); - if ((bool)array_product($checks)) { + if ($checks) { $eventDtstartUnix = $this->iCalDateToUnixTimestamp($event['DTSTART_array'][3]); // phpcs:ignore CustomPHPCS.ControlStructures.AssignmentInCondition if (($alteredEventKey = array_search($eventDtstartUnix, $this->alteredRecurrenceInstances[$event['UID']])) !== false) { $eventKeysToRemove[] = $alteredEventKey; - $alteredEvent = array_replace_recursive($events[$key], $events[$alteredEventKey]); + $alteredEvent = array_replace_recursive($event, $events[$alteredEventKey]); $this->alteredRecurrenceInstances[$event['UID']]['altered-event'] = array($key => $alteredEvent); } } - - unset($checks); } foreach ($eventKeysToRemove as $eventKeyToRemove) { @@ -1568,7 +1529,7 @@ class ICalParser * @param DateTime $initialDateTime * @return array */ - protected function getDaysOfMonthMatchingByDayRRule(array $byDays, $initialDateTime) + protected function getDaysOfMonthMatchingByDayRRule(array $byDays, DateTime $initialDateTime): array { $matchingDays = array(); @@ -1628,7 +1589,7 @@ class ICalParser * @param array $valuesList * @return array */ - protected function filterValuesUsingBySetPosRRule(array $bySetPos, array $valuesList) + protected function filterValuesUsingBySetPosRRule(array $bySetPos, array $valuesList): array { $filteredMatches = array(); @@ -1688,7 +1649,7 @@ class ICalParser * * @return ICalEvent[] */ - public function events() + public function events(): array { if (empty($this->cal) || empty($this->cal['VEVENT'])) return []; @@ -1706,9 +1667,9 @@ class ICalParser * * @return string */ - public function calendarName() + public function calendarName(): string { - return isset($this->cal['VCALENDAR']['X-WR-CALNAME']) ? $this->cal['VCALENDAR']['X-WR-CALNAME'] : ''; + return $this->cal['VCALENDAR']['X-WR-CALNAME'] ?? ''; } /** @@ -1716,9 +1677,9 @@ class ICalParser * * @return string */ - public function calendarDescription() + public function calendarDescription(): string { - return isset($this->cal['VCALENDAR']['X-WR-CALDESC']) ? $this->cal['VCALENDAR']['X-WR-CALDESC'] : ''; + return $this->cal['VCALENDAR']['X-WR-CALDESC'] ?? ''; } /** @@ -1727,7 +1688,7 @@ class ICalParser * @param boolean $ignoreUtc * @return string */ - public function calendarTimeZone($ignoreUtc = false) + public function calendarTimeZone(bool $ignoreUtc = false): ?string { if (isset($this->cal['VCALENDAR']['X-WR-TIMEZONE'])) { $timeZone = $this->cal['VCALENDAR']['X-WR-TIMEZONE']; @@ -1754,11 +1715,11 @@ class ICalParser * * @return array */ - public function freeBusyEvents() + public function freeBusyEvents(): array { $array = $this->cal; - return isset($array['VFREEBUSY']) ? $array['VFREEBUSY'] : array(); + return $array['VFREEBUSY'] ?? array(); } /** @@ -1784,7 +1745,7 @@ class ICalParser * @return array * @throws Exception */ - public function eventsFromRange($rangeStart = null, $rangeEnd = null) + public function eventsFromRange(string $rangeStart = null, string $rangeEnd = null): array { // Sort events before processing range $events = $this->sortEventsWithOrder($this->events()); @@ -1857,7 +1818,7 @@ class ICalParser * @param integer $sortOrder Either SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING * @return array */ - public function sortEventsWithOrder(array $events, $sortOrder = SORT_ASC) + public function sortEventsWithOrder(array $events, int $sortOrder = SORT_ASC): array { $extendedEvents = array(); $timestamp = array(); @@ -1878,7 +1839,7 @@ class ICalParser * @param string $timeZone * @return boolean */ - protected function isValidTimeZoneId($timeZone) + protected function isValidTimeZoneId(string $timeZone): bool { return $this->isValidIanaTimeZoneId($timeZone) !== false || $this->isValidCldrTimeZoneId($timeZone) !== false @@ -1891,7 +1852,7 @@ class ICalParser * @param string $timeZone * @return boolean */ - protected function isValidIanaTimeZoneId($timeZone) + protected function isValidIanaTimeZoneId(string $timeZone): bool { if (in_array($timeZone, $this->validIanaTimeZones)) { return true; @@ -1923,7 +1884,7 @@ class ICalParser * @param string $timeZone * @return boolean */ - public function isValidCldrTimeZoneId($timeZone) + public function isValidCldrTimeZoneId(string $timeZone): bool { return array_key_exists(html_entity_decode($timeZone), self::$cldrTimeZonesMap); } @@ -1934,7 +1895,7 @@ class ICalParser * @param string $timeZone * @return boolean */ - public function isValidWindowsTimeZoneId($timeZone) + public function isValidWindowsTimeZoneId(string $timeZone): bool { return array_key_exists(html_entity_decode($timeZone), self::$windowsTimeZonesMap); } @@ -1942,12 +1903,9 @@ class ICalParser /** * Parses a duration and applies it to a date * - * @param string $date - * @param DateInterval $duration - * @param string $format * @return integer|DateTime */ - protected function parseDuration($date, $duration, $format = self::UNIX_FORMAT) + protected function parseDuration(string $date, DateInterval $duration, ?string $format = self::UNIX_FORMAT) { $dateTime = date_create($date); $dateTime->modify("{$duration->y} year"); @@ -1974,7 +1932,7 @@ class ICalParser * @param string $data * @return string */ - protected function removeUnprintableChars($data) + protected function removeUnprintableChars(string $data): string { return preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $data); } @@ -1986,7 +1944,7 @@ class ICalParser * @param string $candidateText * @return string */ - protected function escapeParamText($candidateText) + protected function escapeParamText(string $candidateText): string { if (strpbrk($candidateText, ':;,') !== false) { return '"' . $candidateText . '"'; @@ -2002,13 +1960,12 @@ class ICalParser * @param array $event * @return array */ - public function parseExdates(array $event) + public function parseExdates(array $event): array { if (empty($event['EXDATE_array'])) { return array(); - } else { - $exdates = $event['EXDATE_array']; } + $exdates = $event['EXDATE_array']; $output = array(); $currentTimeZone = $this->defaultTimeZone; @@ -2046,7 +2003,7 @@ class ICalParser * @param string $value * @return boolean */ - public function isValidDate($value) + public function isValidDate(string $value): bool { if (!$value) { return false; @@ -2065,10 +2022,10 @@ class ICalParser * Returns a `DateTimeZone` object based on a string containing a time zone name. * Falls back to the default time zone if string passed not a recognised time zone. * - * @param string $timeZoneString + * @param DateTimeZone|string $timeZoneString * @return DateTimeZone */ - public function timeZoneStringToDateTimeZone($timeZoneString) + public function timeZoneStringToDateTimeZone($timeZoneString): DateTimeZone { if ($timeZoneString instanceof DateTimeZone) return $timeZoneString; |