Completed
Push — master ( 2a7334...2bafa1 )
by Andreas
19:53
created

midcom_helper_toolbar::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package midcom.helper
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
/**
10
 * This class is a generic toolbar class. It supports enabling
11
 * and disabling of buttons, icons and hover-helptexts (currently
12
 * rendered using TITLE tags).
13
 *
14
 * A single button in the toolbar is represented using an associative
15
 * array with the following elements:
16
 *
17
 * <code>
18
 * $item = Array (
19
 *     [MIDCOM_TOOLBAR_URL] => $url,
20
 *     [MIDCOM_TOOLBAR_LABEL] => $label,
21
 *     [MIDCOM_TOOLBAR_HELPTEXT] => $helptext,
22
 *     [MIDCOM_TOOLBAR_ICON] => $icon,
23
 *     [MIDCOM_TOOLBAR_ENABLED] => $enabled,
24
 *     [MIDCOM_TOOLBAR_HIDDEN] => $hidden
25
 *     [MIDCOM_TOOLBAR_OPTIONS] => array $options,
26
 *     [MIDCOM_TOOLBAR_SUBMENU] => midcom_helper_toolbar $submenu,
27
 *     [MIDCOM_TOOLBAR_ACCESSKEY] => (char) 'a',
28
 *     [MIDCOM_TOOLBAR_POST] => true,
29
 *     [MIDCOM_TOOLBAR_POST_HIDDENARGS] => array $args,
30
 * );
31
 * </code>
32
 *
33
 * The URL parameter can be interpreted in three different ways:
34
 * If it is a relative URL (not starting with 'http[s]://' or at least
35
 * a '/') it will be interpreted relative to the current Anchor
36
 * Prefix as defined in the active MidCOM context. Otherwise, the URL
37
 * is used as-is. Note, that the Anchor-Prefix is appended immediately
38
 * when the item is added, not when the toolbar is rendered.
39
 *
40
 * The original URL (before prepending anything) is stored internally;
41
 * so in all places where you reference an element by-URL, you can use
42
 * the original URL if you wish (actually, both URLs are recognized
43
 * during the translation into an id).
44
 *
45
 * The label is the text shown as the button, the helptext is used as
46
 * TITLE value to the anchor, and will be shown when hovering over the
47
 * link therefore. Set it to null, to suppress this feature (this is the
48
 * default).
49
 *
50
 * The icon is a relative URL within the static MidCOM tree, for example
51
 * 'stock-icons/16x16/attach.png'. Set it to null, to suppress the display
52
 * of an icon (this is the default)
53
 *
54
 * By default, as shown below, the toolbar system renders a standard Hyperlink.
55
 * If you set MIDCOM_TOOLBAR_POST to true however, a form is used instead.
56
 * This is important if you want to provide operations directly behind the
57
 * toolbar entries - you'd run into problems with HTTP Link Prefetching
58
 * otherwise. It is also useful if you want to pass complex operations
59
 * to the URL target, as the option MIDCOM_TOOLBAR_POST_HIDDENARGS allows
60
 * you to add HIDDEN variables to the form. These arguments will be automatically
61
 * run through htmlspecialchars when rendering. By default, standard links will
62
 * be rendered, POST versions will only be used if explicitly requested.
63
 *
64
 * Note, that while this should prevent link prefetching on the POST entries,
65
 * this is a big should. Due to its lack of standardization, it is strongly
66
 * recommended to check for a POST request when processing such toolbar
67
 * targets, using something like this:
68
 *
69
 * <code>
70
 * if ($_SERVER['REQUEST_METHOD'] != 'post')
71
 * {
72
 *     throw new midcom_error_forbidden('Only POST requests are allowed here.');
73
 * }
74
 * </code>
75
 *
76
 * The enabled boolean flag is set to true (the default) if the link should
77
 * be clickable, or to false otherwise.
78
 *
79
 * The hidden boolean flag is very similar to the enabled one: Instead of
80
 * having unclickable links, it just hides the toolbar button entirely.
81
 * This is useful for access control checks, where you want to completely
82
 * hide items without access. The difference from just not adding the
83
 * corresponding variable is that you can have a consistent set of
84
 * toolbar options in a "template" which you just need to tweak by
85
 * setting this flag. (Note, that there is no explicit access
86
 * control checks in the toolbar helper itself, as this would mean that
87
 * the corresponding content objects need to be passed into the toolbar,
88
 * which is not feasible with the large number of toolbars in use in NAP
89
 * for example.)
90
 *
91
 * The midcom_toolbar_submenu can be used to create nested submenus by adding a pointer
92
 * to a new toolbar object.
93
 *
94
 * The toolbar gets rendered as an unordered list, letting you define the
95
 * CSS id and/or class tags of the list itself. The default class for
96
 * example used the well-known horizontal-UL approach to transform this
97
 * into a real toolbar. The output of the draw call therefore looks like
98
 * this:
99
 *
100
 * The <b>accesskey</b> option is used to assign an accesskey to the toolbar item.
101
 * It will be rendered in the toolbar text as either underlining the key or stated in
102
 * parentheses behind the text.
103
 *
104
 * <pre>
105
 * &lt;ul [class="$class"] [id="$id"]&gt;
106
 *   &lt;li class="(enabled|disabled)"&gt;
107
 *     [&lt;a href="$url" [title="$helptext"] [ $options as $key =&gt; $val ]&gt;]
108
 *       [&lt;img src="$calculated_image_url"&gt;]
109
 *       $label
110
 *      [new submenu here]
111
 *     [&lt;/a&gt;]
112
 *   &lt;/li&gt;
113
 * &lt;/ul&gt;
114
 * </pre>
115
 *
116
 * Both class and id can be null, indicating no style should be selected.
117
 * By default, the class will use "midcom_toolbar" and no id style, which
118
 * will yield a traditional MidCOM toolbar. Of course, the
119
 * style sheet must be loaded to support this. Note, that this style assumes
120
 * 16x16 height icons in its toolbar rendering. Larger or smaller icons
121
 * will look ugly in the layout.
122
 *
123
 * The options array. You can use the options array to make simple changes to the toolbar items.
124
 * Here's a quick example to remove the underlining.
125
 * <code>
126
 * foreach ($toolbar->items as $index => $item) {
127
 *     $toolbar->items[$index][MIDCOM_TOOLBAR_OPTIONS] = array( "style" => "text-decoration:none;");
128
 * }
129
 * </code>
130
 * This will add style="text-decoration:none;" to all the links in the toolbar.
131
 *
132
 * @package midcom.helper
133
 */
