Subversion Repositories Applications.papyrus

Rev

Rev 1372 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1173 jp_milcent 1
<?php
2
//
3
// +----------------------------------------------------------------------+
4
// | PEAR :: DB_NestedSet_TigraMenu                                        |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2003 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.0 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: Daniel Khan <dk@webcluster.at>                              |
17
// +----------------------------------------------------------------------+
18
//
19
// $Id: TigraMenu.php,v 1.1 2006-12-14 15:04:29 jp_milcent Exp $
20
//
21
 
22
// {{{ DB_NestedSet_TigraMenu:: class
23
 
24
/**
25
* This class can be used to generate the data to build javascript popup menu
26
* from a DB_NestedSet node array.
27
* The Javascript part is done using the free available TigraMenu
28
* available at http://www.softcomplex.com/products/tigra_menu/.
29
* Currently version 1.0 is supported.
30
* Parts of this class where taken ftom the TreemMenu driver by Jason Rust
31
*
32
* @author       Daniel Khan <dk@webcluster.at>
33
* @package      DB_NestedSet
34
* @version      $Revision: 1.1 $
35
* @access       public
36
*/
37
// }}}
38
class DB_NestedSet_TigraMenu extends DB_NestedSet_Output {
39
    // {{{{ properties
40
 
41
    /**
42
    * @var integer The depth of the current menu.
43
    * @access private
44
    */
45
    var $_levels    = 1;
46
 
47
    /**
48
    * @var integer The level we started at
49
    * @access private
50
    */
51
    var $_levelOffset = false;
52
 
53
 
54
    /**
55
    * @var array The current menu structure
56
    * @access private
57
    */
58
    var $_structTigraMenu = false;
59
 
60
    /**
61
    * @var array The longest text for each level
62
    * @access private
63
    */
64
    var $_strlenByLevel = array();
65
 
66
    // }}}
67
    // {{{ DB_NestedSet_TigraMenu
68
 
69
    /**
70
    * Constructor
71
    *
72
    * @param array $params A hash with parameters needed by the class
73
    * @see _createFromStructure()
74
    * @return bool
75
    **/
76
    function &DB_NestedSet_TigraMenu($params) {
77
        $this->_menu_id = $params['menu_id'];
78
        $this->_structTigraMenu = $this->_createFromStructure($params);
79
        return true;
80
    }
81
 
82
    // }}}
83
    // {{{ _createFromStructure()
84
 
85
    /**
86
    * Creates the JavaScript array for TigraMenu
87
    * Initially this method was introduced for the TreeMenu driver by Jason Rust
88
    *
89
    * o 'structure' => the result from $nestedSet->getAllNodes(true)
90
    * o 'textField' => the field in the table that has the text for node
91
    * o 'linkField' => the field in the table that has the link for the node
92
    *
93
    * @access private
94
    * @return string The TigraMenu JavaScript array
95
    */
96
    function &_createFromStructure($params)
97
    {
98
        // Basically we go through the array of nodes checking to see
99
        // if each node has children and if so recursing.  The reason this
100
        // works is because the data from getAllNodes() is ordered by level
101
        // so a root node will always be first, and sub children will always
102
        // be after them.
103
 
104
        static $rootlevel;
105
 
106
        // always start at level 1
107
        if (!isset($params['currentLevel'])) {
108
            $params['currentLevel'] = 1;
109
        }
110
 
111
        if (!isset($rootlevel)) {
112
            $rootlevel = $params['currentLevel'];
113
        }
114
 
115
        if (isset($params['tigraMenu'])) {
116
            $tigraMenu = $tigraMenu.$params['tigraMenu'];
117
        }
118
 
119
        if(!$this->_levelOffset) {
120
            $this->_levelOffset = $params['currentLevel'];
121
        }
122
 
123
        if($this->_levels < ($params['currentLevel']- $this->_levelOffset)) {
124
            $this->_levels = $params['currentLevel'] - $this->_levelOffset;
125
        }
126
 
127
 
128
        // have to use a while loop here because foreach works on a copy of the array and
129
        // the child nodes are passed by reference during the recursion so that the parent
130
        // will know when they have been hit.
131
        reset($params['structure']);
132
        while(list($key, $node) = each($params['structure'])) {
133
            // see if we've already been here before
134
            if (isset($node['hit']) || $node['level'] < $params['currentLevel']) {
135
                continue;
136
            }
137
 
138
            // mark that we've hit this node
139
            $params['structure'][$key]['hit'] = $node['hit'] = true;
140
 
141
            $tag = array(
142
            isset($node[$params['textField']]) ? "'".$node[$params['textField']]."'" : 'null',
143
            isset($node[$params['linkField']]) ? "'".$node[$params['linkField']]."'" : 'null'
144
            );
145
 
146
            if (!$this->_strlenByLevel[$params['currentLevel'] - $this->_levelOffset] ||
147
            strlen($node[$params['textField']]) > $this->_strlenByLevel[$params['currentLevel'] - $this->_levelOffset]) {
148
                $this->_strlenByLevel[$params['currentLevel'] - $this->_levelOffset] = strlen($node[$params['textField']]);
149
            };
150
 
151
            $tigraMenu = $tigraMenu.$this->_openSubMenu($tag);
152
 
153
            // see if it has children
154
            if (($node['r'] - 1) != $node['l']) {
155
                $children = array();
156
                // harvest all the children
157
                $tempStructure = $params['structure'];
158
                foreach ($tempStructure as $childKey => $childNode) {
159
                    if (!isset($childNode['hit']) &&
160
                    $node['rootid'] == $childNode['rootid'] &&
161
                    $node['l'] < $childNode['l'] &&
162
                    $node['r'] > $childNode['r'] &&
163
                    $childNode['level'] > $params['currentLevel']) {
164
                        // important that we assign it by reference here, so that when the child
165
                        // marks itself 'hit' the parent loops will know
166
                        $children[] =& $params['structure'][$childKey];
167
                    }
168
                }
169
 
170
                $recurseParams = $params;
171
                $recurseParams['structure'] = $children;
172
                $recurseParams['currentLevel']++;
173
                $tigraMenu = $tigraMenu.$this->_createFromStructure($recurseParams);
174
            }
175
 
176
            $tigraMenu = $tigraMenu.$this->_closeSubMenu();
177
        }
178
        return $tigraMenu;
179
    }
180
 
181
    // }}}
182
    // {{{ _openMenu()
183
 
184
    /**
185
    * Returns the string which opens the JavaScript menu
186
    *
187
    * @access private
188
    * @param int $menu_id ID of the menu needed to use more than one menu on a page
189
    * @return string The JavaScript piece
190
    */
191
    function _openMenu($menu_id=1)
192
    {
193
        $str = false;
194
        $str = $str."var MENU_ITEMS".$menu_id." = new Array();\n";
195
        $str = $str."MENU_ITEMS".$menu_id." = [\n";
196
        return $str;
197
    }
198
 
199
    // }}}
200
    // {{{ _openSubMenu()
201
 
202
    /**
203
    * Returns the string which opens a submenu within the JavaScript menu
204
    *
205
    * @access private
206
    * @param array $tag Contains the content of the current item (name, link)
207
    * @return string The JavaScript piece
208
    */
209
    function _openSubMenu($tag)
210
    {
211
        $rtag = implode(', ', $tag);
212
        return "\n[".$rtag.',';
213
    }
214
 
215
    // }}}
216
    // {{{ _closeMenu()
217
 
218
    /**
219
    * Closes the JavaScript array
220
    *
221
    * @access private
222
    * @return string The JavaScript piece
223
    */
224
    function _closeMenu()
225
    {
226
 
227
        return '];';
228
    }
229
 
230
    // }}}
231
    // {{{ _closeSubMenu()
232
 
233
    /**
234
    * Closes the JavaScript array of a submenu
235
    *
236
    * @access private
237
    * @return string The JavaScript piece
238
    */
239
    function _closeSubMenu()
240
    {
241
        return "\n],";
242
    }
243
 
244
    // }}}
245
    // {{{ _addStyles()
246
 
247
    /**
248
    * Creates the JavaScript code which sets the styles for each level
249
    *
250
    * @access private
251
    * @param int $menu_id ID of the menu needed to use more than one menu on a page
252
    * @param array $rootStyles Array of style attributes for the top items
253
    * @param array $childStyles Array of style attributes for the sub items
254
    * @return string The JavaScript piece
255
    */
256
    function _addStyles($menu_id, $rootStyles, $childStyles = false)
257
    {
258
        if (!$childStyles) {
259
            $childStyles = $rootStyles;
260
        }
261
 
262
        $styles = array();
263
        foreach ($rootStyles as $key => $val) {
264
            foreach ($val as $skey => $sval) {
265
                $styles["'$key'"][$skey][] = "'$sval'";
266
            }
267
        }
268
 
269
        foreach ($childStyles as $key => $val) {
270
            foreach ($val as $skey => $sval) {
271
                for ($i = 1; $i <= $this->_levels; $i++) {
272
                    $styles["'$key'"][$skey][] = "'$sval'";
273
                }
274
            }
275
        }
276
 
277
        $menustyles = false;
278
        $menustyles = $menustyles . 'var MENU_STYLES'.$menu_id." = new Array();\n";
279
        foreach ($styles as $key => $val) {
280
            $menustyles = $menustyles.'MENU_STYLES'.$menu_id."[$key] = [\n";
281
            foreach ($val as $skey => $sval) {
282
                $menustyles = $menustyles . "'$skey', [".implode(', ', $sval)."],\n";
283
            }
284
            $menustyles = $menustyles."];\n";
285
        }
286
 
287
        return $menustyles;
288
    }
289
 
290
    // }}}
291
    // {{{ _addGeometry()
292
 
293
    /**
294
    * Creates the JavaScript code which sets the position and geometry of the menu
295
    *
296
    * @access private
297
    * @param int $menu_id ID of the menu needed to use more than one menu on a page
298
    * @param array $rootGeometry Array of geometry attributes for the top items
299
    * @param array $childGeometry  Array of geometry attributes for the sub items
300
    * @return string The JavaScript piece
301
    */
302
    function _addGeometry($menu_id, $rootGeometry, $childGeometry = false)
303
    {
304
        if (!$childGeometry) {
305
            $childGeometry = $rootGeometry;
306
        }
307
 
308
        $params = array();
309
        $geometry = array();
310
        foreach ($rootGeometry as $key => $val) {
311
            $geometry["'$key'"][] = $val;
312
            $incr = false;
313
            if (strpos($val, ',') !== false) {
314
                list($start, $interval) = explode(',',$val);
315
                $incr = true;
316
            }
317
 
318
            $ratio = false;
319
            if ($key == 'width' && strpos($val, '*') !== false) {
320
                $ratio = trim(str_replace('*','', $val));
321
            }
322
            if ($incr) {
323
                $val = trim($interval);
324
                if ($key == 'left' && preg_match('/[+-]/', $interval)) {
325
                    $val = $params[0]['width'] + trim($val);
326
                }
327
            } elseif ($incr) {
328
                $val = trim($start);
329
            } elseif ($ratio) {
330
                $val = $ratio * $this->_strlenByLevel[0];
331
            }
332
            $geometry["'$key'"][0] = $val;
333
            $params[0][$key] = $val;
334
        }
335
 
336
        foreach($childGeometry as $key => $val) {
337
            $incr = false;
338
            if (strpos($val, ',') !== false) {
339
                list($start, $interval) = explode(',', $val);
340
                $incr = true;
341
            }
342
 
343
            $ratio = false;
344
            if ($key == 'width' && strpos($val, '*') !== false) {
345
                $ratio = trim(str_replace('*', '', $val));
346
            }
347
 
348
            for ($i = 1; $i <= $this->_levels; $i++) {
349
                if ($incr && isset($lastval[$key])) {
350
                    $val = trim($interval);
351
                    if($key == 'block_left' && preg_match('/[+-]/', $interval)) {
352
                        $val = $params[$i - 1]['width'] + trim($val);
353
                    }
354
                } elseif($incr) {
355
                    $val = trim($start);
356
                } elseif ($ratio) {
357
                    $val = $ratio * $this->_strlenByLevel[$i];
358
                    if($val < $params[0]['width']) {
359
                        $val =  $params[0]['width'];
360
                    }
361
                }
362
 
363
                $lastval[$key] = $val;
364
                $geometry["'$key'"][] = $val;
365
                $params[$i][$key] = $val;
366
            }
367
 
368
        }
369
 
370
        $pos = false;
371
        $pos = $pos . 'var MENU_POS'.$menu_id." = new Array();\n";
372
        foreach ($geometry as $key => $val) {
373
            $pos = $pos . 'MENU_POS' . $menu_id . "[$key] = [" . implode(', ', $val) . "];\n";
374
        }
375
 
376
        return $pos;
377
    }
378
 
379
    // }}}
380
    // {{{ printTree()
381
 
382
    /**
383
    * Print's the current tree using the output driver
384
    *
385
    * @access public
386
    */
387
    function printTree()
388
    {
389
        if (!$options = $this->_getOptions('printTree')) {
390
            return PEAR::raiseError("TigraMenu::printTree() needs options. See TigraMenu::setOptions()", NESEO_ERROR_NO_OPTIONS, PEAR_ERROR_TRIGGER, E_USER_ERROR);
391
        }
392
 
393
        echo $this->_openMenu($options['menu_id']) . $this->_structTigraMenu  .$this->_closeMenu();
394
        echo "\n\n";
395
        echo $this->_addStyles($options['menu_id'], $options['rootStyles'], $options['childStyles']);
396
        echo "\n\n";
397
        echo $this->_addGeometry($options['menu_id'], $options['rootGeometry'], $options['childGeometry']);
398
    }
399
 
400
    // }}}
401
}
402
?>