1 |
joko |
1.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: XML.php,v 1.6 2003/01/04 11:56:28 mj Exp $ |
20 |
|
|
|
21 |
|
|
require_once "XML/Parser.php"; |
22 |
|
|
|
23 |
|
|
/** |
24 |
|
|
* the XML interface for the tree class |
25 |
|
|
* |
26 |
|
|
* @package Tree |
27 |
|
|
* @author |
28 |
|
|
* @version |
29 |
|
|
* @access public |
30 |
|
|
*/ |
31 |
|
|
class Tree_Memory_XML extends XML_Parser |
32 |
|
|
{ |
33 |
|
|
|
34 |
|
|
/** |
35 |
|
|
* @var array $data the first element has to be empty, so we can use the parentId=0 as "no parent" |
36 |
|
|
*/ |
37 |
|
|
var $data = array(0=>NULL); |
38 |
|
|
|
39 |
|
|
/** |
40 |
|
|
* @var integer $level |
41 |
|
|
*/ |
42 |
|
|
var $level = 0; |
43 |
|
|
|
44 |
|
|
/** |
45 |
|
|
* @var array $parentIdOnLevel |
46 |
|
|
*/ |
47 |
|
|
var $parentIdOnLevel = array(); |
48 |
|
|
|
49 |
|
|
/** |
50 |
|
|
* @var boolean $folding set case folding for the XML_Parser to false |
51 |
|
|
*/ |
52 |
|
|
var $folding = false; // turn off case folding |
53 |
|
|
|
54 |
|
|
/** |
55 |
|
|
* @var boolean if true it converts all attributes and tag names etc to lower case |
56 |
|
|
* this is default, since i dont see no way of case insensitive comparison |
57 |
|
|
* in the tree class, since you can access the internal data directly |
58 |
|
|
* or you get them returned ... i know this is not 100% proper OOP but that's how it is right now |
59 |
|
|
*/ |
60 |
|
|
var $_toLower = true; |
61 |
|
|
|
62 |
|
|
/** |
63 |
|
|
* |
64 |
|
|
* |
65 |
|
|
* @version 2002/01/17 |
66 |
|
|
* @access public |
67 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
68 |
|
|
* @return boolean true on success |
69 |
|
|
*/ |
70 |
|
|
function Tree_Memory_XML( $dsn , $options ) |
71 |
|
|
{ |
72 |
|
|
$handle = $dsn; |
73 |
|
|
|
74 |
|
|
$this->XML_Parser(); |
75 |
|
|
|
76 |
|
|
if (@is_resource($handle)) { |
77 |
|
|
$this->setInput($handle); |
78 |
|
|
} elseif ($handle != "") { |
79 |
|
|
$this->setInputFile($handle); |
80 |
|
|
} else { |
81 |
|
|
return $this->raiseError("No filename passed."); |
82 |
|
|
} |
83 |
|
|
} |
84 |
|
|
|
85 |
|
|
/** |
86 |
|
|
* |
87 |
|
|
* |
88 |
|
|
* @version 2002/01/17 |
89 |
|
|
* @access public |
90 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
91 |
|
|
* @return boolean true on success |
92 |
|
|
*/ |
93 |
|
|
function startHandler($parser, $element, $attribs) |
94 |
|
|
{ |
95 |
|
|
$elementBeforeId = sizeof($this->data)-1; |
96 |
|
|
$curId = sizeof($this->data); |
97 |
|
|
|
98 |
|
|
$this->data[$curId]['id'] = $curId; |
99 |
|
|
$this->data[$curId]['name'] = $this->_toLower ? strtolower($element) : $element; |
100 |
|
|
$this->data[$curId]['level'] = $this->level; |
101 |
|
|
$this->data[$curId]['attributes'] = $attribs; |
102 |
|
|
if( $this->_toLower ) |
103 |
|
|
{ |
104 |
|
|
$this->data[$curId]['attributes'] = array(); |
105 |
|
|
foreach( $attribs as $key=>$value ) |
106 |
|
|
$this->data[$curId]['attributes'][strtolower($key)] = $value; |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
if( isset($this->data[$elementBeforeId]['level']) && |
110 |
|
|
$this->level == $this->data[$elementBeforeId]['level'] ) // is that a new child, or just a 'next' of a child? |
111 |
|
|
{ |
112 |
|
|
$this->data[$curId]['parentId'] = $this->data[$elementBeforeId]['parentId']; |
113 |
|
|
} |
114 |
|
|
else // set stuff for the first child !!! |
115 |
|
|
{ |
116 |
|
|
if( $this->level>0 ) // the root has no parent |
117 |
|
|
{ |
118 |
|
|
$parentId = $this->parentIdOnLevel[$this->level-1]; |
119 |
|
|
$this->data[$curId]['parentId'] = $parentId; |
120 |
|
|
} |
121 |
|
|
else |
122 |
|
|
{ |
123 |
|
|
$this->data[$curId]['parentId'] = 0; |
124 |
|
|
} |
125 |
|
|
} |
126 |
|
|
$this->parentIdOnLevel[$this->level] = $curId; |
127 |
|
|
|
128 |
|
|
#print "$curId $element ".$this->data[$curId]['parentId'].'<br>'; |
129 |
|
|
$this->level++; |
130 |
|
|
} |
131 |
|
|
|
132 |
|
|
/** |
133 |
|
|
* |
134 |
|
|
* |
135 |
|
|
* @version 2002/01/17 |
136 |
|
|
* @access public |
137 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
138 |
|
|
* @return boolean true on success |
139 |
|
|
*/ |
140 |
|
|
function endHandler($parser, $element) |
141 |
|
|
{ |
142 |
|
|
$this->level--; |
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
/** |
146 |
|
|
* |
147 |
|
|
* |
148 |
|
|
* @version 2002/01/17 |
149 |
|
|
* @access public |
150 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
151 |
|
|
* @return boolean true on success |
152 |
|
|
*/ |
153 |
|
|
function cdataHandler($parser, $cdata) |
154 |
|
|
{ |
155 |
|
|
# QUESTION: why is this method called multiple times for one element? |
156 |
|
|
# is every space a cdata ??? |
157 |
|
|
# ANSWER: if you call xml_parse($parser, "foo ", false) and then |
158 |
|
|
# xml_parse($parser, "bar", true), callbacks are done once |
159 |
|
|
# for each xml_parse() call. |
160 |
|
|
if( !isset($this->data[ sizeof($this->data)-1 ]['cdata']) ) |
161 |
|
|
$this->data[ sizeof($this->data)-1 ]['cdata'] = ''; |
162 |
|
|
#print "cdata = '$cdata'\r\n"; |
163 |
|
|
$this->data[ sizeof($this->data)-1 ]['cdata'].= $cdata; |
164 |
|
|
} |
165 |
|
|
|
166 |
|
|
/** |
167 |
|
|
* |
168 |
|
|
* |
169 |
|
|
* @version 2002/01/17 |
170 |
|
|
* @access public |
171 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
172 |
|
|
* @return boolean true on success |
173 |
|
|
*/ |
174 |
|
|
function defaultHandler($parser, $cdata) |
175 |
|
|
{ |
176 |
|
|
# $this->data[ sizeof($this->data)-1 ]['cdata'] = $cdata; |
177 |
|
|
# not in use yet :-( is that ok?? |
178 |
|
|
} |
179 |
|
|
|
180 |
|
|
|
181 |
|
|
|
182 |
|
|
|
183 |
|
|
/** |
184 |
|
|
* read the data from the xml file and prepare them so the tree |
185 |
|
|
* class can work with it, the preparation is mainly done in startHandler |
186 |
|
|
* |
187 |
|
|
* @version 2002/01/17 |
188 |
|
|
* @access public |
189 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
190 |
|
|
* @return boolean true on success |
191 |
|
|
*/ |
192 |
|
|
function setup() |
193 |
|
|
{ |
194 |
|
|
$this->parse(); |
195 |
|
|
|
196 |
|
|
return $this->data; |
197 |
|
|
} // end of function |
198 |
|
|
|
199 |
|
|
/** |
200 |
|
|
* read the data from an xml string and prepare them so the tree |
201 |
|
|
* class can work with it, the preparation is mainly done in startHandler |
202 |
|
|
* |
203 |
|
|
* @version 2002/02/05 |
204 |
|
|
* @access public |
205 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
206 |
|
|
* @return boolean true on success |
207 |
|
|
*/ |
208 |
|
|
function setupByRawData( $xmlString ) |
209 |
|
|
{ |
210 |
|
|
$this->parseString( $xmlString , true ); |
211 |
|
|
|
212 |
|
|
return $this->data; |
213 |
|
|
} |
214 |
|
|
|
215 |
|
|
/** |
216 |
|
|
* TO BE IMPLEMNTED |
217 |
|
|
* adds _one_ new element in the tree under the given parent |
218 |
|
|
* the values' keys given have to match the db-columns, because the |
219 |
|
|
* value gets inserted in the db directly |
220 |
|
|
* to add an entire node containing children and so on see 'addNode()' |
221 |
|
|
* |
222 |
|
|
* @see addNode() |
223 |
|
|
* @version 2001/10/09 |
224 |
|
|
* @access public |
225 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
226 |
|
|
* @param array $newValues this array contains the values that shall be inserted in the db-table |
227 |
|
|
* @return mixed either boolean false on failure or the id of the inserted row |
228 |
|
|
*/ |
229 |
|
|
/* function add( $newValues ) |
230 |
|
|
{ |
231 |
|
|
// add the data in the internal structure $this->data |
232 |
|
|
$this->data[sizeof($this->data)] = $newValues; |
233 |
|
|
|
234 |
|
|
# i am thinking if it might be a good solution to walk the data-array |
235 |
|
|
# and write each line singlely until the one to add comes, write it and |
236 |
|
|
# keep on writing the data-array |
237 |
|
|
# but that means writing the entire file every time any method that |
238 |
|
|
# changes the xml-file's structure the entire file is written, |
239 |
|
|
# can that not be done somehow better ??? |
240 |
|
|
|
241 |
|
|
# // and regenerate the xml file |
242 |
|
|
# $this->_writeFile(); |
243 |
|
|
|
244 |
|
|
} // end of function |
245 |
|
|
*/ |
246 |
|
|
/** |
247 |
|
|
* TO BE IMPLEMNTED |
248 |
|
|
* removes the given node |
249 |
|
|
* |
250 |
|
|
* @version 2001/10/09 |
251 |
|
|
* @access public |
252 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
253 |
|
|
* @param mixed $id the id of the node to be removed |
254 |
|
|
* @return boolean true on success |
255 |
|
|
*/ |
256 |
|
|
/* function remove( $id ) |
257 |
|
|
{ |
258 |
|
|
// remove the data from this->data |
259 |
|
|
unset($this->data[$id]); |
260 |
|
|
|
261 |
|
|
# see comment in "add"-method |
262 |
|
|
} // end of function |
263 |
|
|
*/ |
264 |
|
|
/** |
265 |
|
|
* TO BE IMPLEMNTED |
266 |
|
|
* move an entry under a given parent or behind a given entry |
267 |
|
|
* |
268 |
|
|
* @version 2001/10/10 |
269 |
|
|
* @access public |
270 |
|
|
* @author Wolfram Kriesing <wolfram@kriesing.de> |
271 |
|
|
* @param |
272 |
|
|
* @param |
273 |
|
|
* @param integer if prevId is given the element with the id idToMove shall be moved _behind_ element with id=prevId |
274 |
|
|
* before would be easier, but then no element could be inserted at the end :-/ |
275 |
|
|
* @return boolean true for success |
276 |
|
|
*/ |
277 |
|
|
/* function move( $idToMove , $newParentId , $prevId=0 ) |
278 |
|
|
{ |
279 |
|
|
$this->data[$idToMove]['parentId'] = $newParentId; |
280 |
|
|
$this->data[$idToMove]['prevId'] = $prevId; |
281 |
|
|
|
282 |
|
|
# see comment in "add"-method |
283 |
|
|
} // end of function |
284 |
|
|
*/ |
285 |
|
|
|
286 |
|
|
} |
287 |
|
|
?> |