From 81aee33f877f201364ae2158b8f5c6d407b094ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Lochmu=CC=88ller?= Date: Sun, 24 Feb 2019 10:29:05 +0100 Subject: [PATCH] Prepare migration to new ICS parser --- Classes/Service/IcsReaderService.php | 110 +++- .../Service/TimeTable/ExternalTimeTable.php | 50 +- Resources/Private/Php/ics-parser/MyCal.ics | 216 -------- Resources/Private/Php/ics-parser/README | 28 - .../Php/ics-parser/class.iCalReader.php | 480 ------------------ .../Private/Php/ics-parser/composer.json | 20 - Resources/Private/Php/ics-parser/example.php | 57 --- composer.json | 3 +- 8 files changed, 110 insertions(+), 854 deletions(-) delete mode 100755 Resources/Private/Php/ics-parser/MyCal.ics delete mode 100755 Resources/Private/Php/ics-parser/README delete mode 100755 Resources/Private/Php/ics-parser/class.iCalReader.php delete mode 100755 Resources/Private/Php/ics-parser/composer.json delete mode 100755 Resources/Private/Php/ics-parser/example.php diff --git a/Classes/Service/IcsReaderService.php b/Classes/Service/IcsReaderService.php index 7fc3d587..e32f2977 100644 --- a/Classes/Service/IcsReaderService.php +++ b/Classes/Service/IcsReaderService.php @@ -7,8 +7,11 @@ namespace HDNET\Calendarize\Service; +use HDNET\Calendarize\Service\TimeTable\ExternalTimeTable; use HDNET\Calendarize\Utility\DateTimeUtility; +use JMBTechnologyLimited\ICalDissect\ICalEvent; use JMBTechnologyLimited\ICalDissect\ICalParser; +use Sabre\VObject\Reader; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -17,21 +20,114 @@ class IcsReaderService extends AbstractService { /** - * Get the ICS events in an array. + * Generate the times of the given URL. * - * @param string $paramUrl + * @param string $url + * + * @return array + */ + public function getTimes(string $url): array + { + $fileName = $this->getCachedUrlFile($url); + $times = $this->buildWithICalDissect($fileName); + // $test = $this->buildWithVObject($fileName); + return $times; + } + + /** + * Build with iCal dissect. + * + * @param string $filename * * @return array */ - public function toArray($paramUrl) + protected function buildWithICalDissect(string $filename): array { - $tempFileName = $this->getCachedUrlFile($paramUrl); $backend = new ICalParser(); - if ($backend->parseFromFile($tempFileName)) { - return $backend->getEvents(); + if (!$backend->parseFromFile($filename)) { + return []; + } + $events = $backend->getEvents(); + $times = []; + foreach ($events as $event) { + /** @var $event ICalEvent */ + $startTime = DateTimeUtility::getDaySecondsOfDateTime($event->getStart()); + $endTime = DateTimeUtility::getDaySecondsOfDateTime($event->getEnd()); + if (ExternalTimeTable::DAY_END === $endTime) { + $endTime = 0; + } + + $times[] = [ + 'start_date' => $event->getStart(), + 'end_date' => $this->getEventsFixedEndDate($event), + 'start_time' => $startTime, + 'end_time' => $endTime, + 'all_day' => 0 === $endTime, + ]; + } + + return $times; + } + + /** + * Build with Vobject. + * + * @param string $filename + * + * @return array + * + * @todo implement + */ + protected function buildWithVObject(string $filename): array + { + $vcalendar = Reader::read( + GeneralUtility::getUrl($filename) + ); + $times = []; + foreach ($vcalendar->VEVENT as $event) { + /*DTSTAMP => array(1 item) + UID => array(1 item) + DTSTART => array(1 item) + DTEND => array(1 item)*/ + //DebuggerUtility::var_dump($event->TESTST); + //DebuggerUtility::var_dump($event->DTSTAMP); + //DebuggerUtility::var_dump($event->DTSTART); + //DebuggerUtility::var_dump($event->DTEND); + + $times[] = [ + 'start_date' => $event->DTSTART->getDateTime(), + 'end_date' => 0, // $this->getEventsFixedEndDate($event), + 'start_time' => 0, + 'end_time' => 0, + 'all_day' => true, + ]; + } + + return $times; + } + + /** + * Fixes a parser related bug where the DTEND is EXCLUSIVE. + * The parser uses it inclusive so every event is one day + * longer than it should be. + * + * @param ICalEvent $event + * + * @return \DateTime + */ + protected function getEventsFixedEndDate(ICalEvent $event) + { + if (!$event->getEnd() instanceof \DateTimeInterface) { + return $event->getStart(); + } + + $end = clone $event->getEnd(); + $end->sub(new \DateInterval('P1D')); + if ($end->format('Ymd') === $event->getStart()->format('Ymd')) { + return $end; } - return []; + return $event->getEnd(); } /** diff --git a/Classes/Service/TimeTable/ExternalTimeTable.php b/Classes/Service/TimeTable/ExternalTimeTable.php index c443f21a..332865d3 100644 --- a/Classes/Service/TimeTable/ExternalTimeTable.php +++ b/Classes/Service/TimeTable/ExternalTimeTable.php @@ -9,9 +9,7 @@ use HDNET\Calendarize\Domain\Model\Configuration; use HDNET\Calendarize\Service\IcsReaderService; -use HDNET\Calendarize\Utility\DateTimeUtility; use HDNET\Calendarize\Utility\HelperUtility; -use JMBTechnologyLimited\ICalDissect\ICalEvent; use TYPO3\CMS\Core\Messaging\FlashMessage; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -58,49 +56,11 @@ public function handleConfiguration(array &$times, Configuration $configuration) return; } - $events = $this->icsReaderService->toArray($url); - foreach ($events as $event) { - /** @var $event ICalEvent */ - $startTime = DateTimeUtility::getDaySecondsOfDateTime($event->getStart()); - $endTime = DateTimeUtility::getDaySecondsOfDateTime($event->getEnd()); - if (self::DAY_END === $endTime) { - $endTime = 0; - } - - $entry = [ - 'pid' => $configuration->getPid(), - 'start_date' => $event->getStart(), - 'end_date' => $this->getEventsFixedEndDate($event), - 'start_time' => $startTime, - 'end_time' => $endTime, - 'all_day' => 0 === $endTime, - 'state' => $configuration->getState(), - ]; - $times[$this->calculateEntryKey($entry)] = $entry; - } - } - - /** - * Fixes a parser related bug where the DTEND is EXCLUSIVE. - * The parser uses it inclusive so every event is one day - * longer than it should be. - * - * @param ICalEvent $event - * - * @return \DateTime - */ - protected function getEventsFixedEndDate(ICalEvent $event) - { - if (!$event->getEnd() instanceof \DateTimeInterface) { - return $event->getStart(); + $externalTimes = $this->icsReaderService->getTimes($url); + foreach ($externalTimes as $time) { + $time['pid'] = $configuration->getPid(); + $time['state'] = $configuration->getState(); + $times[$this->calculateEntryKey($time)] = $time; } - - $end = clone $event->getEnd(); - $end->sub(new \DateInterval('P1D')); - if ($end->format('Ymd') === $event->getStart()->format('Ymd')) { - return $end; - } - - return $event->getEnd(); } } diff --git a/Resources/Private/Php/ics-parser/MyCal.ics b/Resources/Private/Php/ics-parser/MyCal.ics deleted file mode 100755 index 830d9886..00000000 --- a/Resources/Private/Php/ics-parser/MyCal.ics +++ /dev/null @@ -1,216 +0,0 @@ -BEGIN:VCALENDAR -PRODID:-//Google Inc//Google Calendar 70.9054//EN -VERSION:2.0 -CALSCALE:GREGORIAN -METHOD:PUBLISH -X-WR-CALNAME:Testkalender -X-WR-TIMEZONE:Europe/Berlin -X-WR-CALDESC:Nur zum testen vom Google Kalender -BEGIN:VEVENT -DTSTART:20110105T090000Z -DTEND:20110107T173000Z -DTSTAMP:20110121T195741Z -UID:15lc1nvupht8dtfiptenljoiv4@google.com -CREATED:20110121T195616Z -DESCRIPTION:This is a short description\nwith a new line. Some "special" 's - igns' may be \, too. -LAST-MODIFIED:20110121T195729Z -LOCATION:Kansas -SEQUENCE:2 -STATUS:CONFIRMED -SUMMARY:My Holidays -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110112 -DTEND;VALUE=DATE:20110116 -DTSTAMP:20110121T195741Z -UID:1koigufm110c5hnq6ln57murd4@google.com -CREATED:20110119T142901Z -DESCRIPTION:Project xyz Review Meeting Minutes\n - Agenda\n1. Review of project version 1.0 requirements.\n2. - Definition - of project processes.\n3. Review of project schedule.\n - Participants: John Smith, Jane Doe, Jim Dandy\n-It was - decided that the requirements need to be signed off by - product marketing.\n-Project processes were accepted.\n - -Project schedule needs to account for scheduled holidays - and employee vacation time. Check with HR for specific - dates.\n-New schedule will be distributed by Friday.\n- - Next weeks meeting is cancelled. No meeting until 3/23. -LAST-MODIFIED:20110119T152216Z -LOCATION: -SEQUENCE:2 -STATUS:CONFIRMED -SUMMARY:test 11 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110118 -DTEND;VALUE=DATE:20110120 -DTSTAMP:20110121T195741Z -UID:4dnsuc3nknin15kv25cn7ridss@google.com -CREATED:20110119T142059Z -DESCRIPTION: -LAST-MODIFIED:20110119T142106Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 9 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110117 -DTEND;VALUE=DATE:20110122 -DTSTAMP:20110121T195741Z -UID:h6f7sdjbpt47v3dkral8lnsgcc@google.com -CREATED:20110119T142040Z -DESCRIPTION: -LAST-MODIFIED:20110119T142040Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY: -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110117 -DTEND;VALUE=DATE:20110118 -DTSTAMP:20110121T195741Z -UID:up56hlrtkpqdum73rk6tl10ook@google.com -CREATED:20110119T142034Z -DESCRIPTION: -LAST-MODIFIED:20110119T142034Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 8 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110118 -DTEND;VALUE=DATE:20110120 -DTSTAMP:20110121T195741Z -UID:8ltm205uhshsbc1huv0ooeg4nc@google.com -CREATED:20110119T142014Z -DESCRIPTION: -LAST-MODIFIED:20110119T142023Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 7 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110119 -DTEND;VALUE=DATE:20110121 -DTSTAMP:20110121T195741Z -UID:opklai3nm8enffdf5vpna4o5fo@google.com -CREATED:20110119T141918Z -DESCRIPTION: -LAST-MODIFIED:20110119T142005Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 5 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110119 -DTEND;VALUE=DATE:20110120 -DTSTAMP:20110121T195741Z -UID:kmbj764g57tcvua11hir61c4b8@google.com -CREATED:20110119T141923Z -DESCRIPTION: -LAST-MODIFIED:20110119T141923Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 6 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110119 -DTEND;VALUE=DATE:20110120 -DTSTAMP:20110121T195741Z -UID:shvr7hvqdag08vjqlmj5lj0i2s@google.com -CREATED:20110119T141913Z -DESCRIPTION: -LAST-MODIFIED:20110119T141913Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 4 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110119 -DTEND;VALUE=DATE:20110120 -DTSTAMP:20110121T195741Z -UID:77gpemlb9es0r0gtjolv3mtap0@google.com -CREATED:20110119T141909Z -DESCRIPTION: -LAST-MODIFIED:20110119T141909Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 3 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110119 -DTEND;VALUE=DATE:20110120 -DTSTAMP:20110121T195741Z -UID:rq8jng4jgq0m1lvpj8486fttu0@google.com -CREATED:20110119T141904Z -DESCRIPTION: -LAST-MODIFIED:20110119T141904Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 2 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20110119 -DTEND;VALUE=DATE:20110120 -DTSTAMP:20110121T195741Z -UID:dh3fki5du0opa7cs5n5s87ca00@google.com -CREATED:20110119T141901Z -DESCRIPTION: -LAST-MODIFIED:20110119T141901Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:test 1 -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:20400201 -DTEND;VALUE=DATE:20400202 -DTSTAMP:20400101T195741Z -UID:dh3fki5du0opa7cs5n5s87ca01@google.com -CREATED:20400101T141901Z -DESCRIPTION: -LAST-MODIFIED:20400101T141901Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:Year 2038 problem test -TRANSP:TRANSPARENT -END:VEVENT -BEGIN:VEVENT -DTSTART;VALUE=DATE:19410512 -DTEND;VALUE=DATE:19410512 -DTSTAMP:19410512T195741Z -UID:dh3fki5du0opa7cs5n5s87ca02@google.com -CREATED:20400101T141901Z -DESCRIPTION: -LAST-MODIFIED:20400101T141901Z -LOCATION: -SEQUENCE:0 -STATUS:CONFIRMED -SUMMARY:Before 1970-Test: Konrad Zuse invents the Z3, the first digital Computer -TRANSP:TRANSPARENT -END:VEVENT -END:VCALENDAR diff --git a/Resources/Private/Php/ics-parser/README b/Resources/Private/Php/ics-parser/README deleted file mode 100755 index 9ae11b26..00000000 --- a/Resources/Private/Php/ics-parser/README +++ /dev/null @@ -1,28 +0,0 @@ -This ics-parser is under MIT license. You may use it for your own sites for -free, but I would like to get a notice when you use it (info@martin-thoma.de). -If you use it for another software project, please let the information / links -to this project in the files. - -It was originally hosted at http://code.google.com/p/ics-parser/ and PEAR coding standard is -used. - -It was modified by John Grogg to properly handle recurring events (specifically with regards -to Microsoft Exchange) - -################################################################################ -# Requirements # -################################################################################ - * PHP - -################################################################################ -# Installation # -################################################################################ - * Copy all files to a folder where PHP can be executed - * Include class.iCalReader.php to your project - -################################################################################ -# Credits # -################################################################################ -Martin Thoma (programming, bug-fixing, project management) -Frank Gregor (programming, feedback, testing) -John Grogg (programming, addition of event recurrence handling) \ No newline at end of file diff --git a/Resources/Private/Php/ics-parser/class.iCalReader.php b/Resources/Private/Php/ics-parser/class.iCalReader.php deleted file mode 100755 index f4fb8ae4..00000000 --- a/Resources/Private/Php/ics-parser/class.iCalReader.php +++ /dev/null @@ -1,480 +0,0 @@ - - * - * @see http://code.google.com/p/ics-parser/ - * - * @example $ical = new ical('MyCal.ics'); - * print_r( $ical->events() ); - */ - -// error_reporting(E_ALL); - -/** - * This is the iCal-class. - * - * @category Parser - * - * @license http://www.opensource.org/licenses/mit-license.php MIT License - * - * @see http://code.google.com/p/ics-parser/ - * - * @param {string} filename The name of the file which should be parsed - * @constructor - */ -class ICal -{ - /* How many ToDos are in this ical? */ - public $todo_count = 0; - - /* How many events are in this ical? */ - public $event_count = 0; - - /* The parsed calendar */ - public $cal; - - /* Which keyword has been added to cal at last? */ - private $_lastKeyWord; - - /** - * Creates the iCal-Object. - * - * @param {string} $filename The path to the iCal-file - * - * @return object The iCal-Object - */ - public function __construct($filename) - { - if (!$filename) { - return false; - } - - $lines = \file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); - if (false == \mb_stristr($lines[0], 'BEGIN:VCALENDAR')) { - return false; - } - // TODO: Fix multiline-description problem (see http://tools.ietf.org/html/rfc2445#section-4.8.1.5) - foreach ($lines as $line) { - $line = \trim($line); - $add = $this->keyValueFromString($line); - if (false == $add) { - $this->addCalendarComponentWithKeyAndValue($type, false, $line); - continue; - } - - list($keyword, $value) = $add; - - switch ($line) { - // http://www.kanzaki.com/docs/ical/vtodo.html - case 'BEGIN:VTODO': - $this->todo_count++; - $type = 'VTODO'; - break; - - // http://www.kanzaki.com/docs/ical/vevent.html - case 'BEGIN:VEVENT': - $this->event_count++; - $type = 'VEVENT'; - break; - - //all other special strings - case 'BEGIN:VCALENDAR': - case 'BEGIN:DAYLIGHT': - // http://www.kanzaki.com/docs/ical/vtimezone.html - case 'BEGIN:VTIMEZONE': - case 'BEGIN:STANDARD': - $type = $value; - break; - case 'END:VTODO': // end special text - goto VCALENDAR key - case 'END:VEVENT': - case 'END:VCALENDAR': - case 'END:DAYLIGHT': - case 'END:VTIMEZONE': - case 'END:STANDARD': - $type = 'VCALENDAR'; - break; - default: - $this->addCalendarComponentWithKeyAndValue($type, - $keyword, - $value); - break; - } - } - $this->process_recurrences(); - - return $this->cal; - } - - /** - * Add to $this->ical array one value and key. - * - * @param {string} $component This could be VTODO, VEVENT, VCALENDAR, ... - * @param {string} $keyword The keyword, for example DTSTART - * @param {string} $value The value, for example 20110105T090000Z - * - * @return {None} - */ - public function addCalendarComponentWithKeyAndValue($component, - $keyword, - $value) - { - if (\mb_strstr($keyword, ';')) { - // Ignore everything in keyword after a ; (things like Language, etc) - $keyword = \mb_substr($keyword, 0, \mb_strpos($keyword, ';')); - } - if (false == $keyword) { - $keyword = $this->last_keyword; - switch ($component) { - case 'VEVENT': - $value = $this->cal[$component][$this->event_count - 1][$keyword] . $value; - break; - case 'VTODO': - $value = $this->cal[$component][$this->todo_count - 1][$keyword] . $value; - break; - } - } - - if (\mb_stristr($keyword, 'DTSTART') or \mb_stristr($keyword, 'DTEND')) { - $keyword = \explode(';', $keyword); - $keyword = $keyword[0]; - } - - switch ($component) { - case 'VTODO': - $this->cal[$component][$this->todo_count - 1][$keyword] = $value; - //$this->cal[$component][$this->todo_count]['Unix'] = $unixtime; - break; - case 'VEVENT': - $this->cal[$component][$this->event_count - 1][$keyword] = $value; - break; - default: - $this->cal[$component][$keyword] = $value; - break; - } - $this->last_keyword = $keyword; - } - - /** - * Get a key-value pair of a string. - * - * @param {string} $text which is like "VCALENDAR:Begin" or "LOCATION:" - * - * @return {array} array("VCALENDAR", "Begin") - */ - public function keyValueFromString($text) - { - \preg_match("/([^:]+)[:]([\w\W]*)/", $text, $matches); - if (0 == \count($matches)) { - return false; - } - $matches = \array_splice($matches, 1, 2); - - return $matches; - } - - /** - * Return Unix timestamp from ical date time format. - * - * @param {string} $icalDate A Date in the format YYYYMMDD[T]HHMMSS[Z] or - * YYYYMMDD[T]HHMMSS - * - * @return {int} - */ - public function iCalDateToUnixTimestamp($icalDate) - { - $icalDate = \str_replace('T', '', $icalDate); - $icalDate = \str_replace('Z', '', $icalDate); - - $pattern = '/([0-9]{4})'; // 1: YYYY - $pattern .= '([0-9]{2})'; // 2: MM - $pattern .= '([0-9]{2})'; // 3: DD - $pattern .= '([0-9]{0,2})'; // 4: HH - $pattern .= '([0-9]{0,2})'; // 5: MM - $pattern .= '([0-9]{0,2})/'; // 6: SS - \preg_match($pattern, $icalDate, $date); - - // Unix timestamp can't represent dates before 1970 - if ($date[1] <= 1970) { - return false; - } - // Unix timestamps after 03:14:07 UTC 2038-01-19 might cause an overflow - // if 32 bit integers are used. - $timestamp = \mktime((int) $date[4], - (int) $date[5], - (int) $date[6], - (int) $date[2], - (int) $date[3], - (int) $date[1]); - - return $timestamp; - } - - /** - * Processes recurrences. - * - * @return {array} - */ - public function process_recurrences() - { - $array = $this->cal; - $events = $array['VEVENT']; - foreach ($array['VEVENT'] as $anEvent) { - if (isset($anEvent['RRULE']) && '' != $anEvent['RRULE']) { - // Recurring event, parse RRULE and add appropriate duplicate events - $rrules = []; - $rrule_strings = \explode(';', $anEvent['RRULE']); - foreach ($rrule_strings as $s) { - list($k, $v) = \explode('=', $s); - $rrules[$k] = $v; - } - // Get Start timestamp - $start_timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTSTART']); - $end_timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTEND']); - $event_timestmap_offset = $end_timestamp - $start_timestamp; - // Get Interval - $interval = (isset($rrules['INTERVAL']) && '' != $rrules['INTERVAL']) ? $rrules['INTERVAL'] : 1; - // Get Until - $until = $this->iCalDateToUnixTimestamp($rrules['UNTIL']); - // Decide how often to add events and do so - switch ($rrules['FREQ']) { - case 'DAILY': - // Simply add a new event each interval of days until UNTIL is reached - $offset = "+$interval day"; - $recurring_timestamp = \strtotime($offset, $start_timestamp); - while ($recurring_timestamp <= $until) { - // Add event - $anEvent['DTSTART'] = \date('Ymd\THis', $recurring_timestamp); - $anEvent['DTEND'] = \date('Ymd\THis', $recurring_timestamp + $event_timestmap_offset); - $events[] = $anEvent; - // Move forward - $recurring_timestamp = \strtotime($offset, $recurring_timestamp); - } - break; - case 'WEEKLY': - // Create offset - $offset = "+$interval week"; - // Build list of days of week to add events - $weekdays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; - $bydays = (isset($rrules['BYDAY']) && '' != $rrules['BYDAY']) ? \explode(',', $rrules['BYDAY']) : ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; - // Get timestamp of first day of start week - $week_recurring_timestamp = (0 == \date('w', $start_timestamp)) ? $start_timestamp : \strtotime('last Sunday ' . \date('H:i:s', $start_timestamp), $start_timestamp); - // Step through weeks - while ($week_recurring_timestamp <= $until) { - // Add events for bydays - $day_recurring_timestamp = $week_recurring_timestamp; - foreach ($weekdays as $day) { - // Check if day should be added - if (\in_array($day, $bydays, true) && $day_recurring_timestamp > $start_timestamp && $day_recurring_timestamp <= $until) { - // Add event to day - $anEvent['DTSTART'] = \date('Ymd\THis', $day_recurring_timestamp); - $anEvent['DTEND'] = \date('Ymd\THis', $day_recurring_timestamp + $event_timestmap_offset); - $events[] = $anEvent; - } - // Move forward a day - $day_recurring_timestamp = \strtotime('+1 day', $day_recurring_timestamp); - } - // Move forward $interaval weeks - $week_recurring_timestamp = \strtotime($offset, $week_recurring_timestamp); - } - break; - case 'MONTHLY': - // Create offset - $offset = "+$interval month"; - $recurring_timestamp = \strtotime($offset, $start_timestamp); - if (isset($rrules['BYMONTHDAY']) && '' != $rrules['BYMONTHDAY']) { - // Deal with BYMONTHDAY - while ($recurring_timestamp <= $until) { - // Add event - $anEvent['DTSTART'] = \date('Ym' . \sprintf('%02d', $rrules['BYMONTHDAY']) . '\THis', $recurring_timestamp); - $anEvent['DTEND'] = \date('Ymd\THis', $this->iCalDateToUnixTimestamp($anEvent['DTSTART']) + $event_timestmap_offset); - $events[] = $anEvent; - // Move forward - $recurring_timestamp = \strtotime($offset, $recurring_timestamp); - } - } elseif (isset($rrules['BYDAY']) && '' != $rrules['BYDAY']) { - $start_time = \date('His', $start_timestamp); - // Deal with BYDAY - $day_number = \mb_substr($rrules['BYDAY'], 0, 1); - $week_day = \mb_substr($rrules['BYDAY'], 1); - $day_cardinals = [1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth']; - $weekdays = ['SU' => 'sunday', 'MO' => 'monday', 'TU' => 'tuesday', 'WE' => 'wednesday', 'TH' => 'thursday', 'FR' => 'friday', 'SA' => 'saturday']; - while ($recurring_timestamp <= $until) { - $event_start_desc = "{$day_cardinals[$day_number]} {$weekdays[$week_day]} of " . \date('F', $recurring_timestamp) . ' ' . \date('Y', $recurring_timestamp) . ' ' . \date('H:i:s', $recurring_timestamp); - $event_start_timestamp = \strtotime($event_start_desc); - if ($event_start_timestamp > $start_timestamp && $event_start_timestamp < $until) { - $anEvent['DTSTART'] = \date('Ymd\T', $event_start_timestamp) . $start_time; - $anEvent['DTEND'] = \date('Ymd\THis', $this->iCalDateToUnixTimestamp($anEvent['DTSTART']) + $event_timestmap_offset); - $events[] = $anEvent; - } - // Move forward - $recurring_timestamp = \strtotime($offset, $recurring_timestamp); - } - } - break; - case 'YEARLY': - // Create offset - $offset = "+$interval year"; - $recurring_timestamp = \strtotime($offset, $start_timestamp); - $month_names = [1 => 'January', 2 => 'Februrary', 3 => 'March', 4 => 'April', 5 => 'May', 6 => 'June', 7 => 'July', 8 => 'August', 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December']; - // HACK: Exchange doesn't set a correct UNTIL for yearly events, so just go 2 years out - $until = \strtotime('+2 year', $start_timestamp); - // Check if BYDAY rule exists - if (isset($rrules['BYDAY']) && '' != $rrules['BYDAY']) { - $start_time = \date('His', $start_timestamp); - // Deal with BYDAY - $day_number = \mb_substr($rrules['BYDAY'], 0, 1); - $month_day = \mb_substr($rrules['BYDAY'], 1); - $day_cardinals = [1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth']; - $weekdays = ['SU' => 'sunday', 'MO' => 'monday', 'TU' => 'tuesday', 'WE' => 'wednesday', 'TH' => 'thursday', 'FR' => 'friday', 'SA' => 'saturday']; - while ($recurring_timestamp <= $until) { - $event_start_desc = "{$day_cardinals[$day_number]} {$weekdays[$month_day]} of {$month_names[$rrules['BYMONTH']]} " . \date('Y', $recurring_timestamp) . ' ' . \date('H:i:s', $recurring_timestamp); - $event_start_timestamp = \strtotime($event_start_desc); - if ($event_start_timestamp > $start_timestamp && $event_start_timestamp < $until) { - $anEvent['DTSTART'] = \date('Ymd\T', $event_start_timestamp) . $start_time; - $anEvent['DTEND'] = \date('Ymd\THis', $this->iCalDateToUnixTimestamp($anEvent['DTSTART']) + $event_timestmap_offset); - $events[] = $anEvent; - } - // Move forward - $recurring_timestamp = \strtotime($offset, $recurring_timestamp); - } - } else { - $day = \date('d', $start_timestamp); - // Step throuhg years adding specific month dates - while ($recurring_timestamp <= $until) { - $event_start_desc = "$day {$month_names[$rrules['BYMONTH']]} " . \date('Y', $recurring_timestamp) . ' ' . \date('H:i:s', $recurring_timestamp); - $event_start_timestamp = \strtotime($event_start_desc); - if ($event_start_timestamp > $start_timestamp && $event_start_timestamp < $until) { - $anEvent['DTSTART'] = \date('Ymd\T', $event_start_timestamp) . $start_time; - $anEvent['DTEND'] = \date('Ymd\THis', $this->iCalDateToUnixTimestamp($anEvent['DTSTART']) + $event_timestmap_offset); - $events[] = $anEvent; - } - // Move forward - $recurring_timestamp = \strtotime($offset, $recurring_timestamp); - } - } - break; - } - } - } - $this->cal['VEVENT'] = $events; - } - - /** - * Returns an array of arrays with all events. Every event is an associative - * array and each property is an element it. - * - * @return {array} - */ - public function events() - { - $array = $this->cal; - - return $array['VEVENT']; - } - - /** - * Returns a boolean value whether thr current calendar has events or not. - * - * @return {boolean} - */ - public function hasEvents() - { - return \count($this->events()) > 0 ? true : false; - } - - /** - * Returns false when the current calendar has no events in range, else the - * events. - * - * Note that this function makes use of a UNIX timestamp. This might be a - * problem on January the 29th, 2038. - * See http://en.wikipedia.org/wiki/Unix_time#Representing_the_number - * - * @param {boolean} $rangeStart Either true or false - * @param {boolean} $rangeEnd Either true or false - * - * @return {mixed} - */ - public function eventsFromRange($rangeStart = false, $rangeEnd = false) - { - $events = $this->sortEventsWithOrder($this->events(), SORT_ASC); - - if (!$events) { - return false; - } - - $extendedEvents = []; - - if (false == $rangeStart) { - $rangeStart = new DateTime(); - } else { - $rangeStart = new DateTime($rangeStart); - } - - if (false == $rangeEnd or $rangeEnd <= 0) { - $rangeEnd = new DateTime('2038/01/18'); - } else { - $rangeEnd = new DateTime($rangeEnd); - } - - $rangeStart = $rangeStart->format('U'); - $rangeEnd = $rangeEnd->format('U'); - - // loop through all events by adding two new elements - foreach ($events as $anEvent) { - $timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTSTART']); - if ($timestamp >= $rangeStart && $timestamp <= $rangeEnd) { - $extendedEvents[] = $anEvent; - } - } - - return $extendedEvents; - } - - /** - * Returns a boolean value whether thr current calendar has events or not. - * - * @param {array} $events An array with events - * @param {array} $sortOrder Either SORT_ASC, SORT_DESC, SORT_REGULAR, - * SORT_NUMERIC, SORT_STRING - * - * @return {boolean} - */ - public function sortEventsWithOrder($events, $sortOrder = SORT_ASC) - { - $extendedEvents = []; - - // loop through all events by adding two new elements - foreach ($events as $anEvent) { - if (!\array_key_exists('UNIX_TIMESTAMP', $anEvent)) { - $anEvent['UNIX_TIMESTAMP'] = - $this->iCalDateToUnixTimestamp($anEvent['DTSTART']); - } - - if (!\array_key_exists('REAL_DATETIME', $anEvent)) { - $anEvent['REAL_DATETIME'] = - \date('d.m.Y', $anEvent['UNIX_TIMESTAMP']); - } - - $extendedEvents[] = $anEvent; - } - - foreach ($extendedEvents as $key => $value) { - $timestamp[$key] = $value['UNIX_TIMESTAMP']; - } - \array_multisort($timestamp, $sortOrder, $extendedEvents); - - return $extendedEvents; - } -} diff --git a/Resources/Private/Php/ics-parser/composer.json b/Resources/Private/Php/ics-parser/composer.json deleted file mode 100755 index 7b607b33..00000000 --- a/Resources/Private/Php/ics-parser/composer.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "johngrogg/ics-parser", - "description": "Ics file parser", - "keywords": ["ics", "ical"], - "authors": [ - { - "name": "Martin Thoma", - "email": "info@martin-thoma.de", - "role": "Original Developer" - }, - { - "name": "John Grogg", - "email": "john.grogg@gmail.com", - "role": "Developer" - } - ], - "autoload": { - "classmap": ["class.iCalReader.php"] - } -} diff --git a/Resources/Private/Php/ics-parser/example.php b/Resources/Private/Php/ics-parser/example.php deleted file mode 100755 index 94cdf92a..00000000 --- a/Resources/Private/Php/ics-parser/example.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * @see http://code.google.com/p/ics-parser/ - * - * @example $ical = new ical('MyCal.ics'); - * print_r( $ical->get_event_array() ); - */ -require 'class.iCalReader.php'; - -$ical = new ICal('MyCal.ics'); -$events = $ical->events(); - -$date = $events[0]['DTSTART']; -echo 'The ical date: '; -echo $date; -echo '
'; - -echo 'The Unix timestamp: '; -echo $ical->iCalDateToUnixTimestamp($date); -echo '
'; - -echo 'The number of events: '; -echo $ical->event_count; -echo '
'; - -echo 'The number of todos: '; -echo $ical->todo_count; -echo '
'; -echo '

'; - -foreach ($events as $event) { - echo 'SUMMARY: ' . $event['SUMMARY'] . '
'; - echo 'DTSTART: ' . $event['DTSTART'] . ' - UNIX-Time: ' . $ical->iCalDateToUnixTimestamp($event['DTSTART']) . '
'; - echo 'DTEND: ' . $event['DTEND'] . '
'; - echo 'DTSTAMP: ' . $event['DTSTAMP'] . '
'; - echo 'UID: ' . $event['UID'] . '
'; - echo 'CREATED: ' . $event['CREATED'] . '
'; - echo 'DESCRIPTION: ' . $event['DESCRIPTION'] . '
'; - echo 'LAST-MODIFIED: ' . $event['LAST-MODIFIED'] . '
'; - echo 'LOCATION: ' . $event['LOCATION'] . '
'; - echo 'SEQUENCE: ' . $event['SEQUENCE'] . '
'; - echo 'STATUS: ' . $event['STATUS'] . '
'; - echo 'TRANSP: ' . $event['TRANSP'] . '
'; - echo '
'; -} diff --git a/composer.json b/composer.json index fd840aa5..e597b0c0 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,8 @@ "ext-json": "*", "ext-pdo": "*", "typo3/cms-core": "~8.7.0||~9.5.0", - "lochmueller/autoloader": ">4.0.0" + "lochmueller/autoloader": ">4.0.0", + "sabre/vobject": "^4.2" }, "replace": { "typo3-ter/calendarize": "self.version"