You are here

function date_ical_parse in Date 6

Same name and namespace in other branches
  1. 5.2 date_api_ical.inc \date_ical_parse()
  2. 6.2 date_api_ical.inc \date_ical_parse()
  3. 7.3 date_api/date_api_ical.inc \date_ical_parse()
  4. 7 date_api/date_api_ical.inc \date_ical_parse()
  5. 7.2 date_api/date_api_ical.inc \date_ical_parse()

Return an array of iCalendar information from an iCalendar file.

As date_ical_import() but different param.

Parameters

$icaldatafolded: an array of lines from an ical feed.

Return value

array An array with all the elements from the ical.

1 call to date_ical_parse()
date_ical_import in ./date_api_ical.inc
Return an array of iCalendar information from an iCalendar file.

File

./date_api_ical.inc, line 113
Parse iCal data.

Code

function date_ical_parse($icaldatafolded = array()) {

  // Verify this is iCal data
  if (trim($icaldatafolded[0]) != 'BEGIN:VCALENDAR') {
    drupal_set_message('Invalid calendar file:' . $filename, 'error');
    return false;
  }

  // "unfold" wrapped lines
  $icaldata = array();
  foreach ($icaldatafolded as $line) {
    $out = array();

    // See if this looks like the beginning of a new property or value.
    // If not, it is a continuation of the previous line.
    // The regex is to ensure that wrapped QUOTED-PRINTABLE data
    // is kept intact.
    if (!preg_match('/([A-Z]+)[:;](.*)/', $line, $out)) {
      $line = array_pop($icaldata) . $line;
    }
    $icaldata[] = $line;
  }
  unset($icaldatafolded);

  // Parse the iCal information
  $parents = array();
  $subgroups = array();
  foreach ($icaldata as $line) {
    $line = trim($line);
    $vcal .= $line . "\n";

    // Deal with begin/end tags separately
    if (preg_match('/(BEGIN|END):V(\\S+)/', $line, $matches)) {
      $closure = $matches[1];
      $type = 'V' . $matches[2];
      if ($closure == 'BEGIN') {
        array_push($parents, $type);
        array_push($subgroups, array());
      }
      else {
        if ($closure == 'END') {
          end($subgroups);
          $subgroup =& $subgroups[key($subgroups)];
          switch ($type) {
            case 'VCALENDAR':
              if (prev($subgroups) == false) {
                $items[] = array_pop($subgroups);
              }
              else {
                $parent[array_pop($parents)][] = array_pop($subgroups);
              }
              break;

            // Add the timezones in with their index their TZID
            case 'VTIMEZONE':
              $subgroup = end($subgroups);
              $id = $subgroup['TZID'];
              unset($subgroup['TZID']);

              // Append this subgroup onto the one above it
              prev($subgroups);
              $parent =& $subgroups[key($subgroups)];
              $parent[$type][$id] = $subgroup;
              array_pop($subgroups);
              array_pop($parents);
              break;

            // Do some fun stuff with durations and all_day events
            // and then append to parent
            case 'VEVENT':
            case 'VALARM':
            case 'VTODO':
            case 'VJOURNAL':
            case 'VVENUE':
            case 'VFREEBUSY':
            default:

              // Can't be sure whether DTSTART is before or after DURATION,
              // so parse DURATION at the end.
              if (isset($subgroup['DURATION'])) {
                date_ical_parse_duration($subgroup);
              }

              // Check for all-day events setting the 'all_day' property under
              // the component instead of DTSTART/DTEND subcomponents
              if (isset($subgroup['DTSTART']) && !isset($subgroup['DTEND']) || $subgroup['DTSTART']['all_day'] && $subgroup['DTEND']['all_day']) {
                $subgroup['all_day'] = true;
                if (!isset($subgroup['DTEND'])) {
                  $subgroup['DTEND'] = $subgroup['DTSTART'];
                }
                unset($subgroup['DTSTART']['all_day']);
                unset($subgroup['DTEND']['all_day']);
              }

            // Add this element to the parent as an array under the
            // component name
            default:
              prev($subgroups);
              $parent =& $subgroups[key($subgroups)];
              $parent[$type][] = $subgroup;
              array_pop($subgroups);
              array_pop($parents);
              break;
          }
        }
      }
    }
    else {

      // Grab current subgroup
      end($subgroups);
      $subgroup =& $subgroups[key($subgroups)];

      // Split up the line into nice pieces for PROPERTYNAME,
      // PROPERTYATTRIBUTES, and PROPERTYVALUE
      preg_match('/([^;:]+)(?:;([^:]*))?:(.+)/', $line, $matches);
      $name = strtoupper(trim($matches[1]));
      $field = $matches[2];
      $data = $matches[3];
      $parse_result = '';
      switch ($name) {

        // Keep blank lines out of the results.
        case '':
          break;

        // Lots of properties have date values that must be parsed out.
        case 'CREATED':
        case 'LAST-MODIFIED':
        case 'DTSTART':
        case 'DTEND':
        case 'DTSTAMP':
        case 'RDATE':
        case 'TRIGGER':
        case 'FREEBUSY':
        case 'DUE':
        case 'COMPLETED':
          $parse_result = date_ical_parse_date($field, $data);
          break;
        case 'EXDATE':
          $parse_result = date_ical_parse_exceptions($field, $data);
          break;
        case 'DURATION':

          // Can't be sure whether DTSTART is before or after DURATION in
          // the VEVENT, so store the data and parse it at the end.
          $subgroup['DURATION'] = array(
            'DATA' => $data,
          );
          break;
        case 'RRULE':
        case 'EXRULE':
          $parse_result = date_ical_parse_rrule($field, $data);
          break;
        case 'SUMMARY':
        case 'DESCRIPTION':
        case 'LOCATION':
          $parse_result = date_ical_parse_text($field, $data);
          break;

        // For all other properties, just store the property and the value.
        // This can be expanded on in the future if other properties should
        // be given special treatment.
        default:
          $parse_result = $data;
          break;
      }

      // Store the result of our parsing
      $subgroup[$name] = $parse_result;
    }
  }
  return $items;
}