Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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