Andrew's Web Libraries (AWL)
vComponent.php
1 <?php
17  include_once('vObject.php');
18  //include_once('HeapLines.php');
19  include_once('vProperty.php');
20 
21  class vComponent extends vObject{
22 
23  private $components;
24  private $properties;
25  private $type;
26  private $iterator;
27  private $seekBegin;
28  private $seekEnd;
29  private $propertyLocation;
30 
31  const KEYBEGIN = 'BEGIN:';
32  const KEYBEGINLENGTH = 6;
33  const KEYEND = "END:";
34  const KEYENDLENGTH = 4;
35  const VEOL = "\r\n";
36 
37  public static $PREPARSED = false;
38 
39  function __construct($propstring=null, &$refData=null){
40  parent::__construct($master);
41 
42  unset($this->type);
43 
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);
51  }
52  } else {
53  //$text = '';
54  //$this->initFromText($text);
55  }
56 
57 
58 // if(isset($this->iterator)){
59 // $this->parseFrom($this->iterator);
60 // }
61 
62 
63  }
64 
65  function initFromIterator(&$iterator, $begin = -1){
66  $this->iterator = &$iterator;
67 
68  //$this->seekBegin = $this->iterator->key();
69 
70 
71 
72  $iterator = $this->iterator;
73  do {
74  $line = $iterator->current();
75  $seek = $iterator->key();
76 
77  $posStart = strpos(strtoupper($line), vComponent::KEYBEGIN);
78  if($posStart !== false && $posStart == 0){
79  if(!isset($this->type)){
80  $this->seekBegin = $seek;
81 
82  $this->type = strtoupper(substr($line, vComponent::KEYBEGINLENGTH));
83  }
84  } else {
85 
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;
91  //$iterator->next();
92  $len = strlen($this->type);
93  $last = $this->type[$len-1];
94  if($last == "\r"){
95  $this->type = strtoupper(substr($this->type, 0, $len-1));
96  }
97  break;
98  }
99 
100  } else {
101  //$this->properties[] = new vProperty(null, $iterator, $seek);
102  }
103  }
104 
105 
106 
107 
108  $iterator->next();
109  } while($iterator->valid());
110  //$this->parseFrom($iterator);
111 
112  }
113 
114  public function getIterator(){
115  return $this->iterator;
116  }
117 
118  function initFromText(&$plainText){
119  $plain2 = $this->UnwrapComponent($plainText);
120 
121  //$file = fopen('data.out.tmp', 'w');
122  //$plain3 = preg_replace('{\r?\n}', '\r\n', $plain2 );
123  //fwrite($file, $plain2);
124  //fclose($file);
125  //$lines = &explode(PHP_EOL, $plain2);
126 // $arrayData = new ArrayObject($lines);
127 // $this->iterator = &$arrayData->getIterator();
128 // $this->initFromIterator($this->iterator, 0);
129 // unset($plain);
130 // unset($iterator);
131 // unset($arrayData);
132 // unset($lines);
133 
134  // Note that we can't use PHP_EOL here, since the line splitting should handle *either* of CR, CRLF or LF line endings.
135  $arrayOfLines = new ArrayObject(preg_split('{\r?\n}', $plain2));
136  $this->iterator = $arrayOfLines->getIterator();
137  unset($plain2);
138  //$this->initFromIterator($this->iterator);
139  //$this->iterator = new HeapLines($plain);
140 
141  //$this->initFromIterator(new HeapLines($plain), 0);
142  $this->parseFrom($this->iterator);
143 
144  }
145 
146  function rewind(){
147  if(isset($this->iterator) && isset($this->seekBegin)){
148  $this->iterator->seek($this->seekBegin);
149  }
150  }
151 
152 
163  function explode(){
164  if(!isset($this->properties) && !isset($this->components) && $this->isValid()){
165  unset($this->properties);
166  unset($this->components);
167  unset($this->type);
168  $this->rewind();
169  $this->parseFrom($this->iterator);
170  }
171  }
172 
173  function close(){
174 
175  if(isset($this->components)){
176  foreach($this->components as $comp){
177  $comp->close();
178  }
179  }
180 
181  if($this->isValid()){
182  unset($this->properties);
183  unset($this->components);
184  }
185 
186 
187 
188  }
189 
190  function parseFrom(&$iterator){
191 
192 
193  $begin = $iterator->key();
194  $typelen = 0;
195  //$count = $lines->count();
196 
197  do{
198  $line = $iterator->current();
199  //$line = substr($current, 0, strlen($current) -1);
200  $end = $iterator->key();
201 
202  $pos = strpos(strtoupper($line), vComponent::KEYBEGIN);
203  $callnext = true;
204  if($pos !== false && $pos == 0) {
205  $type = strtoupper(substr($line, vComponent::KEYBEGINLENGTH));
206 
207  if($typelen !== 0 && strncmp($this->type, $type, $typelen) !== 0){
208  $this->components[] = new vComponent(null, $iterator);
209  $callnext = false;
210  } else {
211  // in special cases when is "\r" on end remove it
212  // We should probably throw an error if we get here, because the
213  // thing that splits stuff should not be giving us this.
214  $typelen = strlen($type);
215  if($type[$typelen-1] == "\r"){
216  $typelen--;
217  $this->type = substr($type, 0, $typelen);
218  } else {
219  $this->type = $type;
220  }
221 
222 
223  //$iterator->offsetUnset($end);
224  //$iterator->seek($begin);
225  //$callnext = false;
226  }
227 
228  } else {
229  $pos = strpos(strtoupper($line), vComponent::KEYEND);
230 
231  if($pos !== false && $pos == 0) {
232  $this->seekBegin = $begin;
233  $this->seekEnd = $end;
234  //$iterator->offsetUnset($end);
235  //$iterator->seek($end-2);
236  //$line2 = $iterator->current();
237  //$this->seekEnd = $iterator->key();
238 
239  //$callnext = false;
240  //$newheap = $lines->createLineHeapFrom($start, $end);
241  //$testfistline = $newheap->substr(0);
242  //echo "end:" . $this->key . "[$start, $end]<br>";
243  //$lines->nextLine();
244  //$iterator->offsetUnset($end);
245  return;
246  } else {
247 // $prstart = $lines->getSwheretartLineOnHeap();
248 // $prend =
249 //$this->properties[] = new vProperty("AHOJ");
250  $parameters = preg_split( '(:|;)', $line);
251  $possiblename = strtoupper(array_shift( $parameters ));
252  $this->properties[] = new vProperty($possiblename, $this->master, $iterator, $end);
253  //echo $this->key . ' property line' . "[$prstart,$prend]<br>";
254 
255  }
256  }
257 
258 // if($callnext){
259 // $iterator->next();
260 // }
261  //if($callnext)
262  // $iterator->offsetUnset($end);
263  if($iterator->valid())
264  $iterator->next();
265 
266  } while($iterator->valid() && ( !isset($this->seekEnd) || $this->seekEnd > $end ) );
267  //$lines->getEndLineOnHeap();
268 
269 
270  }
271 
272 
273 
278  public function ComponentCount(){
279  $this->explode();
280  return isset($this->components) ? count($this->components) : 0;
281  }
282 
287  public function propertiesCount(){
288  $this->explode();
289  return isset($this->properties) ? count($this->properties) : 0;
290  }
291 
296  public function getComponentAt($position){
297  $this->explode();
298  if($this->ComponentCount() > $position){
299  return $this->components[$position];
300  } else {
301  return null;
302  }
303  }
304 
305  function getPropertyAt($position){
306  $this->explode();
307  if($this->propertiesCount() > $position){
308  return $this->properties[$position];
309  } else {
310  return null;
311  }
312 
313  }
314 
315  function clearPropertyAt($position) {
316  $this->explode();
317  if($this->isValid()){
318  $this->invalidate();
319  }
320 
321  $i=0; // property index/position is relative to current vComponent
322  foreach( $this->properties AS $k => $v ) {
323  if ( $i == $position ) {
324  unset($this->properties[$k]);
325  }
326  $i++;
327  }
328  $this->properties = array_values($this->properties);
329  }
330 
331 
335  function GetType() {
336  return $this->type;
337  }
338 
339 
343  function SetType( $type ) {
344  if ( $this->isValid() ) {
345  $this->invalidate();
346  };
347  $this->type = strtoupper($type);
348  return $this->type;
349  }
350 
351 
356  function CollectParameterValues( $parameter_name ) {
357  $this->explode();
358  $values = array();
359  if(isset($this->components)){
360  foreach( $this->components AS $k => $v ) {
361  $also = $v->CollectParameterValues($parameter_name);
362  $values = array_merge( $values, $also );
363  }
364  }
365  if(isset($this->properties)){
366  foreach( $this->properties AS $k => $v ) {
367  $also = $v->GetParameterValue($parameter_name);
368  if ( isset($also) && $also != "" ) {
369 // dbg_error_log( 'vComponent', "::CollectParameterValues(%s) : Found '%s'", $parameter_name, $also);
370  $values[$also] = 1;
371  }
372  }
373  }
374 
375  return $values;
376  }
377 
378 
382  function GetProperty( $type ) {
383  $this->explode();
384  foreach( $this->properties AS $k => $v ) {
385  if ( is_object($v) && $v->Name() == $type ) {
386  return $v;
387  }
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 );
390  }
391  }
393  return null;
394  }
395 
399  function GetPValue( $type ) {
400  $this->explode();
401  $p = $this->GetProperty($type);
402  if ( isset($p) ) return $p->Value();
403  return null;
404  }
405 
406 
411  function GetProperties( $type = null ) {
412  // the properties in base are with name
413  // it was setted in parseFrom(&interator)
414  if(!isset($this->properties)){
415  $this->explode();
416  }
417  $properties = array();
418  $testtypes = (gettype($type) == 'string' ? array( $type => true ) : $type );
419  foreach( $this->properties AS $k => $v ) {
420  $name = $v->Name(); //get Property name (string)
421  $name = preg_replace( '/^.*[.]/', '', $name ); //for grouped properties we remove prefix itemX.
422  if ( $type == null || (isset($testtypes[$name]) && $testtypes[$name])) {
423  $properties[] = $v;
424  }
425  }
426  return $properties;
427  }
428 
438  function GetPropertiesByPath( $path ) {
439  $properties = array();
440  dbg_error_log( 'vComponent', "GetPropertiesByPath: Querying within '%s' for path '%s'", $this->type, $path );
441  if ( !preg_match( '#(/?)(!?)([^/]+)(/?.*)$#', $path, $matches ) ) return $properties;
442 
443  $anchored = ($matches[1] == '/');
444  $inverted = ($matches[2] == '!');
445  $ourtest = $matches[3];
446  $therest = $matches[4];
447  dbg_error_log( 'vComponent', "GetPropertiesByPath: Matches: %s -- %s -- %s -- %s\n", $matches[1], $matches[2], $matches[3], $matches[4] );
448  if ( $ourtest == '*' || (($ourtest == $this->type) !== $inverted) && $therest != '' ) {
449  if ( preg_match( '#^/(!?)([^/]+)$#', $therest, $matches ) ) {
450  $normmatch = ($matches[1] =='');
451  $proptest = $matches[2];
452 
453  $thisproperties = $this->GetProperties();
454  if(isset($thisproperties) && count($thisproperties) > 0){
455  foreach( $thisproperties AS $k => $v ) {
456  if ( $proptest == '*' || (($v->Name() == $proptest) === $normmatch ) ) {
457  $properties[] = $v;
458  }
459  }
460  }
461 
462  }
463  else {
467  foreach( $this->GetComponents() AS $k => $v ) {
468  $properties = array_merge( $properties, $v->GetPropertiesByPath($therest) );
469  }
470  }
471  }
472 
473  if ( ! $anchored ) {
477  foreach( $this->GetComponents() AS $k => $v ) {
478  $properties = array_merge( $properties, $v->GetPropertiesByPath($path) );
479  }
480  }
481  dbg_error_log('vComponent', "GetPropertiesByPath: Found %d within '%s' for path '%s'\n", count($properties), $this->type, $path );
482  return $properties;
483  }
484 
490  function ClearProperties( $type = null ) {
491  $this->explode();
492  if($this->isValid()){
493  $this->invalidate();
494  }
495 
496  if ( $type != null ) {
497  $testtypes = (gettype($type) == 'string' ? array( $type => true ) : $type );
498  // First remove all the existing ones of that type
499  foreach( $this->properties AS $k => $v ) {
500  if ( isset($testtypes[$v->Name()]) && $testtypes[$v->Name()] ) {
501  unset($this->properties[$k]);
502 
503  }
504  }
505  $this->properties = array_values($this->properties);
506  }
507  else {
508 
509  $this->properties = array();
510  }
511  }
512 
516  function SetProperties( $new_properties, $type = null ) {
517  $this->explode();
518  $this->ClearProperties($type);
519  foreach( $new_properties AS $k => $v ) {
520  $this->properties[] = $v;
521  }
522  }
523 
531  function AddProperty( $new_property, $value = null, $parameters = null ) {
532  $this->explode();
533  if ( isset($value) && gettype($new_property) == 'string' ) {
534  $new_prop = new vProperty('', $this->master);
535  $new_prop->Name($new_property);
536  $new_prop->Value($value);
537  if ( $parameters != null ) {
538  $new_prop->Parameters($parameters);
539  }
540 // dbg_error_log('vComponent'," Adding new property '%s'", $new_prop->Render() );
541  $this->properties[] = $new_prop;
542  }
543  else if ( $new_property instanceof vProperty ) {
544  $this->properties[] = $new_property;
545  $new_property->setMaster($this->master);
546  }
547 
548  if($this->isValid()){
549  $this->invalidate();
550  }
551  }
552 
562  function GetComponents( $type = null, $normal_match = true ) {
563  $this->explode();
564  $components = isset($this->components) ? $this->components : array();
565 
566  if ( $type != null ) {
567  //$components = $this->components;
568  $testtypes = (gettype($type) == 'string' ? array( $type => true ) : $type );
569  foreach( $components AS $k => $v ) {
570 // printf( "Type: %s, %s, %s\n", $v->GetType(),
571 // ($normal_match && isset($testtypes[$v->GetType()]) && $testtypes[$v->GetType()] ? 'true':'false'),
572 // ( !$normal_match && (!isset($testtypes[$v->GetType()]) || !$testtypes[$v->GetType()]) ? 'true':'false')
573 // );
574  if ( !($normal_match && isset($testtypes[$v->GetType()]) && $testtypes[$v->GetType()] )
575  && !( !$normal_match && (!isset($testtypes[$v->GetType()]) || !$testtypes[$v->GetType()])) ) {
576  unset($components[$k]);
577  }
578  }
579  $components = array_values($components);
580  }
581 // print_r($components);
582  return $components;
583  }
584 
585 
590  function ClearComponents( $type = null ) {
591  if($this->isValid()){
592  $this->explode();
593  }
594 
595 
596  if ( $type != null && !empty($this->components)) {
597  $testtypes = (gettype($type) == 'string' ? array( $type => true ) : $type );
598  // First remove all the existing ones of that type
599  foreach( $this->components AS $k => $v ) {
600  $this->components[$k]->ClearComponents($testtypes);
601  if ( isset($testtypes[$v->GetType()]) && $testtypes[$v->GetType()] ) {
602  unset($this->components[$k]);
603  if ( $this->isValid()) {
604  $this->invalidate();
605  }
606  }
607 
608  }
609  }
610  else {
611  $this->components = array();
612  if ( $this->isValid()) {
613  $this->invalidate();
614  }
615  }
616 
617  return $this->isValid();
618  }
619 
626  function SetComponents( $new_component, $type = null ) {
627  $this->explode();
628  if ( $this->isValid()) {
629  $this->invalidate();
630  }
631  if ( empty($type) ) {
632  $this->components = $new_component;
633  return;
634  }
635 
636  $this->ClearComponents($type);
637  foreach( $new_component AS $k => $v ) {
638  $this->components[] = $v;
639  }
640  }
641 
647  public function AddComponent( $new_component ) {
648  $this->explode();
649  if ( is_array($new_component) && count($new_component) == 0 ) return;
650 
651  if ( $this->isValid()) {
652  $this->invalidate();
653  }
654 
655  try {
656  if ( is_array($new_component) ) {
657  foreach( $new_component AS $k => $v ) {
658  $this->components[] = $v;
659  if ( !method_exists($v,'setMaster') ) fatal('Component to be added must be a vComponent');
660  $v->setMaster($this->master);
661  }
662  }
663  else {
664  if ( !method_exists($new_component,'setMaster') ) fatal('Component to be added must be a vComponent');
665  $new_component->setMaster($this->master);
666  $this->components[] = $new_component;
667  }
668  }
669  catch( Exception $e ) {
670  fatal();
671  }
672  }
673 
674 
680  function MaskComponents( $keep, $recursive = true ) {
681  $this->explode();
682  if(!isset($this->components)){
683  return ;
684  }
685 
686  foreach( $this->components AS $k => $v ) {
687  if ( !isset($keep[$v->GetType()]) ) {
688  unset($this->components[$k]);
689  if ( $this->isValid()) {
690  $this->invalidate();
691  }
692  }
693  else if ( $recursive ) {
694  $v->MaskComponents($keep);
695  }
696  }
697  }
698 
704  function MaskProperties( $keep, $component_list=null ) {
705  $this->explode();
706  if ( !isset($component_list) || isset($component_list[$this->type]) ) {
707  foreach( $this->properties AS $k => $v ) {
708  if ( !isset($keep[$v->Name()]) || !$keep[$v->Name()] ) {
709  unset($this->properties[$k]);
710  if ( $this->isValid()) {
711  $this->invalidate();
712  }
713  }
714  }
715  }
716  if(isset($this->components)){
717  foreach( $this->components AS $k => $v ) {
718  $v->MaskProperties($keep, $component_list);
719  }
720  }
721 
722  }
723 
732  function WrapComponent( $content ) {
733  $strs = preg_split( "/\r?\n/", $content );
734  $wrapped = "";
735  foreach ($strs as $str) {
736 // print "Before: >>$str<<, len(".strlen($str).")\n";
737  $wrapped_bit = (strlen($str) < 76 ? $str : preg_replace( '/(.{72})/u', '$1'."\r\n ", $str )) .self::VEOL;
738 // print "After: >>$wrapped_bit<<\n";
739  $wrapped .= $wrapped_bit;
740  }
741  return $wrapped;
742  }
743 
749  function UnwrapComponent( &$content ) {
750  return preg_replace('/\r?\n[ \t]/', '', $content );
751  }
752 
753 
760  protected function RenderWithoutWrap($restricted_properties = null, $force_rendering = false){
761  $unrolledComponents = isset($this->components);
762  $rendered = vComponent::KEYBEGIN . $this->type . self::VEOL;
763 
764 
765  if($this->isValid()){
766  $rendered .= $this->RenderWithoutWrapFromIterator($unrolledComponents);
767  } else {
768  $rendered .= $this->RenderWithoutWrapFromObjects();
769  }
770 
771  if($unrolledComponents){
772  //$count = 0;
773  foreach($this->components as $component){
774  //$component->explode();
775  //$count++;
776  $component_render = $component->RenderWithoutWrap( null, $force_rendering );
777  if(strlen($component_render) > 0){
778  $rendered .= $component_render . self::VEOL;
779  }
780 
781  //$component->close();
782 
783  }
784  }
785 
786  return $rendered . vComponent::KEYEND . $this->type;
787  }
788 
793  protected function RenderWithoutWrapFromObjects(){
794  $rendered = '';
795  if(isset($this->properties)){
796  foreach( $this->properties AS $k => $v ) {
797  if ( method_exists($v, 'Render') ) {
798  $forebug = $v->Render() . self::VEOL;
799  $rendered .= $forebug;
800  }
801  }
802  }
803 
804  return $rendered;
805  }
806 
812  protected function RenderWithoutWrapFromIterator($unrolledComponents){
813  $this->rewind();
814  $rendered = '';
815  $lentype = 0;
816 
817  if(isset($this->type)){
818  $lentype = strlen($this->type);
819  }
820 
821  $iterator = $this->iterator;
822  $inInnerObject = 0;
823  do {
824  $line = $iterator->current() . self::VEOL;
825  $seek = $iterator->key();
826 
827  $posStart = strpos($line, vComponent::KEYBEGIN);
828  if($posStart !== false && $posStart == 0){
829  $type = substr($line, vComponent::KEYBEGINLENGTH);
830  if(!isset($this->type)){
831  //$this->seekBegin = $seek;
832  $this->type = $type;
833  $lentype = strlen($this->type);
834  } else if(strncmp($type, $this->type, $lentype) != 0){
835  // dont render line which is owned
836  // by inner commponent -> inner component *BEGIN*
837  if($unrolledComponents){
838  $inInnerObject++;
839  } else {
840  $rendered .= $line ;
841  }
842  }
843  } else {
844 
845  $posEnd = strpos($line, vComponent::KEYEND);
846  if($posEnd !== false && $posEnd == 0){
847  $thisEnd = substr($line, vComponent::KEYENDLENGTH);
848  if(strncmp($thisEnd, $this->type, $lentype) == 0){
849  // Current object end
850  $this->seekEnd = $seek;
851  //$iterator->next();
852  break;
853  }else if($unrolledComponents){
854  // dont render line which is owned
855  // by inner commponent -> inner component *END*
856  $inInnerObject--;
857  } else {
858  $rendered .= $line;
859  }
860 
861  } else if($inInnerObject === 0 || !$unrolledComponents){
862  $rendered .= $line;
863  }
864  }
865  $iterator->next();
866  } while($iterator->valid() && ( !isset($this->seekEnd) || $this->seekEnd > $seek));
867 
868 
869  return $rendered;
870 
871  }
872 
873 
880  function Render($restricted_properties = null, $force_rendering = false){
881  return $this->WrapComponent($this->RenderWithoutWrap($restricted_properties, $force_rendering));
882  //return $this->InternalRender($restricted_properties, $force_rendering);
883  }
884 
885  function isValid(){
886  if($this->valid){
887  if(isset($this->components)){
888  foreach($this->components as $comp){
889  if(!$comp->isValid()){
890  return false;
891  }
892  }
893  }
894 
895  return true;
896  }
897  return false;
898  }
899 
909  function TestFilter( $filters ) {
910  foreach( $filters AS $k => $v ) {
911  $tag = $v->GetNSTag();
912 // dbg_error_log( 'vCalendar', ":TestFilter: '%s' ", $tag );
913  switch( $tag ) {
914  case 'urn:ietf:params:xml:ns:caldav:is-defined':
915  case 'urn:ietf:params:xml:ns:carddav:is-defined':
916  if ( count($this->properties) == 0 && count($this->components) == 0 ) return false;
917  break;
918 
919  case 'urn:ietf:params:xml:ns:caldav:is-not-defined':
920  case 'urn:ietf:params:xml:ns:carddav:is-not-defined':
921  if ( count($this->properties) > 0 || count($this->components) > 0 ) return false;
922  break;
923 
924  case 'urn:ietf:params:xml:ns:caldav:comp-filter':
925  case 'urn:ietf:params:xml:ns:carddav:comp-filter':
926  $subcomponents = $this->GetComponents($v->GetAttribute('name'));
927  $subfilter = $v->GetContent();
928 // dbg_error_log( 'vCalendar', ":TestFilter: Found '%d' (of %d) subs of type '%s'",
929 // count($subcomponents), count($this->components), $v->GetAttribute('name') );
930  $subtag = $subfilter[0]->GetNSTag();
931  if ( $subtag == 'urn:ietf:params:xml:ns:caldav:is-not-defined'
932  || $subtag == 'urn:ietf:params:xml:ns:carddav:is-not-defined' ) {
933  if ( count($properties) > 0 ) {
934 // dbg_error_log( 'vComponent', ":TestFilter: Wanted none => false" );
935  return false;
936  }
937  }
938  else if ( count($subcomponents) == 0 ) {
939  if ( $subtag == 'urn:ietf:params:xml:ns:caldav:is-defined'
940  || $subtag == 'urn:ietf:params:xml:ns:carddav:is-defined' ) {
941 // dbg_error_log( 'vComponent', ":TestFilter: Wanted some => false" );
942  return false;
943  }
944  else {
945 // dbg_error_log( 'vCalendar', ":TestFilter: Wanted something from missing sub-components => false" );
946  $negate = $subfilter[0]->GetAttribute("negate-condition");
947  if ( empty($negate) || strtolower($negate) != 'yes' ) return false;
948  }
949  }
950  else {
951  foreach( $subcomponents AS $kk => $subcomponent ) {
952  if ( ! $subcomponent->TestFilter($subfilter) ) return false;
953  }
954  }
955  break;
956 
957  case 'urn:ietf:params:xml:ns:carddav:prop-filter':
958  case 'urn:ietf:params:xml:ns:caldav:prop-filter':
959  $subfilter = $v->GetContent();
960  $properties = $this->GetProperties($v->GetAttribute("name"));
961  dbg_error_log( 'vCalendar', ":TestFilter: Found '%d' props of type '%s'", count($properties), $v->GetAttribute('name') );
962  if ( empty($subfilter) ) {
963  // empty means: test if a property of the type specified by the "name" attribute exists (rfc6352, 10.5.1)
964  $subtag = str_replace('prop-filter', 'is-defined', $tag);
965  } else {
966  $subtag = $subfilter[0]->GetNSTag();
967  }
968  if ( $subtag == 'urn:ietf:params:xml:ns:caldav:is-not-defined'
969  || $subtag == 'urn:ietf:params:xml:ns:carddav:is-not-defined' ) {
970  if ( count($properties) > 0 ) {
971 // dbg_error_log( 'vCalendar', ":TestFilter: Wanted none => false" );
972  return false;
973  }
974  }
975  else if ( count($properties) == 0 ) {
976  if ( $subtag == 'urn:ietf:params:xml:ns:caldav:is-defined'
977  || $subtag == 'urn:ietf:params:xml:ns:carddav:is-defined' ) {
978 // dbg_error_log( 'vCalendar', ":TestFilter: Wanted some => false" );
979  return false;
980  }
981  else {
982 // dbg_error_log( 'vCalendar', ":TestFilter: Wanted '%s' from missing sub-properties => false", $subtag );
983  $negate = $subfilter[0]->GetAttribute("negate-condition");
984  if ( empty($negate) || strtolower($negate) != 'yes' ) return false;
985  }
986  }
987  else {
988  foreach( $properties AS $kk => $property ) {
989  if ( !empty($subfilter) && !$property->TestFilter($subfilter) ) return false;
990  }
991  }
992  break;
993  }
994  }
995  return true;
996  }
997 
998  }
999 
1000 
SetComponents( $new_component, $type=null)
Definition: vComponent.php:626
SetType( $type)
Definition: vComponent.php:343
getComponentAt($position)
Definition: vComponent.php:296
AddComponent( $new_component)
Definition: vComponent.php:647
GetProperty( $type)
Definition: vComponent.php:382
CollectParameterValues( $parameter_name)
Definition: vComponent.php:356
UnwrapComponent(&$content)
Definition: vComponent.php:749
Render($restricted_properties=null, $force_rendering=false)
Definition: vComponent.php:880
RenderWithoutWrap($restricted_properties=null, $force_rendering=false)
Definition: vComponent.php:760
GetPValue( $type)
Definition: vComponent.php:399
RenderWithoutWrapFromIterator($unrolledComponents)
Definition: vComponent.php:812
MaskProperties( $keep, $component_list=null)
Definition: vComponent.php:704
ClearComponents( $type=null)
Definition: vComponent.php:590
SetProperties( $new_properties, $type=null)
Definition: vComponent.php:516
GetProperties( $type=null)
Definition: vComponent.php:411
TestFilter( $filters)
Definition: vComponent.php:909
GetComponents( $type=null, $normal_match=true)
Definition: vComponent.php:562
RenderWithoutWrapFromObjects()
Definition: vComponent.php:793
MaskComponents( $keep, $recursive=true)
Definition: vComponent.php:680
GetPropertiesByPath( $path)
Definition: vComponent.php:438
WrapComponent( $content)
Definition: vComponent.php:732
ClearProperties( $type=null)
Definition: vComponent.php:490
AddProperty( $new_property, $value=null, $parameters=null)
Definition: vComponent.php:531