Вход Регистрация
Файл: ips_kernel/sabre/Sabre/CalDAV/XMLUtil.php
Строк: 216
<?php

/**
 * XML utilities for CalDAV 
 *
 * This class contains a few static methods used for parsing certain CalDAV 
 * requests.
 *
 * @package Sabre
 * @subpackage CalDAV
 * @copyright Copyright (C) 2007-2010 Rooftop Solutions. All rights reserved.
 * @author Evert Pot (http://www.rooftopsolutions.nl/) 
 * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
 */
class Sabre_CalDAV_XMLUtil {

    
/**
     * This function parses the calendar-query report request body
     *
     * The body is quite complicated, so we're turning it into a PHP
     * array.
     *
     * The resulting associative array has xpath expressions as keys.
     * By default the xpath expressions should simply be checked for existance
     * The xpath expressions can point to elements or attributes.
     * 
     * The array values can contain a number of items, which alters the query
     * filter. 
     *
     * * time-range. Must also check if the todo or event falls within the
     *               specified timerange. How this is interpreted depends on
     *               the type of object (VTODO, VEVENT, VJOURNAL, etc)
     * * is-not-defined
     *               Instead of checking if the attribute or element exist,
     *               we must check if it doesn't.
     * * text-match
     *               Checks if the value of the attribute or element matches
     *               the specified value. This is actually another array with
     *               the 'collation', 'value' and 'negate-condition' items.
     *
     * Refer to the CalDAV spec for more information.
     * 
     * @param DOMNode $domNode 
     * @param string $basePath used for recursive calls.
     * @param array $filters used for recursive calls.
     * @return array 
     */
    
static public function parseCalendarQueryFilters($domNode,$basePath '/c:iCalendar', &$filters = array()) {

        foreach(
$domNode->childNodes as $child) {

            switch(
Sabre_DAV_XMLUtil::toClarkNotation($child)) {

                case 
'{urn:ietf:params:xml:ns:caldav}comp-filter' :
                case 
'{urn:ietf:params:xml:ns:caldav}prop-filter' :
                   
                    
$filterName $basePath '/' 'c:' strtolower($child->getAttribute('name'));
                    
$filters[$filterName] = array(); 

                    
self::parseCalendarQueryFilters($child$filterName,$filters);
                    break;

                case 
'{urn:ietf:params:xml:ns:caldav}time-range' :
               
                    if (
$start $child->getAttribute('start')) {
                        
$start self::parseICalendarDateTime($start);
                    } else {
                        
$start null;
                    }
                    if (
$end $child->getAttribute('end')) {
                        
$end self::parseICalendarDateTime($end);
                    } else {
                        
$end null;
                    }

                    if (!
is_null($start) && !is_null($end) && $end <= $start) {
                        throw new 
Sabre_DAV_Exception_BadRequest('The end-date must be larger than the start-date in the time-range filter');
                    }

                    
$filters[$basePath]['time-range'] = array(
                        
'start' => $start,
                        
'end'   => $end
                    
);
                    break;

                case 
'{urn:ietf:params:xml:ns:caldav}is-not-defined' :
                    
$filters[$basePath]['is-not-defined'] = true;
                    break;

                case 
'{urn:ietf:params:xml:ns:caldav}param-filter' :
               
                    
$filterName $basePath '/@' strtolower($child->getAttribute('name'));
                    
$filters[$filterName] = array();
                    
self::parseCalendarQueryFilters($child$filterName$filters);
                    break;

                case 
'{urn:ietf:params:xml:ns:caldav}text-match' :
               
                    
$collation $child->getAttribute('collation');
                    if (!
$collation$collation 'i;ascii-casemap';

                    
$filters[$basePath]['text-match'] = array(
                        
'collation' => $collation,
                        
'negate-condition' => $child->getAttribute('negate-condition')==='yes',
                        
'value' => $child->nodeValue,
                    );
                    break;

            }

        }

        return 
$filters;

    }

    
/**
     * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
     *
     * Specifying a reference timezone is optional. It will only be used
     * if the non-UTC format is used. The argument is used as a reference, the 
     * returned DateTime object will still be in the UTC timezone.
     *
     * @param string $dt 
     * @param DateTimeZone $tz 
     * @return DateTime 
     */
    
static public function parseICalendarDateTime($dt,DateTimeZone $tz null) {

        
// Format is YYYYMMDD + "T" + hhmmss 
        
$result preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/',$dt,$matches);

        if (!
$result) {
            throw new 
Sabre_DAV_Exception_BadRequest('The supplied iCalendar datetime value is incorrect: ' $dt);
        }

        if (
$matches[7]==='Z' || is_null($tz)) {
            
$tz = new DateTimeZone('UTC');
        } 
        
$date = new DateTime($matches[1] . '-' $matches[2] . '-' $matches[3] . ' ' $matches[4] . ':' $matches[5] .':' $matches[6], $tz);

        
// Still resetting the timezone, to normalize everything to UTC
        
$date->setTimeZone(new DateTimeZone('UTC'));
        return 
$date;

    }

    
/**
     * Parses an iCalendar (rfc5545) formatted datetime and returns a DateTime object
     *
     * @param string $date 
     * @param DateTimeZone $tz 
     * @return DateTime 
     */
    
static public function parseICalendarDate($date) {

        
// Format is YYYYMMDD
        
$result preg_match('/^([1-3][0-9]{3})([0-1][0-9])([0-3][0-9])$/',$date,$matches);

        if (!
$result) {
            throw new 
Sabre_DAV_Exception_BadRequest('The supplied iCalendar date value is incorrect: ' $date);
        }

        
$date = new DateTime($matches[1] . '-' $matches[2] . '-' $matches[3], new DateTimeZone('UTC'));
        return 
$date;

    }
   
    
/**
     * Parses an iCalendar (RFC5545) formatted duration and returns a string suitable
     * for strtotime or DateTime::modify.
     *
     * NOTE: When we require PHP 5.3 this can be replaced by the DateTimeInterval object, which
     * supports ISO 8601 Intervals, which is a superset of ICalendar durations.
     *
     * For now though, we're just gonna live with this messy system
     *
     * @param string $duration
     * @return string
     */
    
static public function parseICalendarDuration($duration) {

        
$result preg_match('/^(?P<plusminus>+|-)?P((?P<week>d+)W)?((?P<day>d+)D)?(T((?P<hour>d+)H)?((?P<minute>d+)M)?((?P<second>d+)S)?)?$/'$duration$matches);
        if (!
$result) {
            throw new 
Sabre_DAV_Exception_BadRequest('The supplied iCalendar duration value is incorrect: ' $duration);
        }
       
        
$parts = array(
            
'week',
            
'day',
            
'hour',
            
'minute',
            
'second',
        );

        
$newDur '';
        foreach(
$parts as $part) {
            if (isset(
$matches[$part]) && $matches[$part]) {
                
$newDur.=' '.$matches[$part] . ' ' $part 's';
            }
        }

        
$newDur = ($matches['plusminus']==='-'?'-':'+') . trim($newDur);
        return 
$newDur;

    }

}
Онлайн: 1
Реклама