wCMF  3.6
 All Classes Namespaces Files Functions Variables Groups Pages
class.Node.php
Go to the documentation of this file.
1 <?php
2 /**
3  * wCMF - wemove Content Management Framework
4  * Copyright (C) 2005-2014 wemove digital solutions GmbH
5  *
6  * Licensed under the terms of any of the following licenses
7  * at your choice:
8  *
9  * - GNU Lesser General Public License (LGPL)
10  * http://www.gnu.org/licenses/lgpl.html
11  * - Eclipse Public License (EPL)
12  * http://www.eclipse.org/org/documents/epl-v10.php
13  *
14  * See the license.txt file distributed with this work for
15  * additional information.
16  *
17  * $Id: class.Node.php 1462 2014-02-04 23:52:27Z iherwig $
18  */
19 require_once(BASE."wcmf/lib/core/class.WCMFException.php");
20 require_once(BASE."wcmf/lib/util/class.Log.php");
21 require_once(BASE."wcmf/lib/util/class.StringUtil.php");
22 require_once(BASE."wcmf/lib/persistence/class.PersistentObject.php");
23 require_once(BASE."wcmf/lib/persistence/class.PersistenceFacade.php");
24 require_once(BASE."wcmf/lib/model/class.NodeUtil.php");
25 require_once(BASE."wcmf/lib/util/class.ArrayUtil.php");
26 
27 /**
28  * Some constants describing the build process
29  */
30 define("ADDCHILD_FRONT", -1); // add child at front of children list
31 define("ADDCHILD_BACK", -2); // add child at back of children list
32 /**
33  * Some constants describing the sort process
34  */
35 define("SORTTYPE_ASC", -1); // sort children ascending
36 define("SORTTYPE_DESC", -2); // sort children descending
37 define("OID", -3); // sort by oid
38 define("TYPE", -4); // sort by type
39 
40 /**
41  * Compare function for sorting Nodes by a given criteria.
42  * @param a, b The Nodes to compare.
43  * @return -1, 0 or 1 whether a is less, equal or greater than b in respect of the criteria
44  */
45 $g_sortCriteria = array(); // global sort criteria (is used by Node class and nodeCmpFunction)
46 function nodeCmpFunction ($a, $b)
47 {
48  global $g_sortCriteria;
49  // we compare for each criteria and sum the results for $a, $b
50  // afterwards we compare the sums and return -1,0,1 appropriate
51  $sumA = 0;
52  $sumB = 0;
53  $maxWeight = sizeOf($g_sortCriteria);
54  $i = 0;
55  foreach ($g_sortCriteria as $criteria => $sortType)
56  {
57  $weightedValue = ($maxWeight-$i)*($maxWeight-$i);
58  $AGreaterB = 0;
59  // sort by id
60  if ($criteria == OID)
61  {
62  if ($a->getOID() != $b->getOID())
63  ($a->getOID() > $b->getOID()) ? $AGreaterB = 1 : $AGreaterB = -1;
64  }
65  // sort by name
66  else if ($criteria == TYPE)
67  {
68  if ($a->getType() != $b->getType())
69  ($a->getType() > $b->getType()) ? $AGreaterB = 1 : $AGreaterB = -1;
70  }
71  // sort by value
72  else if($a->getValue($criteria) != null || $b->getValue($criteria) != null)
73  {
74  $aValue = strToLower($a->getValue($criteria));
75  $bValue = strToLower($b->getValue($criteria));
76  if ($aValue != $bValue)
77  ($aValue > $bValue) ? $AGreaterB = 1 : $AGreaterB = -1;
78  }
79  // sort by property
80  else if($a->getProperty($criteria) != null || $b->getProperty($criteria) != null)
81  {
82  $aProperty = strToLower($a->getProperty($criteria));
83  $bProperty = strToLower($b->getProperty($criteria));
84  if ($aProperty != $bProperty)
85  ($aProperty > $bProperty) ? $AGreaterB = 1 : $AGreaterB = -1;
86  }
87  // calculate result of current criteria depending on current sorttype
88  if ($sortType == SORTTYPE_ASC)
89  {
90  if ($AGreaterB == 1) $sumA += $weightedValue;
91  else if ($AGreaterB == -1) $sumB += $weightedValue;
92  }
93  else if ($sortType == SORTTYPE_DESC)
94  {
95  if ($AGreaterB == 1) $sumB += $weightedValue;
96  else if ($AGreaterB == -1) $sumA += $weightedValue;
97  }
98  else
99  WCMFException::throwEx("Unknown SORTTYPE.", __FILE__, __LINE__);
100  $i++;
101  }
102  if ($sumA == $sumB) return 0;
103  return ($sumA > $sumB) ? 1 : -1;
104 }
105 
106 /**
107  * @class Node
108  * @ingroup Model
109  * @brief Node is the basic component for building trees (although a Node can have one than more parents).
110  * The Node class implements the 'Composite Pattern', so no special tree class is required, all interaction
111  * is performed using the Node interface.
112  * Subclasses for specialized Nodes must implement this interface so that clients don't have to know
113  * about special Node classes.
114  * Use the methods addChild(), deleteChild() to build/modify trees.
115  *
116  * @author ingo herwig <ingo@wemove.com>
117  */
118 class Node extends PersistentObject
119 {
120  var $_children = array(); //Node[]
121  var $_parents = array(); //Node
122  var $_depth = -1; //int
123  var $_path = ''; //string
124 
125  /**
126  * Constructor.
127  * @param type The Nodes type.
128  * @param oid The Nodes oid (, optional will be calculated if not given or not valid).
129  */
130  function Node ($type, $oid=null)
131  {
132  $this->PersistentObject($type, $oid);
133  }
134  /**
135  * Get the number of children of the Node.
136  * @param memOnly True/False wether to only get the number of loaded children or all children [default: true].
137  * @param type The type of children to check (maybe null to check all children) [default: null].
138  * @return The number of children.
139  */
140  function getNumChildren ($memOnly=true, $type=null)
141  {
142  $count = 0;
143  if ($memOnly)
144  {
145  // check loaded children
146  for ($i=0; $i<sizeof($this->_children); $i++)
147  if ($type == null || $this->_children[$i]->getType() == $type)
148  $count++;
149  }
150  else
151  {
152  // check child oids
153  $childoids = $this->getProperty('childoids');
154  for ($i=0; $i<sizeof($childoids); $i++)
155  if ($type == null || PersistenceFacade::getOIDParameter($childoids[$i], 'type') == $type)
156  $count++;
157  }
158  return $count;
159  }
160  /**
161  * Add a Node to the Nodes childrenlist.
162  * @param child The Node to add.
163  * @param addtype One of the ADDCHILD constants or any number >= 0
164  * (if the number is greater than the number of children the effect is the same as ADDCHILD_BACK).
165  */
166  function addChild (&$child, $addtype=ADDCHILD_BACK)
167  {
168  if (!is_a($child, 'node') && !is_a($child, 'Node'))
169  WCMFException::throwEx("addChild() assumes a Node as parameter. Found: ".get_class($child),__FILE__,__LINE__);
170  if ($addtype == ADDCHILD_BACK || $addtype == ADDCHILD_FRONT || $addtype > 0)
171  {
172  if ($addtype == ADDCHILD_BACK)
173  $pos = sizeof($this->_children);
174  elseif ($addtype == ADDCHILD_FRONT)
175  $pos = 0;
176  else
177  $pos = $addtype;
178 
179  ArrayUtil::array_insert($this->_children, $pos, $child);
180  $childOID = $child->getOID();
181  ArrayUtil::array_insert($this->_properties['childoids'], $pos, $childOID);
182  }
183  else
184  WCMFException::throwEx("Unknown ADDTYPE.", __FILE__, __LINE__);
185 
186  // propagate add action to current objects
187  $child->updateParent($this);
188  }
189  /**
190  * Set a given parent. Works recursively.
191  * @attention Internal use only.
192  * @param parent A reference to the Node to set the parent to.
193  * @param recursive Apply function on all subsequent Nodes or not.
194  */
195  function updateParent (&$parent, $recursive=true)
196  {
197  // check if the given parent is already assigned,
198  // and do nothing if yes
199  for ($i=0; $i<sizeof($this->_parents); $i++)
200  {
201  if ($this->_parents[$i]->getOID() == $parent->getOID())
202  return;
203  }
204 
205  // add a new parent
206  $this->setState(STATE_DIRTY);
207  $this->_parents[sizeof($this->_parents)] = &$parent;
208  if ($recursive)
209  {
210  // propagate add action to current objects
211  for($i=0;$i<sizeOf($this->_children);$i++)
212  $this->_children[$i]->updateParent($this, $recursive);
213  }
214  $parentOID = $parent->getOID();
215  ArrayUtil::array_insert($this->_properties['parentoids'], sizeof($this->_properties['parentoids']), $parentOID);
216  }
217  /**
218  * Delete a Node's child.
219  * @param childOID The object id of the child Node to delete.
220  * @param reallyDelete True/false [default: false].
221  * (if reallyDelete==false mark it and it's descendants as deleted).
222  */
223  function deleteChild ($childOID, $reallyDelete=false)
224  {
225  for($i=0;$i<sizeOf($this->_children);$i++)
226  {
227  if ($this->_children[$i]->getOID() == $childOID)
228  {
229  if (!$reallyDelete)
230  {
231  // mark child as deleted
232  $this->_children[$i]->setState(STATE_DELETED);
233  break;
234  }
235  else
236  {
237  // remove child
238  array_splice($this->_children, $i, 1);
239  break;
240  }
241  }
242  ArrayUtil::array_remove($this->_children[$i]->_properties['parentoids'], $this->getOID());
243  }
244  ArrayUtil::array_remove($this->_properties['childoids'], $childOID);
245  }
246  /**
247  * Load the children of a given type and add them. If all children should be
248  * loaded, set the type parameter to null.
249  * @param type The type of children to load (maybe null, to load all children)
250  * @param buildDepth One of the BUILDDEPTH constants or a number describing the number of generations to build
251  * [default: BUILDDEPTH_SINGLE)]
252  * @param forceUpdate True/False wether to reload already loaded children even if they are already loaded [default: false]
253  * @note This method relies on the property childoids, that should be set by the mapper, when loading the node
254  */
255  function loadChildren ($type, $buildDepth=BUILDDEPTH_SINGLE, $forceUpdate=false)
256  {
257  $persistenceFacade = &PersistenceFacade::getInstance();
258 
259  // collect all existing oids first
260  $existingOIDs = array();
261  for($i=0;$i<sizeOf($this->_children);$i++)
262  array_push($existingOIDs, $this->_children[$i]->getOID());
263 
264  // load children if necessary
265  $childoids = $this->getProperty('childoids');
266  for($i=0;$i<sizeOf($childoids);$i++)
267  {
268  $curOID = $childoids[$i];
269  if (PersistenceFacade::isValidOID($curOID))
270  {
271  if ($type != null && PersistenceFacade::getOIDParameter($curOID, 'type') != $type)
272  continue;
273 
274  $exists = in_array($curOID, $existingOIDs);
275  if ($exists && !$forceUpdate)
276  continue;
277 
278  if ($exists)
279  $this->deleteChild($curOID, true);
280 
281  $child = &$persistenceFacade->load($curOID, $buildDepth);
282  // check if the child really exists
283  if ($child != null)
284  $this->addChild($child);
285  }
286  }
287  }
288  /**
289  * Get the first child that matches given conditions.
290  * @param type The type that the child should match [maybe null].
291  * @param values An assoziative array holding key value pairs that the child values should match [maybe null].
292  * @param properties An assoziative array holding key value pairs that the child properties should match [maybe null].
293  * @param useRegExp True/False wether to interpret the given values/properties as regular expressions or not [default:true]
294  * @return An reference to the first child that matched or null.
295  */
296  function &getFirstChild ($type, $values, $properties, $useRegExp=true)
297  {
298  $children = $this->getChildrenEx(null, $type, $values, $properties, $useRegExp);
299  if (sizeof($children) > 0)
300  return $children[0];
301  else
302  return null;
303  }
304  /**
305  * Get the Node's children.
306  * @return An Array holding references to the children.
307  */
308  function getChildren ()
309  {
310  $returnArray = array();
311  for($i=0;$i<sizeOf($this->_children);$i++)
312  $returnArray[$i] = & $this->_children[$i];
313 
314  return $returnArray;
315  }
316  /**
317  * Get the children that match given conditions.
318  * @param oid The object id that the children should match [maybe null].
319  * @param type The type that the children should match [maybe null].
320  * @param values An assoziative array holding key value pairs that the children values should match [maybe null].
321  * @param properties An assoziative array holding key value pairs that the children properties should match [maybe null].
322  * @param useRegExp True/False wether to interpret the given values/properties as regular expressions or not [default:true]
323  * @return An Array holding references to the children that matched.
324  */
325  function getChildrenEx ($oid, $type, $values, $properties, $useRegExp=true)
326  {
327  return Node::filter($this->_children, $oid, $type, $values, $properties, $useRegExp);
328  }
329  /**
330  * Sort children by a given criteria.
331  * @param criteria An assoziative array of criteria - SORTTYPE constant pairs OR a single criteria string.
332  * possible criteria: OID, TYPE or any value/property name
333  * (e.g. array(OID => SORTTYPE_ASC, 'sortkey' => SORTTYPE_DESC) OR 'sortkey')
334  * @note If criteria is only a string we will sort by this criteria with SORTTYPE_ASC
335  * @param recursive True/False whether the descendants of the children schould be sorted too (default: false)
336  * @param changeSortkey True/False whether the sortkey should be changed according to the new order (default: false)
337  * @param sortFunction The name of a global compare function to use. If given criteria will be ignored (default: "")
338  */
339  function sortChildren ($criteria, $recursive=false, $changeSortkey=false, $sortFunction='')
340  {
341  $this->_children = Node::sort($this->_children, $criteria, $recursive, $changeSortkey, $sortFunction);
342  }
343  /**
344  * Sort Node list by a given criteria.
345  * @note static method
346  * @param nodeList A reference to an array of Nodes
347  * @param criteria An assoziative array of criteria - SORTTYPE constant pairs OR a single criteria string.
348  * possible criteria: OID, TYPE or any value/property name
349  * (e.g. array(OID => SORTTYPE_ASC, 'sortkey' => SORTTYPE_DESC) OR 'sortkey')
350  * @note If criteria is only a string we will sort by this criteria with SORTTYPE_ASC
351  * @param recursive True/False whether the descendants of the children schould be sorted too (default: false)
352  * @param changeSortkey True/False whether the sortkey should be changed according to the new order (default: false)
353  * @param sortFunction The name of a global compare function to use. If given criteria will be ignored (default: "")
354  * @return The sorted array of Nodes
355  */
356  function sort (&$nodeList, $criteria, $recursive=false, $changeSortkey=false, $sortFunction='')
357  {
358  if ($sortFunction == '')
359  {
360  // sort with internal sort function
361  global $g_sortCriteria;
362  if (!is_array($criteria))
363  $g_sortCriteria = array($criteria => SORTTYPE_ASC);
364  else
365  $g_sortCriteria = $criteria;
366  usort ($nodeList, 'nodeCmpFunction');
367  }
368  else
369  usort ($nodeList, $sortFunction);
370 
371  // change sortkey
372  if ($changeSortkey)
373  {
374  $sortkey = 0;
375  for($i=0;$i<sizeOf($nodeList);$i++)
376  {
377  $nodeList[$i]->setValue('sortkey', $sortkey, DATATYPE_IGNORE);
378  $sortkey++;
379  }
380  }
381 
382  // recurse
383  if ($recursive)
384  for ($i=0; $i<sizeof($nodeList); $i++)
385  $nodeList[$i]->sortChildren($criteria, $recursive, $changeSortkey, $sortFunction);
386 
387  return $nodeList;
388  }
389  /**
390  * Get Nodes that match given conditions from a list.
391  * @param nodeList An reference to an array of nodes to filter.
392  * @param oid The object id that the Nodes should match [maybe null].
393  * @param type The type that the Nodes should match [maybe null].
394  * @param values An assoziative array holding key value pairs that the Node values should match
395  * [values are interpreted as regular expression, parameter maybe null].
396  * @param properties An assoziative array holding key value pairs that the Node properties should match
397  * [values are interpreted as regular expression, parameter maybe null].
398  * @param useRegExp True/False wether to interpret the given values/properties as regular expressions or not [default:true]
399  * @return An Array holding references to the Nodes that matched.
400  */
401  function filter (&$nodeList, $oid, $type, $values, $properties, $useRegExp=true)
402  {
403  $returnArray = array();
404  for($i=0;$i<sizeOf($nodeList);$i++)
405  {
406  $curNode = &$nodeList[$i];
407  if (is_a($curNode, 'node') || is_a($curNode, 'Node'))
408  {
409  $match = true;
410  // check oid
411  if ($oid != null && $curNode->getOID() != $oid)
412  $match = false;
413  // check type
414  if ($type != null && $curNode->getType() != $type)
415  $match = false;
416  // check values
417  if ($values != null && is_array($values))
418  {
419  foreach($values as $key => $value)
420  {
421  $nodeValue = $curNode->getValue($key);
422  if ($useRegExp && !preg_match("/".$value."/m", $nodeValue) || !$useRegExp && $value != $nodeValue)
423  {
424  $match = false;
425  break;
426  }
427  }
428  }
429  // check properties
430  if ($properties != null && is_array($properties))
431  {
432  foreach($properties as $key => $value)
433  {
434  $nodeProperty = $curNode->getProperty($key);
435  if ($useRegExp && !preg_match("/".$value."/m", $nodeProperty) || !$useRegExp && $value != $nodeProperty)
436  {
437  $match = false;
438  break;
439  }
440  }
441  }
442  if ($match)
443  $returnArray[sizeof($returnArray)] = &$curNode;
444  }
445  else
446  Log::warn(StringUtil::getDump($curNode)." found, where a Node was expected.\n".WCMFException::getStackTrace(),
447  __FILE__, __LINE__);
448  }
449  return $returnArray;
450  }
451  /**
452  * Get the next sibling of the Node.
453  * @return The next sibling of the node or NULL if it does not exists.
454  */
455  function getNextSibling()
456  {
457  $parent = &$this->getParent();
458  if ($parent != null)
459  {
460  $pChildren = $parent->getChildren();
461  $nextSibling = null;
462  for ($i=0;$i<sizeOf($pChildren);$i++)
463  {
464  if ($pChildren[$i]->getOID()==$this->_oid && $i<(sizeOf($pChildren)-1))
465  {
466  $nextSibling = $pChildren[++$i];
467  break;
468  }
469  }
470  if ($nextSibling != null)
471  return $nextSibling;
472  }
473  return null;
474  }
475  /**
476  * Get the previous sibling of the Node.
477  * @return The previous sibling of the node or NULL if it does not exists.
478  */
480  {
481  $parent = &$this->getParent();
482  if ($parent != null)
483  {
484  $pChildren = $parent->getChildren();
485  $prevSibling = null;
486  for ($i=0;$i<sizeOf($pChildren);$i++)
487  {
488  if ($pChildren[$i]->getOID()==$this->_oid && $i>0)
489  {
490  $prevSibling = $pChildren[--$i];
491  break;
492  }
493  }
494  if ($prevSibling != null)
495  return $prevSibling;
496  }
497  return null;
498  }
499  /**
500  * Load the parents of a given type and add them. If all parents should be
501  * loaded, set the type parameter to null.
502  * @param type The type of parents to load (maybe null, to load all children)
503  * @param forceUpdate True/False wether to reload already loaded parents even if they are already loaded [default: false]
504  * @note This method relies on the property childoids, that should be set by the mapper, when loading the node
505  */
506  function loadParents ($type, $forceUpdate=false)
507  {
508  $persistenceFacade = &PersistenceFacade::getInstance();
509 
510  // collect all existing oids first
511  $existingOIDs = array();
512  for($i=0;$i<sizeOf($this->_parents);$i++)
513  array_push($existingOIDs, $this->_parents[$i]->getOID());
514 
515  // load parents if necessary
516  $parentoids = $this->getProperty('parentoids');
517  for($i=0;$i<sizeOf($parentoids);$i++)
518  {
519  $curOID = $parentoids[$i];
520  if (PersistenceFacade::isValidOID($curOID))
521  {
522  if ($type != null && PersistenceFacade::getOIDParameter($curOID, 'type') != $type)
523  continue;
524 
525  $exists = in_array($curOID, $existingOIDs);
526  if ($exists && !$forceUpdate)
527  continue;
528 
529  if ($exists)
530  {
531  $parents = $this->getParentsEx($curOID, null, null, null);
532  if (sizeof($parents) > 0 && $parents[0] != null)
533  $parents[0]->deleteChild($this, true);
534  }
535 
536  $parent = &$persistenceFacade->load($curOID, BUILDDEPTH_SINGLE);
537  // check if the parent really exists
538  if ($parent != null)
539  $parent->addChild($this);
540  }
541  }
542  }
543  /**
544  * Get the number of parents of the Node.
545  * @param memOnly True/False wether to only get the number of loaded parents or all parents [default: true].
546  * @param type The type of parents to check (maybe null to check all parents) [default: null].
547  * @return The number of parents.
548  */
549  function getNumParents ($memOnly=true, $type=null)
550  {
551  $count = 0;
552  if ($memOnly)
553  {
554  // check loaded parents
555  for ($i=0; $i<sizeof($this->_parents); $i++)
556  if ($type == null || $this->_parents[$i]->getType() == $type)
557  $count++;
558  }
559  else
560  {
561  // check parent oids
562  $parentoids = $this->getProperty('parentoids');
563  for ($i=0; $i<sizeof($parentoids); $i++)
564  if ($type == null || PersistenceFacade::getOIDParameter($parentoids[$i], 'type') == $type)
565  $count++;
566  }
567  return $count;
568  }
569  /**
570  * Get the Nodes parent. This method exists for compatibility with previous
571  * versions. It returns the first parent.
572  * @return A reference to the Nodes parent.
573  */
574  function &getParent ()
575  {
576  if (sizeof($this->_parents) > 0)
577  return $this->_parents[0];
578  else
579  return null;
580  }
581  /**
582  * Get the first parent that matches given conditions.
583  * @param type The type that the parent should match [maybe null].
584  * @param values An assoziative array holding key value pairs that the parent values should match [maybe null].
585  * @param properties An assoziative array holding key value pairs that the parent properties should match [maybe null].
586  * @param useRegExp True/False wether to interpret the given values/properties as regular expressions or not [default:true]
587  * @return An reference to the first parent that matched or null.
588  */
589  function &getFirstParent ($type, $values, $properties, $useRegExp=true)
590  {
591  $parents = $this->getParentsEx(null, $type, $values, $properties, $useRegExp);
592  if (sizeof($parents) > 0)
593  return $parents[0];
594  else
595  return null;
596  }
597  /**
598  * Get the Nodes parents.
599  * @return An array of references to the Nodes parents.
600  */
601  function &getParents ()
602  {
603  $returnArray = array();
604  for($i=0;$i<sizeOf($this->_parents);$i++)
605  $returnArray[$i] = & $this->_parents[$i];
606 
607  return $returnArray;
608  }
609  /**
610  * Get the parents that match given conditions.
611  * @param oid The object id that the parent should match [maybe null].
612  * @param type The type that the parents should match [maybe null].
613  * @param values An assoziative array holding key value pairs that the parent values should match [maybe null].
614  * @param properties An assoziative array holding key value pairs that the parent properties should match [maybe null].
615  * @param useRegExp True/False wether to interpret the given values/properties as regular expressions or not [default:true]
616  * @return An Array holding references to the parents that matched.
617  */
618  function getParentsEx ($oid, $type, $values, $properties, $useRegExp=true)
619  {
620  return Node::filter($this->_parents, $oid, $type, $values, $properties, $useRegExp);
621  }
622  /**
623  * Get the Nodes depth.
624  * @return The number of parents of the Node.
625  */
626  function getDepth ()
627  {
628  $this->_depth = 0;
629  $parent = & $this->getParent();
630  while ($parent != null && is_a($parent, 'node'))
631  {
632  $this->_depth++;
633  $parent = & $parent->getParent();
634  }
635  return $this->_depth;
636  }
637  /**
638  * Get the Nodes path (to root).
639  * @return The Node path.
640  */
641  function getPath ()
642  {
643  $this->_path = $this->getType();
644  $parent = & $this->getParent();
645  while ($parent != null && is_a($parent, 'node'))
646  {
647  $this->_path = $parent->getType().'/'.$this->_path;
648  $parent = & $parent->getParent();
649  }
650  return $this->_path;
651  }
652  /**
653  * Accept a Visitor. For use with the 'Visitor Pattern'.
654  * @param visitor The Visitor.
655  */
656  function acceptVisitor(&$visitor)
657  {
658  $visitor->visit($this);
659  }
660  /**
661  * Set the state of the node.
662  * @param state The state to set.
663  * @param recursive True/False [Default: True]
664  */
665  function setState ($state, $recursive=true)
666  {
667  parent::setState($state);
668  if ($recursive)
669  for($i=0;$i<sizeOf($this->_children);$i++)
670  $this->_children[$i]->setState($state, $recursive);
671  }
672  /**
673  * Remove all object ids from a list of object ids, that don't have a role,
674  * but also exist as an object id with a specified role.
675  * @param oids The array of object ids to filter
676  * @return Array
677  */
679  {
680  // first pass - collect infos:
681  // construct a hashset with the base oids as keys and the list
682  // of oids with roles as values
683  $oidList = array();
684  foreach ($oids as $oid)
685  {
686  $baseOid = PersistenceFacade::getBaseOID($oid, false);
687  if (!isset($oidList[$baseOid])) {
688  $oidList[$baseOid] = array();
689  }
690  if ($oid != $baseOid) {
691  $oidList[$baseOid][] = $oid;
692  }
693  }
694 
695  // second pass - assemble the final list
696  $result = array();
697  foreach ($oidList as $key => $value)
698  {
699  if (sizeof($value) == 0) {
700  // use the base oid, because no oid with role was contained
701  $result[] = $oid;
702  }
703  else {
704  // use the oids with roles
705  $result = array_merge($result, $value);
706  }
707  }
708  return $result;
709  }
710 
711  /**
712  * Output
713  */
714 
715  /**
716  * @see PersistentObject::getDisplayValue()
717  * Delegates to NodeUtil::getDisplayValue
718  */
719  function getDisplayValue($useDisplayType=false)
720  {
721  return NodeUtil::getDisplayValue($this, $useDisplayType);
722  }
723  /**
724  * Delegates to NodeUtil::getDisplayValues
725  */
726  function getDisplayValues($useDisplayType=false)
727  {
728  return NodeUtil::getDisplayValues($this, $useDisplayType);
729  }
730  /**
731  * Get a string representation of the Node.
732  * @param verbose True to get a verbose output [default: false]
733  * @return The string representation of the Node.
734  */
735  function toString ($verbose=false)
736  {
737  $str = 'NODE ';
738  $str .= parent::toString($verbose);
739  $str .= 'depth:'.$this->getDepth().' ';
740  $str .= 'path:'.$this->getPath().' ';
741  if ($this->getNumParents())
742  {
743  $str .= 'PARENTS ';
744  $parents = $this->getParents();
745  for($i=0;$i<sizeOf($parents);$i++)
746  $str .= $parents[$i]->getOID().',';
747  $str = substr($str, 0, strlen($str)-1);
748  $str .= "\n";
749  }
750  if ($this->getNumChildren())
751  {
752  $str .= 'CHILDREN ';
753  $children = $this->getChildren();
754  for($i=0;$i<sizeOf($children);$i++)
755  $str .= $children[$i]->getOID().',';
756  $str = substr($str, 0, strlen($str)-1);
757  $str .= "\n";
758  }
759  return $str;
760  }
761 }
762 ?>
& getFirstParent($type, $values, $properties, $useRegExp=true)
Definition: class.Node.php:589
const STATE_DIRTY
getNumChildren($memOnly=true, $type=null)
Definition: class.Node.php:140
array_remove(&$input, &$val)
const STATE_DELETED
Node is the basic component for building trees (although a Node can have one than more parents)...
Definition: class.Node.php:118
warn($message, $category)
Definition: class.Log.php:59
toString($verbose=false)
Definition: class.Node.php:735
sort(&$nodeList, $criteria, $recursive=false, $changeSortkey=false, $sortFunction='')
Definition: class.Node.php:356
getNumParents($memOnly=true, $type=null)
Definition: class.Node.php:549
getChildren()
Definition: class.Node.php:308
const ADDCHILD_FRONT
Definition: class.Node.php:30
$g_sortCriteria
Definition: class.Node.php:45
& getParents()
Definition: class.Node.php:601
getDisplayValues(&$node, $useDisplayType=false, $language=null, $values=null)
loadChildren($type, $buildDepth=BUILDDEPTH_SINGLE, $forceUpdate=false)
Definition: class.Node.php:255
& getFirstChild($type, $values, $properties, $useRegExp=true)
Definition: class.Node.php:296
addChild(&$child, $addtype=ADDCHILD_BACK)
Definition: class.Node.php:166
getNextSibling()
Definition: class.Node.php:455
removeDuplicateOidsWithoutRole($oids)
Definition: class.Node.php:678
array_insert(&$input, $pos, &$val, $unique=true)
throwEx($message, $file='', $line='')
getParentsEx($oid, $type, $values, $properties, $useRegExp=true)
Definition: class.Node.php:618
filter(&$nodeList, $oid, $type, $values, $properties, $useRegExp=true)
Definition: class.Node.php:401
getDisplayValues($useDisplayType=false)
Definition: class.Node.php:726
loadParents($type, $forceUpdate=false)
Definition: class.Node.php:506
const DATATYPE_IGNORE
const TYPE
Definition: class.Node.php:38
& getParent()
Definition: class.Node.php:574
sortChildren($criteria, $recursive=false, $changeSortkey=false, $sortFunction='')
Definition: class.Node.php:339
getPath()
Definition: class.Node.php:641
$_children
Definition: class.Node.php:120
getDisplayValue($useDisplayType=false)
Definition: class.Node.php:719
const SORTTYPE_ASC
Definition: class.Node.php:35
const SORTTYPE_DESC
Definition: class.Node.php:36
const ADDCHILD_BACK
Definition: class.Node.php:31
getDepth()
Definition: class.Node.php:626
Node($type, $oid=null)
Definition: class.Node.php:130
getBaseOID($oid, $validate=true)
PersistentObject($type, $oid=null)
getOIDParameter($oid, $param, $validate=true)
nodeCmpFunction($a, $b)
Definition: class.Node.php:46
getPreviousSibling()
Definition: class.Node.php:479
getDisplayValue(&$node, $useDisplayType=false, $language=null, $values=null)
setState($state, $recursive=true)
Definition: class.Node.php:665
getChildrenEx($oid, $type, $values, $properties, $useRegExp=true)
Definition: class.Node.php:325
acceptVisitor(&$visitor)
Definition: class.Node.php:656
deleteChild($childOID, $reallyDelete=false)
Definition: class.Node.php:223
const BUILDDEPTH_SINGLE
updateParent(&$parent, $recursive=true)
Definition: class.Node.php:195
PersistentObject is the base class of all persistent objects. It implements the basic persistence met...
const OID
Definition: class.Node.php:37