Horde_Icalendar::parsevCalendar PHP Method

parsevCalendar() public method

Parses a string containing vCalendar data.
public parsevCalendar ( string $text, string $base = 'VCALENDAR', boolean $clear = true ) : boolean
$text string The data to parse.
$base string The type of the base object.
$clear boolean If true clears this object before parsing.
return boolean True on successful import, false otherwise.
    public function parsevCalendar($text, $base = 'VCALENDAR', $clear = true)
    {
        if ($clear) {
            $this->clear();
        }
        $text = Horde_String::trimUtf8Bom($text);
        if (preg_match('/^BEGIN:' . $base . '(.*)^END:' . $base . '/ism', $text, $matches)) {
            $container = true;
            $vCal = $matches[1];
        } else {
            // Text isn't enclosed in BEGIN:VCALENDAR
            // .. END:VCALENDAR. We'll try to parse it anyway.
            $container = false;
            $vCal = $text;
        }
        $vCal = trim($vCal);
        // Extract all subcomponents.
        $matches = $components = null;
        if (preg_match_all('/^BEGIN:(.*)\\s*?(\\r\\n|\\r|\\n)(.*)^END:\\1\\s*?/Uims', $vCal, $components)) {
            foreach ($components[0] as $key => $data) {
                // Remove from the vCalendar data.
                $vCal = str_replace($data, '', $vCal);
            }
        } elseif (!$container) {
            return false;
        }
        // Unfold "quoted printable" folded lines like:
        //  BODY;ENCODING=QUOTED-PRINTABLE:=
        //  another=20line=
        //  last=20line
        while (preg_match_all('/^([^:]+;\\s*(ENCODING=)?QUOTED-PRINTABLE(.*=\\r?\\n)+(.*[^=])?(\\r?\\n|$))/mU', $vCal, $matches)) {
            foreach ($matches[1] as $s) {
                $r = preg_replace('/=\\r?\\n/', '', $s);
                $vCal = str_replace($s, $r, $vCal);
            }
        }
        // Unfold any folded lines.
        $vCal = preg_replace('/[\\r\\n]+[ \\t]/', '', $vCal);
        // Parse the remaining attributes.
        if (preg_match_all('/^((?:[^":]+|(?:"[^"]*")+)*):([^\\r\\n]*)\\r?$/m', $vCal, $matches)) {
            foreach ($matches[0] as $attribute) {
                preg_match('/([^;^:]*)((;(?:[^":]+|(?:"[^"]*")+)*)?):([^\\r\\n]*)[\\r\\n]*/', $attribute, $parts);
                $tag = trim(preg_replace('/^.*\\./', '', Horde_String::upper($parts[1])));
                $value = $parts[4];
                $params = array();
                // Parse parameters.
                if (!empty($parts[2])) {
                    preg_match_all('/;(([^;=]*)(=("[^"]*"|[^;]*))?)/', $parts[2], $param_parts);
                    foreach ($param_parts[2] as $key => $paramName) {
                        $paramName = Horde_String::upper($paramName);
                        $paramValue = $param_parts[4][$key];
                        if ($paramName == 'TYPE') {
                            $paramValue = preg_split('/(?<!\\\\),/', $paramValue);
                            if (count($paramValue) == 1) {
                                $paramValue = $paramValue[0];
                            }
                        }
                        if (is_string($paramValue)) {
                            if (preg_match('/"([^"]*)"/', $paramValue, $parts)) {
                                $paramValue = $parts[1];
                            }
                        } else {
                            foreach ($paramValue as $k => $tmp) {
                                if (preg_match('/"([^"]*)"/', $tmp, $parts)) {
                                    $paramValue[$k] = $parts[1];
                                }
                            }
                        }
                        if (isset($params[$paramName])) {
                            if (is_array($params[$paramName])) {
                                $params[$paramName][] = $paramValue;
                            } else {
                                $params[$paramName] = array($params[$paramName], $paramValue);
                            }
                        } else {
                            $params[$paramName] = $paramValue;
                        }
                    }
                }
                // Charset and encoding handling.
                if (isset($params['ENCODING']) && Horde_String::upper($params['ENCODING']) == 'QUOTED-PRINTABLE' || isset($params['QUOTED-PRINTABLE'])) {
                    $value = quoted_printable_decode($value);
                    if (isset($params['CHARSET'])) {
                        $value = Horde_String::convertCharset($value, $params['CHARSET'], 'UTF-8');
                    }
                } elseif (isset($params['CHARSET'])) {
                    $value = Horde_String::convertCharset($value, $params['CHARSET'], 'UTF-8');
                }
                // Get timezone info for date fields from $params.
                $tzid = isset($params['TZID']) ? trim($params['TZID'], '\\"') : false;
                switch ($tag) {
                    // Date fields.
                    case 'COMPLETED':
                    case 'CREATED':
                    case 'LAST-MODIFIED':
                    case 'X-MOZ-LASTACK':
                    case 'X-MOZ-SNOOZE-TIME':
                        $this->setAttribute($tag, $this->_parseDateTime($value, $tzid), $params);
                        break;
                    case 'BDAY':
                    case 'X-ANNIVERSARY':
                        $this->setAttribute($tag, $this->_parseDate($value), $params);
                        break;
                    case 'DTEND':
                    case 'DTSTART':
                    case 'DTSTAMP':
                    case 'DUE':
                    case 'AALARM':
                    case 'RECURRENCE-ID':
                        // types like AALARM may contain additional data after a ;
                        // ignore these.
                        $ts = explode(';', $value);
                        if (isset($params['VALUE']) && $params['VALUE'] == 'DATE') {
                            $this->setAttribute($tag, $this->_parseDate($ts[0]), $params);
                        } else {
                            $this->setAttribute($tag, $this->_parseDateTime($ts[0], $tzid), $params);
                        }
                        break;
                    case 'TRIGGER':
                        if (isset($params['VALUE']) && $params['VALUE'] == 'DATE-TIME') {
                            $this->setAttribute($tag, $this->_parseDateTime($value, $tzid), $params);
                        } else {
                            $this->setAttribute($tag, $this->_parseDuration($value), $params);
                        }
                        break;
                        // Comma seperated dates.
                    // Comma seperated dates.
                    case 'EXDATE':
                    case 'RDATE':
                        if (!strlen($value)) {
                            break;
                        }
                        $dates = array();
                        $separator = $this->_oldFormat ? ';' : ',';
                        preg_match_all('/' . $separator . '([^' . $separator . ']*)/', $separator . $value, $values);
                        foreach ($values[1] as $value) {
                            $stamp = $this->_parseDateTime($value);
                            if (!is_int($stamp)) {
                                continue;
                            }
                            $dates[] = array('year' => date('Y', $stamp), 'month' => date('m', $stamp), 'mday' => date('d', $stamp));
                        }
                        $this->setAttribute($tag, isset($dates[0]) ? $dates[0] : null, $params, true, $dates);
                        break;
                        // Duration fields.
                    // Duration fields.
                    case 'DURATION':
                        $this->setAttribute($tag, $this->_parseDuration($value), $params);
                        break;
                        // Period of time fields.
                    // Period of time fields.
                    case 'FREEBUSY':
                        $periods = array();
                        preg_match_all('/,([^,]*)/', ',' . $value, $values);
                        foreach ($values[1] as $value) {
                            $periods[] = $this->_parsePeriod($value);
                        }
                        $this->setAttribute($tag, isset($periods[0]) ? $periods[0] : null, $params, true, $periods);
                        break;
                        // UTC offset fields.
                    // UTC offset fields.
                    case 'TZOFFSETFROM':
                    case 'TZOFFSETTO':
                        $this->setAttribute($tag, $this->_parseUtcOffset($value), $params);
                        break;
                        // Integer fields.
                    // Integer fields.
                    case 'PERCENT-COMPLETE':
                    case 'PRIORITY':
                    case 'REPEAT':
                    case 'SEQUENCE':
                        $this->setAttribute($tag, intval($value), $params);
                        break;
                        // Geo fields.
                    // Geo fields.
                    case 'GEO':
                        if ($value) {
                            if ($this->_oldFormat) {
                                $floats = explode(',', $value);
                                $value = array('latitude' => floatval($floats[1]), 'longitude' => floatval($floats[0]));
                            } else {
                                $floats = explode(';', $value);
                                $value = array('latitude' => floatval($floats[0]), 'longitude' => floatval($floats[1]));
                            }
                        }
                        $this->setAttribute($tag, $value, $params);
                        break;
                        // Recursion fields.
                    // Recursion fields.
                    case 'EXRULE':
                    case 'RRULE':
                        $this->setAttribute($tag, trim($value), $params);
                        break;
                        // ADR, ORG and N are lists seperated by unescaped semicolons
                        // with a specific number of slots.
                    // ADR, ORG and N are lists seperated by unescaped semicolons
                    // with a specific number of slots.
                    case 'ADR':
                    case 'N':
                    case 'ORG':
                        $value = trim($value);
                        // As of rfc 2426 2.4.2 semicolon, comma, and colon must
                        // be escaped (comma is unescaped after splitting below).
                        $value = str_replace(array('\\n', '\\N', '\\;', '\\:'), array($this->_newline, $this->_newline, ';', ':'), $value);
                        // Split by unescaped semicolons:
                        $values = preg_split('/(?<!\\\\);/', $value);
                        $value = str_replace('\\;', ';', $value);
                        $values = str_replace('\\;', ';', $values);
                        $this->setAttribute($tag, trim($value), $params, true, $values);
                        break;
                        // String fields.
                    // String fields.
                    default:
                        if ($this->_oldFormat) {
                            // vCalendar 1.0 and vCard 2.1 only escape semicolons
                            // and use unescaped semicolons to create lists.
                            $value = trim($value);
                            // Split by unescaped semicolons:
                            $values = preg_split('/(?<!\\\\);/', $value);
                            $value = str_replace('\\;', ';', $value);
                            $values = str_replace('\\;', ';', $values);
                            $this->setAttribute($tag, trim($value), $params, true, $values);
                        } else {
                            $value = trim($value);
                            // As of rfc 2426 2.4.2 semicolon, comma, and colon
                            // must be escaped (comma is unescaped after splitting
                            // below).
                            $value = str_replace(array('\\n', '\\N', '\\;', '\\:', '\\\\'), array($this->_newline, $this->_newline, ';', ':', '\\'), $value);
                            // Split by unescaped commas.
                            $values = preg_split('/(?<!\\\\),/', $value);
                            $value = str_replace('\\,', ',', $value);
                            $values = str_replace('\\,', ',', $values);
                            $this->setAttribute($tag, trim($value), $params, true, $values);
                        }
                        break;
                }
            }
        }
        // Process all components.
        if ($components) {
            // vTimezone components are processed first. They are
            // needed to process vEvents that may use a TZID.
            foreach ($components[0] as $key => $data) {
                $type = trim($components[1][$key]);
                if ($type != 'VTIMEZONE') {
                    continue;
                }
                $component = $this->newComponent($type, $this);
                if ($component === false) {
                    throw new Horde_Icalendar_Exception('Unable to create object for type ' . $type);
                }
                $component->parsevCalendar($data, $type);
                $this->addComponent($component);
                // Remove from the vCalendar data.
                $vCal = str_replace($data, '', $vCal);
            }
            // Now process the non-vTimezone components.
            foreach ($components[0] as $key => $data) {
                $type = trim($components[1][$key]);
                if ($type == 'VTIMEZONE') {
                    continue;
                }
                $component = $this->newComponent($type, $this);
                if ($component === false) {
                    throw new Horde_Icalendar_Exception('Unable to create object for type ' . $type);
                }
                $component->parsevCalendar($data, $type);
                $this->addComponent($component);
            }
        }
        return true;
    }

Usage Example

Example #1
0
 public function testGeo()
 {
     $ical = new Horde_Icalendar();
     $ical->parsevCalendar(file_get_contents(__DIR__ . '/fixtures/geo1.vcf'));
     $this->assertEquals(array('latitude' => -17.87, 'longitude' => 37.24), $ical->getComponent(0)->getAttribute('GEO'));
     $ical->parsevCalendar(file_get_contents(__DIR__ . '/fixtures/geo2.vcf'));
     $this->assertEquals(array('latitude' => 37.386013, 'longitude' => -122.082932), $ical->getComponent(0)->getAttribute('GEO'));
 }
All Usage Examples Of Horde_Icalendar::parsevCalendar