134
class midcom_helper_toolbar
135
{
136
    /**
137
     * The CSS ID-Style rule that should be used for the toolbar.
138
     * Set to null if none should be used.
139
     *
140
     * @var string
141
     */
142
    public $id_style;
143
144
    /**
145
     * The CSS class-Style rule that should be used for the toolbar.
146
     * Set to null if none should be used.
147
     *
148
     * @var string
149
     */
150
    public $class_style;
151
152
    /**
153
     * The toolbar's label
154
     *
155
     * @var string
156
     */
157
    protected $label;
158
159
    /**
160
     * The items in the toolbar.
161
     *
162
     * The array consists of Arrays outlined in the class introduction.
163
     * You can modify existing items in this collection but you should use
164
     * the class methods to add or delete existing items. Also note that
165
     * relative URLs are processed upon the invocation of add_item(), if
166
     * you change URL manually, you have to ensure a valid URL by yourself
167
     * or use update_item_url, which is recommended.
168
     *
169
     * @var Array
170
     */
171
    public $items = [];
172
173
    /**
174
     * Allow our users to add arbitrary data to the toolbar.
175
     *
176
     * This is for example used to track which items have been added to a toolbar
177
     * when it is possible that the adders are called repeatedly.
178
     *
179
     * The entries should be namespaced according to the usual MidCOM
180
     * Namespacing rules.
181
     *
182
     * @var Array
183
     */
184
    public $customdata = [];
185
186
    /**
187
     * Basic constructor, initializes the class and sets defaults for the
188
     * CSS style if omitted.
189
     *
190
     * Note that the styles can be changed after construction by updating
191
     * the id_style and class_style members.
192
     *
193
     * @param string $class_style The class style tag for the UL.
194
     * @param string $id_style The id style tag for the UL.
195
     */
196 329
    public function __construct($class_style = 'midcom_toolbar', $id_style = null)
197
    {
198 329
        $this->id_style = $id_style;
199 329
        $this->class_style = $class_style;
200 329
    }
201
202
    /**
203
     *
204
     * @return string
205
     */
206
    public function get_label()
207
    {
208
        return $this->label;
209
    }
210
211
    /**
212
     *
213
     * @param string $label
214
     */
215 50
    public function set_label($label)
216
    {
217 50
        $this->label = $label;
218 50
    }
219
220
    /**
221
     * Add a help item to the toolbar.
222
     *
223
     * @param string $help_id Name of the help file in component documentation directory.
224
     * @param string $component Component to display the help from
225
     * @param string $label Label for the help link
226
     * @param string $anchor Anchor ("a name" or "id" in HTML page) to link to
227
     */
228 1
    public function add_help_item($help_id, $component = null, $label = null, $anchor = null, $before = -1)
229
    {
230 1
        $uri = "__ais/help/";
231 1
        if (!is_null($component)) {
232 1
            $uri .= $component . '/';
233
        }
234 1
        $uri .= $help_id . '/';
235
236 1
        if (!is_null($anchor)) {
237
            $uri .= "#{$anchor}";
238
        }
239
240 1
        if (is_null($label)) {
241 1
            $label = midcom::get()->i18n->get_string('help', 'midcom.admin.help');
242
        }
243
244 1
        $this->add_item([
245 1
            MIDCOM_TOOLBAR_URL => $uri,
246 1
            MIDCOM_TOOLBAR_LABEL => $label,
247 1
            MIDCOM_TOOLBAR_GLYPHICON => 'question',
248 1
            MIDCOM_TOOLBAR_ACCESSKEY => 'h',
249
            MIDCOM_TOOLBAR_OPTIONS => [
250
                'target' => '_blank',
251
            ]],
252
            $before
253
        );
254 1
    }
255
256
    /**
257
     * Add an item to the toolbar.
258
     *
259
     * Set before to the index of the element before which you want to insert
260
     * the item or use -1 if you want to append an item. Alternatively,
261
     * instead of specifying an index, you can specify a URL instead.
262
     *
263
     * This member will process the URL and append the anchor prefix in case
264
     * the URL is a relative one.
265
     *
266
     * Invalid positions will result in a MidCOM Error.
267
     *
268
     * @param array $item The item to add.
269
     * @param mixed $before The index before which the item should be inserted.
270
     *     Use -1 for appending at the end, use a string to insert
271
     *     it before a URL, an integer will insert it before a
272
     *     given index.
273
     * @see midcom_helper_toolbar::get_index_from_url()
274
     * @see midcom_helper_toolbar::_check_index()
275
     * @see midcom_helper_toolbar::clean_item()
276
     */
277 329
    public function add_item($item, $before = -1)
278
    {
279 329
        if ($before != -1) {
280 1
            $before = $this->_check_index($before, false);
281
        }
282 329
        $item = $this->clean_item($item);
283
284 329
        if ($before == -1) {
285 329
            $this->items[] = $item;
286 1
        } elseif ($before == 0) {
287
            array_unshift($this->items, $item);
288
        } else {
289 1
            $start = array_slice($this->items, 0, $before - 1);
290 1
            $start[] = $item;
291 1
            $this->items = array_merge($start, array_slice($this->items, $before));
292
        }
293 329
    }
294
295
    /**
296
     * Convenience shortcut to add multiple buttons at the same item
297
     *
298
     * @param array $items The items to add.
299
     * @param mixed $before The index before which the item should be inserted.
300
     *     Use -1 for appending at the end, use a string to insert
301
     *     it before a URL, an integer will insert it before a
302
     *     given index.
303
     */
304 329
    public function add_items(array $items, $before = -1)
305
    {
306 329
        foreach ($items as $item) {
307 329
            $this->add_item($item, $before);
308
        }
309 329
    }
310
311
    /**
312
     * Add an item to another item by either adding the item to the MIDCOM_TOOLBAR_SUBMENU
313
     * or creating a new subtoolbar and adding the item there.
314
     *
315
     * @param array $item
316
     * @param int $index toolbar item index.
317
     * @return boolean false if insert failed.
318
     */
319
    public function add_item_to_index($item, $index)
320
    {
321
        $item = $this->clean_item($item);
322
        if (!array_key_exists($index, $this->items)) {
323
            debug_add("Insert of item {$item[MIDCOM_TOOLBAR_LABEL]} into index $index failed");
324
            return false;
325
        }
326
327
        if (empty($this->items[$index][MIDCOM_TOOLBAR_SUBMENU])) {
328
            $this->items[$index][MIDCOM_TOOLBAR_SUBMENU] = new midcom_helper_toolbar($this->class_style, $this->id_style);
329
        }
330
331
        $this->items[$index][MIDCOM_TOOLBAR_SUBMENU]->items[] = $item;
332
333
        return true;
334
    }
335
336
    /**
337
     * Clean up an item that is added, making sure that the item has all the
338
     * needed options and indexes.
339
     *
340
     * @param array $item the item to be cleaned
341
     * @return array the cleaned item.
342
     */
343 329
    public function clean_item($item)
344
    {
345 329
        static $used_access_keys = [];
346
347
        $defaults = [
348 329
            MIDCOM_TOOLBAR_URL => './',
349
            MIDCOM_TOOLBAR_OPTIONS => [],
350
            MIDCOM_TOOLBAR_HIDDEN => false,
351
            MIDCOM_TOOLBAR_HELPTEXT => '',
352
            MIDCOM_TOOLBAR_ICON => null,
353
            MIDCOM_TOOLBAR_GLYPHICON => null,
354
            MIDCOM_TOOLBAR_ENABLED => true,
355
            MIDCOM_TOOLBAR_POST => false,
356
            MIDCOM_TOOLBAR_POST_HIDDENARGS => [],
357
            MIDCOM_TOOLBAR_ACCESSKEY => null
358
        ];
359
        // we can't use array_merge unfortunately, because the constants are numeric..
360 329
        foreach ($defaults as $key => $value) {
361 329
            if (!array_key_exists($key, $item)) {
362 329
                $item[$key] = $value;
363
            }
364
        }
365
366 329
        if (   !empty($item[MIDCOM_TOOLBAR_ACCESSKEY])
367 329
            && !array_key_exists($item[MIDCOM_TOOLBAR_ACCESSKEY], $used_access_keys)) {
368
            // We have valid access key, add it to help text
369 9
            $prefix = 'Alt-';
370 9
            if (   isset($_SERVER['HTTP_USER_AGENT'])
371 9
                && strstr($_SERVER['HTTP_USER_AGENT'], 'Macintosh')) {
372
                // Mac users
373
                $prefix = 'Ctrl-Alt-';
374
            }
375 9
            $hotkey = $prefix . strtoupper($item[MIDCOM_TOOLBAR_ACCESSKEY]);
376
377 9
            if ($item[MIDCOM_TOOLBAR_HELPTEXT] == '') {
378 9
                $item[MIDCOM_TOOLBAR_HELPTEXT] = $hotkey;
379
            } else {
380
                $item[MIDCOM_TOOLBAR_HELPTEXT] .= " ({$hotkey})";
381
            }
382 9
            $used_access_keys[$item[MIDCOM_TOOLBAR_ACCESSKEY]] = true;
383
        }
384
385 329
        $this->set_url($item, $item[MIDCOM_TOOLBAR_URL]);
386 329
        return $item;
387
    }
388
389 329
    private function set_url(array &$item, $url)
390
    {
391 329
        $item[MIDCOM_TOOLBAR__ORIGINAL_URL] = $url;
392 329
        if (   (   empty($item[MIDCOM_TOOLBAR_OPTIONS]["rel"])
393
                // Some items may want to keep their links unmutilated
394 329
                || $item[MIDCOM_TOOLBAR_OPTIONS]["rel"] != "directlink")
395 329
            && substr($url, 0, 1) != '/'
396 329
            && !preg_match('|^https?://|', $url)) {
397 329
            $url = midcom_core_context::get()->get_key(MIDCOM_CONTEXT_ANCHORPREFIX) . $url;
398
        }
399 329
        $item[MIDCOM_TOOLBAR_URL] = $url;
400 329
    }
401
402
    /**
403
     * Removes a toolbar item based on its index or its URL
404
     *
405
     * It will trigger a MidCOM Error upon an invalid index.
406
     *
407
     * @param mixed $index The (integer) index or URL to remove.
408
     * @see midcom_helper_toolbar::get_index_from_url()
409
     * @see midcom_helper_toolbar::_check_index()
410
     */
411
    public function remove_item($index)
412
    {
413
        $index = $this->_check_index($index);
414
415
        if ($index == 0) {
416
            array_shift($this->items);
417
        } elseif ($index == count($this->items) -1) {
418
            array_pop($this->items);
419
        } else {
420
            $this->items = array_merge(array_slice($this->items, 0, $index - 1),
421
                array_slice($this->items, $index + 1));
422
        }
423
    }
424
425
    /**
426
     * Clears the complete toolbar.
427
     */
428
    public function remove_all_items()
429
    {
430
        $this->items = [];
431
    }
432
433
    /**
434
     * Moves an item on place upwards in the list.
435
     *
436
     * This will only work, of course, if you are not working with the top element.
437
     *
438
     * @param mixed $index The integer index or URL of the item to move upwards.
439
     */
440
    public function move_item_up($index)
441
    {
442
        if ($index == 0) {
443
            throw new midcom_error('Cannot move the top element upwards.');
444
        }
445
        $index = $this->_check_index($index);
446
447
        $tmp = $this->items[$index];
448
        $this->items[$index] = $this->items[$index - 1];
449
        $this->items[$index - 1] = $tmp;
450
    }
451
452
    /**
453
     * Moves an item on place downwards in the list.
454
     *
455
     * This will only work, of course, if you are not working with the bottom element.
456
     *
457
     * @param mixed $index The integer index or URL of the item to move downwards.
458
     */
459
    public function move_item_down($index)
460
    {
461
        if ($index == (count($this->items) - 1)) {
462
            throw new midcom_error('Cannot move the bottom element downwards.');
463
        }
464
        $index = $this->_check_index($index);
465
466
        $tmp = $this->items[$index];
467
        $this->items[$index] = $this->items[$index + 1];
468
        $this->items[$index + 1] = $tmp;
469
    }
470
471
    /**
472
     * Set's an item's enabled flag to true.
473
     *
474
     * @param mixed $index The integer index or URL of the item to enable.
475
     */
476
    public function enable_item($index)
477
    {
478
        $index = $this->_check_index($index);
479
        $this->items[$index][MIDCOM_TOOLBAR_ENABLED] = true;
480
    }
481
482
    /**
483
     * Set's an item's enabled flag to false.
484
     *
485
     * @param mixed $index The integer index or URL of the item to disable.
486
     */
487 14
    public function disable_item($index)
488
    {
489 14
        $index = $this->_check_index($index, false);
490
491 14
        if (is_null($index)) {
0 ignored issues
show
introduced by
The condition is_null($index) is always false.
Loading history...
492
            return false;
493
        }
494
495 14
        $this->items[$index][MIDCOM_TOOLBAR_ENABLED] = false;
496 14
    }
497
498
    /**
499
     * Set's an item's hidden flag to true.
500
     *
501
     * @param mixed $index The integer index or URL of the item to hide.
502
     */
503 7
    public function hide_item($index)
504
    {
505 7
        $index = $this->_check_index($index, false);
506
507 7
        if (is_null($index)) {
0 ignored issues
show
introduced by
The condition is_null($index) is always false.
Loading history...
508 2
            return false;
509
        }
510
511 5
        $this->items[$index][MIDCOM_TOOLBAR_HIDDEN] = true;
512 5
    }
513
514
    /**
515
     * Set's an item's hidden flag to false.
516
     *
517
     * @param mixed $index The integer index or URL of the item to show.
518
     */
519
    public function show_item($index)
520
    {
521
        $index = $this->_check_index($index);
522
        $this->items[$index][MIDCOM_TOOLBAR_HIDDEN] = false;
523
    }
524
525
    /**
526
     * Updates an items URL using the same rules as in add_item.
527
     *
528
     * @param mixed $index The integer index or URL of the item to update.
529
     * @param string $url The new URL to set.
530
     * @see midcom_helper_toolbar::get_index_from_url()
531
     * @see midcom_helper_toolbar::_check_index()
532
     * @see midcom_helper_toolbar::add_item()
533
     */
534
    public function update_item_url($index, $url)
535
    {
536
        $index = $this->_check_index($index);
537
        $this->set_url($this->items[$index], $url);
538
    }
539
540
    /**
541
     * Renders the toolbar and returns it as a string.
542
     *
543
     * @return string The rendered toolbar.
544
     */
545
    public function render()
546
    {
547 8
        $visible_items = array_filter($this->items, function ($item) {
548 7
            return !$item[MIDCOM_TOOLBAR_HIDDEN];
549 8
        });
550
551 8
        if (count($visible_items) == 0) {
552 1
            debug_add('Tried to render an empty toolbar, returning an empty string.');
553 1
            return '';
554
        }
555
556
        // List header
557 7
        $output = '<ul';
558 7
        if (!is_null($this->class_style)) {
0 ignored issues
show
introduced by
The condition is_null($this->class_style) is always false.
Loading history...
559 7
            $output .= " class='{$this->class_style}'";
560
        }
561 7
        if (!is_null($this->id_style)) {
0 ignored issues
show
introduced by
The condition is_null($this->id_style) is always false.
Loading history...
562
            $output .= " id='{$this->id_style}'";
563
        }
564 7
        $output .= '>';
565
566 7
        $last = count($visible_items);
567 7
        $first_class = ($last === 1) ? 'only_item' : 'first_item';
568
        // List items
569 7
        foreach ($visible_items as $i => $item) {
570 7
            $output .= '<li class="';
571 7
            if ($i == 0) {
572 7
                $output .= $first_class .  ' ';
573 5
            } elseif ($i == $last) {
574
                $output .= 'last_item ';
575
            }
576
577 7
            if ($item[MIDCOM_TOOLBAR_ENABLED]) {
578 7
                $output .= 'enabled">';
579
            } else {
580 4
                $output .= 'disabled">';
581
            }
582
583 7
            if ($item[MIDCOM_TOOLBAR_POST]) {
584
                $output .= $this->_render_post_item($item);
585
            } else {
586 7
                $output .= $this->_render_link_item($item);
587
            }
588
589 7
            $output .= '</li>';
590
        }
591
592
        // List footer
593 7
        $output .= '</ul>';
594
595 7
        return $output;
596
    }
597
598
    /**
599
     * Generate a label for the item that includes its accesskey
600
     *
601
     * @param array $item The item to label
602
     * @return string Item's label to display
603
     */
604 7
    private function _generate_item_label($item)
605
    {
606 7
        $label = htmlentities($item[MIDCOM_TOOLBAR_LABEL], ENT_COMPAT, "UTF-8");
607
608 7
        if (!empty($item[MIDCOM_TOOLBAR_ACCESSKEY])) {
609
            // Try finding uppercase version of the accesskey first
610
            $accesskey = strtoupper($item[MIDCOM_TOOLBAR_ACCESSKEY]);
611
            $position = strpos($label, $accesskey);
612
            if (   $position === false
613
                && midcom::get()->i18n->get_current_language() == 'en') {
614
                // Try lowercase, too
615
                $accesskey = strtolower($accesskey);
616
                $position = strpos($label, $accesskey);
617
            }
618
            if ($position !== false) {
0 ignored issues
show
introduced by
The condition $position !== false is always true.
Loading history...
619
                $label = substr_replace($label, "<span style=\"text-decoration: underline;\">{$accesskey}</span>", $position, 1);
620
            }
621
        }
622
623 7
        return $label;
624
    }
625
626
    /**
627
     * Render a regular a href... based link target.
628
     *
629
     * @param array $item The item to render
630
     * @return string The rendered item
631
     */
632 7
    private function _render_link_item($item)
633
    {
634 7
        $output = '';
635 7
        $attributes = $this->get_item_attributes($item);
636
637 7
        if ($item[MIDCOM_TOOLBAR_ENABLED]) {
638 7
            $tagname = 'a';
639 7
            $attributes['href'] = $item[MIDCOM_TOOLBAR_URL];
640
        } else {
641 4
            $tagname = !empty($attributes['title']) ? 'abbr' : 'span';
642
        }
643
644 7
        $output .= '<' . $tagname;
645 7
        foreach ($attributes as $key => $val) {
646 7
            $output .= ' ' . $key . '="' . htmlspecialchars($val) . '"';
647
        }
648 7
        $output .= '>';
649
650 7
        if (!is_null($item[MIDCOM_TOOLBAR_GLYPHICON])) {
651 7
            $class = 'fa fa-' . $item[MIDCOM_TOOLBAR_GLYPHICON];
652 7
            $output .= "<i class='{$class}'></i>";
653
        } elseif (!is_null($item[MIDCOM_TOOLBAR_ICON])) {
654
            $url = MIDCOM_STATIC_URL . '/' . $item[MIDCOM_TOOLBAR_ICON];
655
            $output .= "<img src='{$url}' alt=\"{$item[MIDCOM_TOOLBAR_HELPTEXT]}\" />";
656
        }
657
658 7
        $output .= '&nbsp;<span class="toolbar_label">' . $this->_generate_item_label($item) . "</span>";
659 7
        $output .= '</' . $tagname . '>';
660
661 7
        if (!empty($item[MIDCOM_TOOLBAR_SUBMENU])) {
662
            $output .= $item[MIDCOM_TOOLBAR_SUBMENU]->render();
663
        }
664
665 7
        return $output;
666
    }
667
668 7
    private function get_item_attributes(array $item)
669
    {
670 7
        $attributes = ($item[MIDCOM_TOOLBAR_ENABLED]) ? $item[MIDCOM_TOOLBAR_OPTIONS] : [];
671
672 7
        if (!is_null($item[MIDCOM_TOOLBAR_HELPTEXT])) {
673 7
            $attributes['title'] = $item[MIDCOM_TOOLBAR_HELPTEXT];
674
        }
675
676 7
        if (   $item[MIDCOM_TOOLBAR_ENABLED]
677 7
            && !is_null($item[MIDCOM_TOOLBAR_ACCESSKEY])) {
678
            $attributes['class'] = 'accesskey';
679
            $attributes['accesskey'] = $item[MIDCOM_TOOLBAR_ACCESSKEY];
680
        }
681 7
        return $attributes;
682
    }
683
684
    /**
685
     * Render a form based link target.
686
     *
687
     * @param array $item The item to render
688
     * @return string The rendered item
689
     */
690
    private function _render_post_item($item)
691
    {
692
        $output = '';
693
694
        if ($item[MIDCOM_TOOLBAR_ENABLED]) {
695
            $output .= "<form method=\"post\" action=\"{$item[MIDCOM_TOOLBAR_URL]}\">";
696
            $output .= "<div><button type=\"submit\" name=\"midcom_helper_toolbar_submit\"";
697
698
            foreach ($this->get_item_attributes($item) as $key => $val) {
699
                $output .= ' ' . $key . '="' . htmlspecialchars($val) . '"';
700
            }
701
            $output .= '>';
702
        }
703
704
        if (!is_null($item[MIDCOM_TOOLBAR_GLYPHICON])) {
705
            $class = 'fa fa-' . $item[MIDCOM_TOOLBAR_GLYPHICON];
706
            $output .= "<i class='{$class}'></i>";
707
        } elseif ($item[MIDCOM_TOOLBAR_ICON]) {
708
            $url = MIDCOM_STATIC_URL . "/{$item[MIDCOM_TOOLBAR_ICON]}";
709
            $output .= "<img src=\"{$url}\" alt=\"{$item[MIDCOM_TOOLBAR_HELPTEXT]}\" />";
710
        }
711
712
        $label = $this->_generate_item_label($item);
713
        $output .= " {$label}";
714
715
        if ($item[MIDCOM_TOOLBAR_ENABLED]) {
716
            $output .= '</button>';
717
            foreach ($item[MIDCOM_TOOLBAR_POST_HIDDENARGS] as $key => $value) {
718
                $key = htmlspecialchars($key);
719
                $value = htmlspecialchars($value);
720
                $output .= "<input type=\"hidden\" name=\"{$key}\" value=\"{$value}\"/>";
721
            }
722
            $output .= '</div></form>';
723
        }
724
725
        if (!empty($item[MIDCOM_TOOLBAR_SUBMENU])) {
726
            $output .= $item[MIDCOM_TOOLBAR_SUBMENU]->render();
727
        }
728
729
        return $output;
730
    }
731
732
    /**
733
     * Traverse all available items and return the first
734
     * element whose URL matches the value passed to the function.
735
     *
736
     * Note, that if two items point to the same URL, only the first one
737
     * will be reported.
738
     *
739
     * @param string $url The url to search in the list.
740
     * @return int The index of the item or null, if not found.
741
     */
742 21
    public function get_index_from_url($url)
743
    {
744 21
        foreach ($this->items as $i => $item) {
745 19
            if (   $item[MIDCOM_TOOLBAR_URL] == $url
746 19
                || $item[MIDCOM_TOOLBAR__ORIGINAL_URL] == $url) {
747 19
                return $i;
748
            }
749
        }
750 2
        return null;
751
    }
752
753
    /**
754
     * Check an index for validity.
755
     *
756
     * It will automatically convert a string-based URL into an
757
     * Index (if possible); if the URL can't be found, it will
758
     * also trigger an error. The translated URL is returned by the
759
     * function.
760
     *
761
     * @param mixed $index The integer index or URL to check
762
     * @param boolean $raise_error Whether we should raise an error on missing item
763
     * @throws midcom_error
764
     * @return int $index The valid index (possibly translated from the URL) or null on missing index.
765
     */
766 21
    private function _check_index($index, $raise_error = true)
767
    {
768 21
        if (is_string($index)) {
769 21
            $url = $index;
770 21
            debug_add("Translating the URL '{$url}' into an index.");
771 21
            $index = $this->get_index_from_url($url);
772 21
            if (is_null($index)) {
0 ignored issues
show
introduced by
The condition is_null($index) is always false.
Loading history...
773 2
                debug_add("Invalid URL '{$url}', URL not found.", MIDCOM_LOG_ERROR);
774
775 2
                if ($raise_error) {
776
                    throw new midcom_error("Invalid URL '{$url}', URL not found.");
777
                }
778 2
                return null;
779
            }
780
        }
781 19
        if ($index >= count($this->items)) {
782
            throw new midcom_error("Invalid index {$index}, it is off-the-end.");
783
        }
784 19
        if ($index < 0) {
785
            throw new midcom_error("Invalid index {$index}, it is negative.");
786
        }
787 19
        return $index;
788
    }
789
790
    /**
791
     * Binds this toolbar instance to a DBA content object using the MidCOM toolbar service.
792
     *
793
     * @param midcom_core_dbaobject $object The DBA class instance to bind to.
794
     * @see midcom_services_toolbars
795
     */
796 50
    public function bind_to($object)
797
    {
798 50
        midcom::get()->toolbars->bind_toolbar_to_object($this, $object);
799 50
    }
800
}
801