Array.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license, |
  9. // | that is bundled with this package in the file LICENSE, and is |
  10. // | available at through the world-wide-web at |
  11. // | http://www.php.net/license/2_02.txt. |
  12. // | If you did not receive a copy of the PHP license and are unable to |
  13. // | obtain it through the world-wide-web, please send a note to |
  14. // | license@php.net so we can mail you a copy immediately. |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Wolfram Kriesing <wolfram@kriesing.de> |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Array.php,v 1.9 2003/03/17 16:02:54 cain Exp $
  20. require_once('Tree/Error.php');
  21. /**
  22. * EXPERIMENTAL
  23. *
  24. * @access public
  25. * @author Wolfram Kriesing <wolfram@kriesing.de>
  26. * @version 2002/08/30
  27. * @package Tree
  28. */
  29. class Tree_Memory_Array
  30. {
  31. var $data = array();
  32. /**
  33. * this is the internal id that will be assigned if no id is given
  34. * it simply counts from 1, so we can check if( $id ) i am lazy :-)
  35. */
  36. var $_id = 1;
  37. /**
  38. * set up this object
  39. *
  40. * @version 2002/08/30
  41. * @access public
  42. * @author Wolfram Kriesing <wolfram@kriesing.de>
  43. * @param string $dsn the path on the filesystem
  44. * @param array $options additional options you can set
  45. */
  46. function Tree_Memory_Array( &$array , $options=array() )
  47. {
  48. $this->_array = &$array;
  49. $this->_options = $options; // not in use currently
  50. } // end of function
  51. /**
  52. *
  53. *
  54. * @version 2002/08/30
  55. * @access public
  56. * @author Wolfram Kriesing <wolfram@kriesing.de>
  57. * @return boolean true on success
  58. */
  59. function setup()
  60. {
  61. unset($this->data); // unset the data to be sure to get the real data again, no old data
  62. if (is_array($this->_array)) {
  63. $this->data[0] = null;
  64. $theData = array(&$this->_array);
  65. $this->_setup($theData);
  66. }
  67. /*foreach($this->data as $val){print "\r\n";
  68. foreach ($val as $k=>$v)
  69. print "$k=>$v\r\n";
  70. }*/
  71. return $this->data;
  72. }
  73. /**
  74. * we modify the $this->_array in here, we also add the id
  75. * so methods like 'add' etc can find the elements they are searching for,
  76. * if you dont like your data to be modified dont pass them as reference!
  77. */
  78. function _setup( &$array , $parentId=0 )
  79. {
  80. foreach ($array as $nodeKey=>$aNode) {
  81. $newData = $aNode;
  82. if (!isset($newData['id']) || !$newData['id']) { // if the current element has no id, we generate one
  83. $newData['id'] = $this->_id++; // build a unique numeric id
  84. $array[$nodeKey]['id'] = $newData['id']; // set the id
  85. } else {
  86. $idAsInt = (int)$newData['id'];
  87. if ($idAsInt > $this->_id) {
  88. $this->_id = $idAsInt;
  89. }
  90. }
  91. //print "a node name=".$aNode['name'].'<br>';
  92. $newData['parentId'] = $parentId; // set the parent-id, since we only have a 'children' array
  93. $children = null;
  94. foreach ( $newData as $key=>$val ) { // remove the 'children' array, since this is only info for this class
  95. if ($key=='children') {
  96. unset($newData[$key]);
  97. }
  98. }
  99. $this->data[$newData['id']] = $newData;
  100. if (isset($aNode['children']) && $aNode['children']) {
  101. if (!isset($array[$nodeKey]['children'])) {
  102. $array[$nodeKey]['children'] = array();
  103. }
  104. $this->_setup( $array[$nodeKey]['children'] , $newData['id'] );
  105. }
  106. }
  107. }
  108. /**
  109. * this is mostly used by switchDataSource
  110. * this method put data gotten from getNode() in the $this->_array
  111. *
  112. */
  113. function setData($data)
  114. {
  115. /*
  116. $root = array_shift($data);
  117. unset($root['children']);
  118. $this->_array = array('children'=> array($root));
  119. foreach ($this->_array['children'][0] as $key=>$val)
  120. print "$key=>$val<br>";
  121. print "<br>";
  122. */
  123. $unsetKeys = array('childId','left','right');
  124. foreach ( $data as $aNode ) {
  125. //print $aNode['id'].' : '.$aNode['name'].' parentId='.$aNode['parentId'].' size='.sizeof($this->_array['children'][0]['children']).'<br>';
  126. foreach ($aNode as $key=>$val) {
  127. if (is_array($val) || in_array($key,$unsetKeys)) {
  128. unset($aNode[$key]);
  129. }
  130. }
  131. $this->add($aNode,$aNode['parentId']);
  132. }
  133. //foreach ($this->_array['children'][0]['children'] as $x){print "<br>";
  134. //foreach ($x as $key=>$val)
  135. // print "$key=>$val<br>";}
  136. $this->_array = $this->_array['children'][0];
  137. }
  138. /**
  139. *
  140. *
  141. * @access private
  142. * @version 2002/03/02
  143. * @author Wolfram Kriesing <wolfram@kriesing.de>
  144. * @param
  145. * @return
  146. */
  147. function _throwError( $msg , $line , $mode=null )
  148. {
  149. return new Tree_Error( $msg , $line , __FILE__ , $mode , $this->db->last_query );
  150. }
  151. /**
  152. * prepare multiple results
  153. *
  154. * @see _prepareResult()
  155. * @access private
  156. * @version 2002/03/03
  157. * @author Wolfram Kriesing <wolfram@kriesing.de>
  158. * @param
  159. * @return
  160. */
  161. function _prepareResults( $results )
  162. {
  163. $newResults = array();
  164. foreach( $results as $aResult )
  165. $newResults[] = $this->_prepareResult($aResult);
  166. return $newResults;
  167. }
  168. /**
  169. * map back the index names to get what is expected
  170. *
  171. * @access private
  172. * @version 2002/03/03
  173. * @author Wolfram Kriesing <wolfram@kriesing.de>
  174. * @param
  175. * @return
  176. */
  177. function _prepareResult( $result )
  178. {
  179. $map = $this->getOption('columnNameMaps');
  180. if( $map )
  181. foreach( $map as $key=>$columnName )
  182. {
  183. $result[$key] = $result[$columnName];
  184. unset($result[$columnName]);
  185. }
  186. return $result;
  187. }
  188. /**
  189. * add a new item to the tree
  190. * what is tricky here, we also need to add it to the source array
  191. *
  192. * @param array the data for the new node
  193. * @param int the ID of the parent node
  194. * @param int the ID of the previous node
  195. */
  196. function add( $data , $parentId , $previousId=null )
  197. {
  198. if (!isset($data['id'])) {
  199. $data['id'] = ++$this->_id;
  200. } elseif((int)$data['id'] > $this->_id) {
  201. // update the $this->_id if the data['id'] has a higher number, since
  202. // we dont want to overwrite anything. just in case
  203. $this->_id = (int)$data['id'];
  204. }
  205. $data['parentId'] = $parentId;
  206. $this->data[$data['id']] = $data;
  207. //$path = $this->getPathById($parentId);
  208. if (!isset($this->_array['children'])) { // there might not be a root element yet
  209. $data['parentId'] = 0;
  210. $this->_array['children'][] = $data;
  211. } else {
  212. array_walk($this->_array['children'],array(&$this,'_add'),array($data,$parentId,$previousId));
  213. }
  214. //$this->_array
  215. return $data['id'];
  216. }
  217. /**
  218. * we need to add the node to the source array
  219. * for this we have this private method which loops through
  220. * the source array and adds it in the right place
  221. *
  222. * @param mixed the value of the array, as a reference, so we work right on the source
  223. * @param mixed the key of the node
  224. * @param array an array which contains the following
  225. * new data,
  226. * parent ID under which to add the node,
  227. * the prvious ID
  228. */
  229. function _add( &$val , $key , $data )
  230. {
  231. if ($val['id']==$data[1]) { // is the id of the current elment ($val) == to the parentId ($data[1])
  232. if (isset($data[2]) && $data[2]===0 ) {
  233. // if the previousId is 0 means, add it as the first member
  234. $val['children'] = array_merge(array($data[0]),$val['children']);
  235. } else {
  236. $val['children'][] = $data[0];
  237. }
  238. } else { // if we havent found the new element go on searching
  239. if (isset($val['children'])) {
  240. array_walk($val['children'],array(&$this,'_add'),$data);
  241. }
  242. }
  243. }
  244. /**
  245. * update an entry with the given id and set the data as given in the array $data
  246. *
  247. * @param int the id of the element that shall be updated
  248. * @param array the data, [key]=>[value]
  249. * @return void
  250. */
  251. function update($id,$data)
  252. {
  253. if ($this->_array['id']==$id) {
  254. foreach ($data as $key=>$newVal) {
  255. $this->_array[$key] = $newVal;
  256. }
  257. } else {
  258. array_walk($this->_array['children'],array(&$this,'_update'),array($id,$data));
  259. }
  260. }
  261. /**
  262. * update the element with the given id
  263. *
  264. * @param array a reference to an element inside $this->_array
  265. * has to be a reference, so we can really modify the actual data
  266. * @param int not in use, but array_walk passes this param
  267. * @param array [0] is the id we are searching for
  268. * [1] are the new data we shall set
  269. * @return void
  270. */
  271. function _update( &$val , $key , $data )
  272. {
  273. //print $val['id'].'=='.$data[0].'<br>';
  274. if ($val['id']==$data[0]) { // is the id of the current elment ($val) == to the parentId ($data[1])
  275. foreach ($data[1] as $key=>$newVal) {
  276. //print "set ".$val['name']." $key = $newVal<br>";
  277. $val[$key] = $newVal;
  278. }
  279. } else { // if we havent found the new element go on searching in the children
  280. if (isset($val['children'])) {
  281. array_walk($val['children'],array(&$this,'_update'),$data);
  282. }
  283. }
  284. }
  285. /**
  286. * remove an element from the tree
  287. * this removes all the children too
  288. *
  289. * @param int the id of the element to be removed
  290. */
  291. function remove($id)
  292. {
  293. if ($this->data[$id]) { // we only need to search for element that do exist :-) otherwise we save some processing time
  294. $this->_remove($this->_array,$id);
  295. }
  296. }
  297. /**
  298. * remove the element with the given id
  299. * this will definitely remove all the children too
  300. *
  301. * @param array a reference to an element inside $this->_array
  302. * has to be a reference, so we can really modify the actual data
  303. * @param int the id of the element to be removed
  304. * @return void
  305. */
  306. function _remove( &$val , $id )
  307. {
  308. if (isset($val['children'])) {
  309. foreach ($val['children'] as $key=>$aVal) {
  310. //print $aVal['id'].'=='.$id."\r\n";
  311. if ($aVal['id']==$id) {
  312. //print "remove ".$aVal['name']."\r\n";
  313. if (sizeof($val['children'])<2) {
  314. unset($val['children']);
  315. } else {
  316. unset($val['children'][$key]);
  317. }
  318. } else {
  319. $this->_remove($val['children'][$key],$id);
  320. }
  321. }
  322. }
  323. }
  324. } // end of class
  325. ?>