17 include_once(
'vObject.php');
19 include_once(
'vProperty.php');
29 private $propertyLocation;
31 const KEYBEGIN =
'BEGIN:';
32 const KEYBEGINLENGTH = 6;
33 const KEYEND =
"END:";
34 const KEYENDLENGTH = 4;
37 public static $PREPARSED =
false;
39 function __construct($propstring=
null, &$refData=
null){
40 parent::__construct($master);
44 if(isset($propstring) && gettype($propstring) ==
'string'){
45 $this->initFromText($propstring);
46 }
else if(isset($refData)){
47 if(gettype($refData) ==
'string'){
48 $this->initFromText($refData);
49 }
else if(gettype($refData) ==
'object') {
50 $this->initFromIterator($refData);
65 function initFromIterator(&$iterator, $begin = -1){
66 $this->iterator = &$iterator;
72 $iterator = $this->iterator;
74 $line = $iterator->current();
75 $seek = $iterator->key();
77 $posStart = strpos(strtoupper($line), vComponent::KEYBEGIN);
78 if($posStart !==
false && $posStart == 0){
79 if(!isset($this->type)){
80 $this->seekBegin = $seek;
82 $this->type = strtoupper(substr($line, vComponent::KEYBEGINLENGTH));
86 $posEnd = strpos(strtoupper($line), vComponent::KEYEND);
87 if($posEnd !==
false && $posEnd == 0){
88 $thisEnd = strtoupper(substr($line, vComponent::KEYENDLENGTH));
89 if($thisEnd == $this->type){
90 $this->seekEnd = $seek;
92 $len = strlen($this->type);
93 $last = $this->type[$len-1];
95 $this->type = strtoupper(substr($this->type, 0, $len-1));
109 }
while($iterator->valid());
114 public function getIterator(){
115 return $this->iterator;
118 function initFromText(&$plainText){
135 $arrayOfLines =
new ArrayObject(preg_split(
'{\r?\n}', $plain2));
136 $this->iterator = $arrayOfLines->getIterator();
142 $this->parseFrom($this->iterator);
147 if(isset($this->iterator) && isset($this->seekBegin)){
148 $this->iterator->seek($this->seekBegin);
164 if(!isset($this->properties) && !isset($this->components) && $this->isValid()){
165 unset($this->properties);
166 unset($this->components);
169 $this->parseFrom($this->iterator);
175 if(isset($this->components)){
176 foreach($this->components as $comp){
181 if($this->isValid()){
182 unset($this->properties);
183 unset($this->components);
190 function parseFrom(&$iterator){
193 $begin = $iterator->key();
198 $line = $iterator->current();
200 $end = $iterator->key();
202 $pos = strpos(strtoupper($line), vComponent::KEYBEGIN);
204 if($pos !==
false && $pos == 0) {
205 $type = strtoupper(substr($line, vComponent::KEYBEGINLENGTH));
207 if($typelen !== 0 && strncmp($this->type, $type, $typelen) !== 0){
208 $this->components[] =
new vComponent(
null, $iterator);
214 $typelen = strlen($type);
215 if($type[$typelen-1] ==
"\r"){
217 $this->type = substr($type, 0, $typelen);
229 $pos = strpos(strtoupper($line), vComponent::KEYEND);
231 if($pos !==
false && $pos == 0) {
232 $this->seekBegin = $begin;
233 $this->seekEnd = $end;
250 $parameters = preg_split(
'(:|;)', $line);
251 $possiblename = strtoupper(array_shift( $parameters ));
252 $this->properties[] =
new vProperty($possiblename, $this->master, $iterator, $end);
263 if($iterator->valid())
266 }
while($iterator->valid() && ( !isset($this->seekEnd) || $this->seekEnd > $end ) );
280 return isset($this->components) ? count($this->components) : 0;
289 return isset($this->properties) ? count($this->properties) : 0;
299 return $this->components[$position];
305 function getPropertyAt($position){
308 return $this->properties[$position];
315 function clearPropertyAt($position) {
317 if($this->isValid()){
322 foreach( $this->properties AS $k => $v ) {
323 if ( $i == $position ) {
324 unset($this->properties[$k]);
328 $this->properties = array_values($this->properties);
344 if ( $this->isValid() ) {
347 $this->type = strtoupper($type);
359 if(isset($this->components)){
360 foreach( $this->components AS $k => $v ) {
361 $also = $v->CollectParameterValues($parameter_name);
362 $values = array_merge( $values, $also );
365 if(isset($this->properties)){
366 foreach( $this->properties AS $k => $v ) {
367 $also = $v->GetParameterValue($parameter_name);
368 if ( isset($also) && $also !=
"" ) {
384 foreach( $this->properties AS $k => $v ) {
385 if ( is_object($v) && $v->Name() == $type ) {
388 else if ( !is_object($v) ) {
389 dbg_error_log(
"ERROR",
'vComponent::GetProperty(): Trying to get %s on %s which is not an object!', $type, $v );
402 if ( isset($p) )
return $p->Value();
414 if(!isset($this->properties)){
417 $properties = array();
420 if (gettype($type) ==
'string') {
421 $testtypes = array( strtoupper($type) =>
true );
423 $testtypes = array();
424 foreach ($type as $propname => $val) {
425 $testtypes[strtoupper($propname)] = $val;
430 foreach( $this->properties AS $k => $v ) {
431 $fullname = $v->Name();
432 $propname = preg_replace(
'/^.*[.]/',
'', $fullname );
439 || (isset($testtypes[$propname]) && $testtypes[$propname])
440 || (isset($testtypes[$fullname]) && $testtypes[$fullname])
458 $properties = array();
459 dbg_error_log(
'vComponent',
"GetPropertiesByPath: Querying within '%s' for path '%s'", $this->type, $path );
460 if ( !preg_match(
'#(/?)(!?)([^/]+)(/?.*)$#', $path, $matches ) )
return $properties;
462 $anchored = ($matches[1] ==
'/');
463 $inverted = ($matches[2] ==
'!');
464 $ourtest = $matches[3];
465 $therest = $matches[4];
466 dbg_error_log(
'vComponent',
"GetPropertiesByPath: Matches: %s -- %s -- %s -- %s\n", $matches[1], $matches[2], $matches[3], $matches[4] );
467 if ( $ourtest ==
'*' || (($ourtest == $this->type) !== $inverted) && $therest !=
'' ) {
468 if ( preg_match(
'#^/(!?)([^/]+)$#', $therest, $matches ) ) {
469 $normmatch = ($matches[1] ==
'');
470 $proptest = $matches[2];
473 if(isset($thisproperties) && count($thisproperties) > 0){
474 foreach( $thisproperties AS $k => $v ) {
475 if ( $proptest ==
'*' || (($v->Name() == $proptest) === $normmatch ) ) {
487 $properties = array_merge( $properties, $v->GetPropertiesByPath($therest) );
497 $properties = array_merge( $properties, $v->GetPropertiesByPath($path) );
500 dbg_error_log(
'vComponent',
"GetPropertiesByPath: Found %d within '%s' for path '%s'\n", count($properties), $this->type, $path );
511 if($this->isValid()){
515 if ( $type !=
null ) {
516 $testtypes = (gettype($type) ==
'string' ? array( $type =>
true ) : $type );
518 foreach( $this->properties AS $k => $v ) {
519 if ( isset($testtypes[$v->Name()]) && $testtypes[$v->Name()] ) {
520 unset($this->properties[$k]);
524 $this->properties = array_values($this->properties);
528 $this->properties = array();
538 foreach( $new_properties AS $k => $v ) {
539 $this->properties[] = $v;
550 function AddProperty( $new_property, $value =
null, $parameters =
null ) {
552 if ( isset($value) && gettype($new_property) ==
'string' ) {
553 $new_prop =
new vProperty(
'', $this->master);
554 $new_prop->Name($new_property);
555 $new_prop->Value($value);
556 if ( $parameters !=
null ) {
557 $new_prop->Parameters($parameters);
560 $this->properties[] = $new_prop;
562 else if ( $new_property instanceof
vProperty ) {
563 $this->properties[] = $new_property;
564 $new_property->setMaster($this->master);
567 if($this->isValid()){
583 $components = isset($this->components) ? $this->components : array();
585 if ( $type !=
null ) {
587 $testtypes = (gettype($type) ==
'string' ? array( $type =>
true ) : $type );
588 foreach( $components AS $k => $v ) {
593 if ( !($normal_match && isset($testtypes[$v->GetType()]) && $testtypes[$v->GetType()] )
594 && !( !$normal_match && (!isset($testtypes[$v->GetType()]) || !$testtypes[$v->GetType()])) ) {
595 unset($components[$k]);
598 $components = array_values($components);
610 if($this->isValid()){
615 if ( $type !=
null && !empty($this->components)) {
616 $testtypes = (gettype($type) ==
'string' ? array( $type =>
true ) : $type );
618 foreach( $this->components AS $k => $v ) {
619 $this->components[$k]->ClearComponents($testtypes);
620 if ( isset($testtypes[$v->GetType()]) && $testtypes[$v->GetType()] ) {
621 unset($this->components[$k]);
622 if ( $this->isValid()) {
630 $this->components = array();
631 if ( $this->isValid()) {
636 return $this->isValid();
647 if ( $this->isValid()) {
650 if ( empty($type) ) {
651 $this->components = $new_component;
656 foreach( $new_component AS $k => $v ) {
657 $this->components[] = $v;
668 if ( is_array($new_component) && count($new_component) == 0 )
return;
670 if ( $this->isValid()) {
675 if ( is_array($new_component) ) {
676 foreach( $new_component AS $k => $v ) {
677 $this->components[] = $v;
678 if ( !method_exists($v,
'setMaster') ) fatal(
'Component to be added must be a vComponent');
679 $v->setMaster($this->master);
683 if ( !method_exists($new_component,
'setMaster') ) fatal(
'Component to be added must be a vComponent');
684 $new_component->setMaster($this->master);
685 $this->components[] = $new_component;
688 catch( Exception $e ) {
701 if(!isset($this->components)){
705 foreach( $this->components AS $k => $v ) {
706 if ( !isset($keep[$v->GetType()]) ) {
707 unset($this->components[$k]);
708 if ( $this->isValid()) {
712 else if ( $recursive ) {
713 $v->MaskComponents($keep);
725 if ( !isset($component_list) || isset($component_list[$this->type]) ) {
726 foreach( $this->properties AS $k => $v ) {
727 if ( !isset($keep[$v->Name()]) || !$keep[$v->Name()] ) {
728 unset($this->properties[$k]);
729 if ( $this->isValid()) {
735 if(isset($this->components)){
736 foreach( $this->components AS $k => $v ) {
737 $v->MaskProperties($keep, $component_list);
752 $strs = preg_split(
"/\r?\n/", $content );
754 foreach ($strs as $str) {
756 $wrapped_bit = (strlen($str) < 76 ? $str : preg_replace(
'/(.{72})/u',
'$1'.
"\r\n ", $str )) .self::VEOL;
758 $wrapped .= $wrapped_bit;
769 return preg_replace(
'/\r?\n[ \t]/',
'', $content );
780 $unrolledComponents = isset($this->components);
781 $rendered = vComponent::KEYBEGIN . $this->type . self::VEOL;
784 if($this->isValid()){
790 if($unrolledComponents){
792 foreach($this->components as $component){
795 $component_render = $component->RenderWithoutWrap(
null, $force_rendering );
796 if(strlen($component_render) > 0){
797 $rendered .= $component_render . self::VEOL;
805 return $rendered . vComponent::KEYEND . $this->type;
814 if(isset($this->properties)){
815 foreach( $this->properties AS $k => $v ) {
816 if ( method_exists($v,
'Render') ) {
817 $forebug = $v->Render() . self::VEOL;
818 $rendered .= $forebug;
836 if(isset($this->type)){
837 $lentype = strlen($this->type);
840 $iterator = $this->iterator;
843 $line = $iterator->current() . self::VEOL;
844 $seek = $iterator->key();
846 $posStart = strpos($line, vComponent::KEYBEGIN);
847 if($posStart !==
false && $posStart == 0){
848 $type = substr($line, vComponent::KEYBEGINLENGTH);
849 if(!isset($this->type)){
852 $lentype = strlen($this->type);
853 }
else if(strncmp($type, $this->type, $lentype) != 0){
856 if($unrolledComponents){
864 $posEnd = strpos($line, vComponent::KEYEND);
865 if($posEnd !==
false && $posEnd == 0){
866 $thisEnd = substr($line, vComponent::KEYENDLENGTH);
867 if(strncmp($thisEnd, $this->type, $lentype) == 0){
869 $this->seekEnd = $seek;
872 }
else if($unrolledComponents){
880 }
else if($inInnerObject === 0 || !$unrolledComponents){
885 }
while($iterator->valid() && ( !isset($this->seekEnd) || $this->seekEnd > $seek));
899 function Render($restricted_properties =
null, $force_rendering =
false){
906 if(isset($this->components)){
907 foreach($this->components as $comp){
908 if(!$comp->isValid()){
929 foreach( $filters AS $k => $v ) {
930 $tag = $v->GetNSTag();
933 case 'urn:ietf:params:xml:ns:caldav:is-defined':
934 case 'urn:ietf:params:xml:ns:carddav:is-defined':
935 if ( count($this->properties) == 0 && count($this->components) == 0 )
return false;
938 case 'urn:ietf:params:xml:ns:caldav:is-not-defined':
939 case 'urn:ietf:params:xml:ns:carddav:is-not-defined':
940 if ( count($this->properties) > 0 || count($this->components) > 0 )
return false;
943 case 'urn:ietf:params:xml:ns:caldav:comp-filter':
944 case 'urn:ietf:params:xml:ns:carddav:comp-filter':
945 $subcomponents = $this->
GetComponents($v->GetAttribute(
'name'));
946 $subfilter = $v->GetContent();
949 $subtag = $subfilter[0]->GetNSTag();
950 if ( $subtag ==
'urn:ietf:params:xml:ns:caldav:is-not-defined'
951 || $subtag ==
'urn:ietf:params:xml:ns:carddav:is-not-defined' ) {
952 if ( count($properties) > 0 ) {
957 else if ( count($subcomponents) == 0 ) {
958 if ( $subtag ==
'urn:ietf:params:xml:ns:caldav:is-defined'
959 || $subtag ==
'urn:ietf:params:xml:ns:carddav:is-defined' ) {
965 $negate = $subfilter[0]->GetAttribute(
"negate-condition");
966 if ( empty($negate) || strtolower($negate) !=
'yes' )
return false;
970 foreach( $subcomponents AS $kk => $subcomponent ) {
971 if ( ! $subcomponent->TestFilter($subfilter) )
return false;
976 case 'urn:ietf:params:xml:ns:carddav:prop-filter':
977 case 'urn:ietf:params:xml:ns:caldav:prop-filter':
978 $subfilter = $v->GetContent();
979 $properties = $this->
GetProperties($v->GetAttribute(
"name"));
980 dbg_error_log(
'vCalendar',
":TestFilter: Found '%d' props of type '%s'", count($properties), $v->GetAttribute(
'name') );
981 if ( empty($subfilter) ) {
983 $subtag = str_replace(
'prop-filter',
'is-defined', $tag);
985 $subtag = $subfilter[0]->GetNSTag();
987 if ( $subtag ==
'urn:ietf:params:xml:ns:caldav:is-not-defined'
988 || $subtag ==
'urn:ietf:params:xml:ns:carddav:is-not-defined' ) {
989 if ( count($properties) > 0 ) {
994 else if ( count($properties) == 0 ) {
995 if ( $subtag ==
'urn:ietf:params:xml:ns:caldav:is-defined'
996 || $subtag ==
'urn:ietf:params:xml:ns:carddav:is-defined' ) {
1007 $matchAll = $v->GetAttribute(
"test");
1008 if (isset($matchAll) && $matchAll ==
"allof") {
1019 foreach( $properties AS $kk => $property ) {
1020 if ( empty($subfilter) || $property->TestFilter($subfilter, $matchAll) ) {
1028 if ( $subtag ==
'urn:ietf:params:xml:ns:caldav:param-filter'
1029 || $subtag ==
'urn:ietf:params:xml:ns:carddav:param-filter' ) {
1030 $paramSubFilter = $subfilter[0]->GetContent();
1031 if (!empty($paramSubFilter)) {
1032 $paramSubFilterTag = $paramSubFilter[0]->getNSTag();
1034 if ( $paramSubFilterTag ==
'urn:ietf:params:xml:ns:caldav:is-not-defined'
1035 || $paramSubFilterTag ==
'urn:ietf:params:xml:ns:carddav:is-not-defined' ) {
1037 $matchesNeeded = count($properties);
1042 if ($matchCount < $matchesNeeded) {
AddComponent( $new_component)
getComponentAt($position)
AddProperty( $new_property, $value=null, $parameters=null)
Render($restricted_properties=null, $force_rendering=false)
RenderWithoutWrapFromObjects()
RenderWithoutWrap($restricted_properties=null, $force_rendering=false)
SetComponents( $new_component, $type=null)
ClearComponents( $type=null)
UnwrapComponent(&$content)
MaskComponents( $keep, $recursive=true)
CollectParameterValues( $parameter_name)
GetPropertiesByPath( $path)
ClearProperties( $type=null)
MaskProperties( $keep, $component_list=null)
GetComponents( $type=null, $normal_match=true)
GetProperties( $type=null)
RenderWithoutWrapFromIterator($unrolledComponents)
SetProperties( $new_properties, $type=null)