1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: class Horde_Tree_Html extends Horde_Tree_Base
16: {
17: 18: 19: 20: 21:
22: protected $_node_pos = array();
23:
24: 25: 26: 27: 28:
29: protected $_dropline = array();
30:
31: 32: 33: 34: 35:
36: protected $_altCount = 0;
37:
38: 39: 40: 41: 42:
43: protected $_allowed = array(
44: 'class',
45: 'icon',
46: 'iconalt',
47: 'iconopen',
48: 'url',
49: 'urlclass',
50: 'title',
51: 'target'
52: );
53:
54: 55: 56: 57: 58:
59: protected $_images = array(
60: 'line' => null,
61: 'blank' => null,
62: 'join' => null,
63: 'join_bottom' => null,
64: 'join_top' => null,
65: 'plus' => null,
66: 'plus_bottom' => null,
67: 'plus_only' => null,
68: 'minus' => null,
69: 'minus_bottom' => null,
70: 'minus_only' => null,
71: 'null_only' => null,
72: 'folder' => null,
73: 'folderopen' => null,
74: 'leaf' => null
75: );
76:
77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98:
99: public function __construct($name, array $params = array())
100: {
101: $params = array_merge(array(
102: 'lines' => true
103: ), $params);
104:
105: parent::__construct($name, $params);
106: }
107:
108: 109: 110: 111: 112: 113: 114: 115:
116: public function getTree($static = false)
117: {
118: $this->_static = (bool)$static;
119: $this->_buildIndents($this->_root_nodes);
120:
121: $tree = $this->_buildHeader();
122: foreach ($this->_root_nodes as $node_id) {
123: $tree .= $this->_buildTree($node_id);
124: }
125: return $tree;
126: }
127:
128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143:
144: public function addNodeParams($id, $params = array())
145: {
146: parent::addNodeParams($id, $params);
147: }
148:
149: 150: 151: 152: 153: 154: 155: 156: 157: 158:
159: public function ($header)
160: {
161: parent::setHeader($header);
162: }
163:
164: 165: 166: 167: 168:
169: protected function ()
170: {
171: if (!count($this->_header) ||
172: $this->getOption('hideHeaders')) {
173: return '';
174: }
175:
176: $className = 'treeRowHeader';
177:
178: 179:
180: if ($this->getOption('alternate')) {
181: $className .= ' item' . $this->_altCount;
182: $this->_altCount = 1 - $this->_altCount;
183: }
184:
185: $html = '<div class="' . $className . '">';
186:
187: foreach ($this->_header as $header) {
188: $html .= '<span';
189: if (!empty($header['class'])) {
190: $html .= ' class="' . $header['class'] . '"';
191: }
192:
193: $html .= '>' .
194: (empty($header['html']) ? ' ' : $header['html'])
195: . '</span>';
196: }
197:
198: return $html . '</div>';
199: }
200:
201: 202: 203: 204: 205: 206: 207:
208: protected function _buildTree($node_id)
209: {
210: $node = $this->_nodes[$node_id];
211: $output = $this->_buildLine($node_id);
212:
213: if (isset($node['children']) && $node['expanded']) {
214: foreach ($node['children'] as $key => $val) {
215: $child_node_id = $node['children'][$key];
216: $this->_node_pos[$child_node_id] = array(
217: 'count' => count($node['children']),
218: 'pos' => $key + 1
219: );
220: $output .= $this->_buildTree($child_node_id);
221: }
222: }
223:
224: return $output;
225: }
226:
227: 228: 229: 230: 231: 232: 233:
234: protected function _buildLine($node_id)
235: {
236: $node = $this->_nodes[$node_id];
237:
238: $className = 'treeRow';
239: if (!empty($node['class'])) {
240: $className .= ' ' . $node['class'];
241: }
242:
243: 244:
245: if ($this->getOption('alternate')) {
246: $className .= ' item' . $this->_altCount;
247: $this->_altCount = 1 - $this->_altCount;
248: }
249:
250: $line = '<div class="' . $className . '">';
251:
252: 253:
254: $column = 0;
255:
256: if (isset($node['extra'][Horde_Tree::EXTRA_LEFT])) {
257: $extra = $node['extra'][Horde_Tree::EXTRA_LEFT];
258: $cMax = count($extra);
259: while ($column < $cMax) {
260: $line .= $this->_addColumn($column) . $extra[$column] . '</span>';
261: ++$column;
262: }
263: }
264:
265: $line .= $this->_addColumn($column++);
266:
267: if ($this->getOption('multiline')) {
268: $line .= '<table cellspacing="0"><tr><td>';
269: }
270:
271: for ($i = intval($this->_static); $i < $node['indent']; ++$i) {
272: $line .= $this->_generateImage(($this->_dropline[$i] && $this->getOption('lines')) ? $this->_images['line'] : $this->_images['blank']);
273: }
274: $line .= $this->_setNodeToggle($node_id) . $this->_setNodeIcon($node_id);
275: if ($this->getOption('multiline')) {
276: $line .= '</td><td>';
277: }
278: $line .= $this->_setLabel($node_id);
279:
280: if ($this->getOption('multiline')) {
281: $line .= '</td></tr></table>';
282: }
283:
284: $line .= '</span>';
285:
286: if (isset($node['extra'][Horde_Tree::EXTRA_RIGHT])) {
287: $extra = $node['extra'][Horde_Tree::EXTRA_RIGHT];
288: $cMax = count($extra);
289: for ($c = 0, $cMax = count($extra); $c < $cMax; ++$c) {
290: $line .= $this->_addColumn($column++) . $extra[$c] . '</span>';
291: }
292: }
293:
294: return $line . "</div>\n";
295: }
296:
297: 298:
299: protected function _addColumn($column)
300: {
301: $line = '<span';
302: if (isset($this->_header[$column]['class'])) {
303: $line .= ' class="' . $this->_header[$column]['class'] . '"';
304: }
305: return $line . '>';
306: }
307:
308: 309: 310: 311: 312: 313: 314:
315: protected function _setLabel($node_id)
316: {
317: $n = $this->_nodes[$node_id];
318:
319: $output = '<span>';
320:
321: $label = $n['label'];
322: if (!empty($n['url'])) {
323: $target = '';
324: if (!empty($n['target'])) {
325: $target = ' target="' . $n['target'] . '"';
326: } elseif ($target = $this->getOption('target')) {
327: $target = ' target="' . $target . '"';
328: }
329: $output .= '<a' . (!empty($n['urlclass']) ? ' class="' . $n['urlclass'] . '"' : '') . ' href="' . $n['url'] . '"' . $target . '>' . $label . '</a>';
330: } else {
331: $output .= $label;
332: }
333:
334: return $output . '</span>';
335: }
336:
337: 338: 339: 340: 341: 342: 343:
344: protected function _setNodeToggle($node_id)
345: {
346: $link_start = '';
347: $node = $this->_nodes[$node_id];
348:
349:
350: if ($node['indent'] == 0) {
351: $this->_dropline[0] = false;
352:
353: if ($this->_static) {
354: return '';
355: }
356:
357: 358: 359: 360: 361:
362: $node_type = 0;
363: if ($this->getOption('lines_base') &&
364: (count($this->_root_nodes) > 1)) {
365: switch (array_search($node_id, $this->_root_nodes)) {
366: case 0:
367: $node_type = 1;
368: $this->_dropline[0] = true;
369: break;
370:
371: case (count($this->_root_nodes) - 1):
372: $node_type = 3;
373: break;
374:
375: default:
376: $node_type = 2;
377: $this->_dropline[0] = true;
378: break;
379: }
380: }
381:
382: if (isset($node['children'])) {
383: if (!$this->getOption('lines')) {
384: $img = $this->_images['blank'];
385: } elseif ($node['expanded']) {
386: $img = $node_type
387: ? (($node_type == 2) ? $this->_images['minus'] : $this->_images['minus_bottom'])
388: : $this->_images['minus_only'];
389: } else {
390: $img = $node_type
391: ? (($node_type == 2) ? $this->_images['plus'] : $this->_images['plus_bottom'])
392: : $this->_images['plus_only'];
393: }
394:
395: $link_start = $this->_generateUrlTag($node_id);
396: } else {
397: if ($this->getOption('lines')) {
398: switch ($node_type) {
399: case 0:
400: $img = $this->_images['null_only'];
401: break;
402:
403: case 1:
404: $img = $this->_images['join_top'];
405: break;
406:
407: case 2:
408: $img = $this->_images['join'];
409: break;
410:
411: case 3:
412: $img = $this->_images['join_bottom'];
413: break;
414: }
415: } else {
416: $img = $this->_images['blank'];
417: }
418: }
419: } elseif (isset($node['children'])) {
420:
421: if ($this->_node_pos[$node_id]['pos'] < $this->_node_pos[$node_id]['count']) {
422:
423: if (!$this->getOption('lines')) {
424: $img = $this->_images['blank'];
425: } elseif ($this->_static) {
426: $img = $this->_images['join'];
427: } elseif ($node['expanded']) {
428: $img = $this->_images['minus'];
429: } else {
430: $img = $this->_images['plus'];
431: }
432: $this->_dropline[$node['indent']] = true;
433: } else {
434:
435: if (!$this->getOption('lines')) {
436: $img = $this->_images['blank'];
437: } elseif ($this->_static) {
438: $img = $this->_images['join_bottom'];
439: } elseif ($node['expanded']) {
440: $img = $this->_images['minus_bottom'];
441: } else {
442: $img = $this->_images['plus_bottom'];
443: }
444: $this->_dropline[$node['indent']] = false;
445: }
446:
447: if (!$this->_static) {
448: $link_start = $this->_generateUrlTag($node_id);
449: }
450: } else {
451:
452: if ($this->_node_pos[$node_id]['pos'] < $this->_node_pos[$node_id]['count']) {
453:
454: $img = $this->getOption('lines')
455: ? $this->_images['join']
456: : $this->_images['blank'];
457:
458: $this->_dropline[$node['indent']] = true;
459: } else {
460:
461: $img = $this->getOption('lines')
462: ? $this->_images['join_bottom']
463: : $this->_images['blank'];
464:
465: $this->_dropline[$node['indent']] = false;
466: }
467: }
468:
469: return $link_start .
470: $this->_generateImage($img, 'treeToggle') .
471: ($link_start ? '</a>' : '');
472: }
473:
474: 475: 476: 477: 478: 479: 480:
481: protected function _generateUrlTag($node_id)
482: {
483: $url = new Horde_Url($_SERVER['PHP_SELF']);
484: return $url->add(Horde_Tree::TOGGLE . $this->_instance, $node_id)->link();
485: }
486:
487: 488: 489: 490: 491: 492: 493: 494: 495:
496: protected function _generateImage($src, $class = '', $alt = null)
497: {
498: $img = '<img src="' . $src . '"';
499:
500: if ($class) {
501: $img .= ' class="' . $class . '"';
502: }
503:
504: if (!is_null($alt)) {
505: $img .= ' alt="' . $alt . '"';
506: }
507:
508: return $img . ' />';
509: }
510:
511: 512: 513: 514: 515: 516: 517:
518: protected function _setNodeIcon($node_id)
519: {
520: $node = $this->_nodes[$node_id];
521:
522: if (isset($node['icon'])) {
523: if (empty($node['icon'])) {
524: return '';
525: }
526:
527:
528: $img = (isset($node['iconopen']) && $node['expanded'])
529: ? $node['iconopen']
530: : $node['icon'];
531: } elseif (isset($node['children'])) {
532:
533: $img = $node['expanded']
534: ? $this->_images['folderopen']
535: : $this->_images['folder'];
536: } else {
537:
538: $img = $this->_images['leaf'];
539: }
540:
541: return $this->_generateImage($img, 'treeIcon', isset($node['iconalt']) ? htmlspecialchars($node['iconalt']) : null);
542: }
543:
544: }
545: