ics-parser icon indicating copy to clipboard operation
ics-parser copied to clipboard

Support ability to parse RDATE

Open u01jmg3 opened this issue 7 years ago • 9 comments

u01jmg3 avatar Mar 19 '17 00:03 u01jmg3

The lack of this functionality is preventing the library from working correctly for me. Parsing RDATE should be very straightforward (much more so than other already supported methods of handling recurring events) as it is simply indicates additional DTSTART values for the event.

oisact avatar Feb 09 '19 04:02 oisact

Happy to accept a PR

u01jmg3 avatar Feb 09 '19 17:02 u01jmg3

Happy to accept a PR

This works for me and the ICS I'm importing.

Patch file (renamed .txt to allow uploading) Enhance_the_iCal_php_library_to_support_RDATE_type_recurring_events_.txt

oisact avatar Feb 10 '19 12:02 oisact

Please raise a PR. Unable to apply the patch even renaming it to *.patch.

u01jmg3 avatar Feb 10 '19 12:02 u01jmg3

Please raise a PR. Unable to apply the patch even renaming it to *.patch.

remote: Permission to u01jmg3/ics-parser.git denied to oisact. fatal: unable to access 'https://github.com/u01jmg3/ics-parser.git/': The requested URL returned error: 403

oisact avatar Feb 10 '19 13:02 oisact

If you don't have write access to the repository where you'd like to create a pull request, you must create a fork, or copy, of the repository first. For more information, see "Creating a pull request from a fork" and "About forks."

  • https://help.github.com/articles/creating-a-pull-request/

u01jmg3 avatar Feb 10 '19 13:02 u01jmg3

Sorry, I don't have the time to jump through the hoops. Here it is if you want it... one solid block of code:

if (isset($anEvent['RDATE'])) {
    $isAllDayEvent = (strlen($anEvent['DTSTART_array'][1]) === 8) ? true : false;

    $initialStart             = new \DateTime($anEvent['DTSTART_array'][1]);
    $initialStartTimeZoneName = $initialStart->getTimezone()->getName();

    if (isset($anEvent['DTEND'])) {
        $initialEnd             = new \DateTime($anEvent['DTEND_array'][1]);
        $initialEndTimeZoneName = $initialEnd->getTimezone()->getName();
    } else {
        $initialEndTimeZoneName = $initialStartTimeZoneName;
    }

    // Get Start timestamp
    $startTimestamp = $initialStart->getTimestamp();

    if (isset($anEvent['DTEND'])) {
        $endTimestamp = $initialEnd->getTimestamp();
    } elseif (isset($anEvent['DURATION'])) {
        $duration = end($anEvent['DURATION_array']);
        $endTimestamp = $this->parseDuration($anEvent['DTSTART'], $duration);
    } else {
        $endTimestamp = $startTimestamp;
    }

    $eventTimestampOffset = $endTimestamp - $startTimestamp;


    for ($i = 1; $i < count($anEvent['RDATE_array']); $i+=2) {
        $date = $anEvent['RDATE_array'][$i];

        if (strtotime($date) == $startTimestamp) {
            //This RDATE is the same as the primary event
            continue;
        }

        if (isset($anEvent['RDATE_array'][$i - 1]['TZID'])) {
            $date = sprintf(self::ICAL_DATE_TIME_TEMPLATE, $anEvent['RDATE_array'][$i - 1]['TZID']) . $date;
        }

        $newEvent = $anEvent;

        // Tag as generated by a recurrence rule
        $newEvent['RRULE_array'][2] = self::RECURRENCE_EVENT;

        $newEvent['DTSTART'] = $anEvent['RDATE_array'][$i];
        $newEvent['DTSTART_array']= [
            0 => $anEvent['RDATE_array'][$i - 1],
            1 => $anEvent['RDATE_array'][$i],
            2 => $this->iCalDateToUnixTimestamp($date, false, false),
            3 => $date
        ];

        $newEvent['DTEND_array']      = $newEvent['DTSTART_array'];
        $newEvent['DTEND_array'][2]  += $eventTimestampOffset;
        $newEvent['DTEND'] = date(
                self::DATE_TIME_FORMAT,
                $newEvent['DTEND_array'][2]
            ) . ($isAllDayEvent || ($initialEndTimeZoneName === 'Z') ? 'Z' : '');
        $newEvent['DTEND_array'][1] = $newEvent['DTEND'];

        $newEvent            = $this->processEventIcalDateTime($newEvent);
        $recurrenceEvents[]  = $newEvent;
        $this->eventCount++;
    }
    $allRecurrenceEvents = array_merge($allRecurrenceEvents, $recurrenceEvents);
    $recurrenceEvents    = array(); // Reset
}

Which immediately follows:

protected function processRecurrences()
    {
        $events = (isset($this->cal['VEVENT'])) ? $this->cal['VEVENT'] : array();

        $recurrenceEvents    = array();
        $allRecurrenceEvents = array();

        if (empty($events)) {
            return false;
        }

        foreach ($events as $anEvent) {

oisact avatar Feb 10 '19 13:02 oisact

The data I'm importing is coming from here: https://smythchamber.org/?plugin=all-in-one-event-calendar&controller=ai1ec_exporter_controller&action=export_events&no_html=true

oisact avatar Feb 10 '19 13:02 oisact

Sorry, I don't have the time to jump through the hoops.

Pull requests are the standard method of contributing to open source software on GitHub. If you want to continue/begin contributing to any project on GitHub I would suggest getting up to speed with how this method works. Forking a repo can be done in seconds. Instead I will have to copy and paste your code which I'm sure you will agree is not an ideal way of incorporating changes to a repo.

u01jmg3 avatar Feb 10 '19 13:02 u01jmg3