Completed
Push — master ( 9b78f7...5dcb4f )
by Andreas
08:15 queued 03:39
created

AbstractItem::getLabel()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 5
nop 0
dl 0
loc 12
rs 9.2
c 0
b 0
f 0
1
<?php
2
3
namespace dokuwiki\Menu\Item;
4
5
/**
6
 * Class AbstractItem
7
 *
8
 * This class defines a single Item to be displayed in one of DokuWiki's menus. Plugins
9
 * can extend those menus through action plugins and add their own instances of this class,
10
 * overwriting some of its properties.
11
 *
12
 * Items may be shown multiple times in different contexts. Eg. for the default template
13
 * all menus are shown in a Dropdown list on mobile, but are split into several places on
14
 * desktop. The item's $context property can be used to hide the item depending on the current
15
 * context.
16
 *
17
 * Children usually just need to overwrite the different properties, but for complex things
18
 * the accessors may be overwritten instead.
19
 */
20
abstract class AbstractItem {
21
22
    /** menu item is to be shown on desktop screens only */
23
    const CTX_DESKTOP = 1;
24
    /** menu item is to be shown on mobile screens only */
25
    const CTX_MOBILE = 2;
26
    /** menu item is to be shown in all contexts */
27
    const CTX_ALL = 3;
28
29
    /** @var string name of the action, usually the lowercase class name */
30
    protected $type = '';
31
    /** @var string optional keyboard shortcut */
32
    protected $accesskey = '';
33
    /** @var string the page id this action links to */
34
    protected $id = '';
35
    /** @var string the method to be used when this action is used in a form */
36
    protected $method = 'get';
37
    /** @var array parameters for the action (should contain the do parameter) */
38
    protected $params = array();
39
    /** @var bool when true, a rel=nofollow should be used */
40
    protected $nofollow = true;
41
    /** @var string this item's label may contain a placeholder, which is replaced with this */
42
    protected $replacement = '';
43
    /** @var string the full path to the SVG icon of this menu item */
44
    protected $svg = DOKU_INC . 'lib/images/menu/00-default_checkbox-blank-circle-outline.svg';
45
    /** @var string can be set to overwrite the default lookup in $lang.btn_* */
46
    protected $label = '';
47
    /** @var int the context this titme is shown in */
48
    protected $context = self::CTX_ALL;
49
50
    /**
51
     * AbstractItem constructor.
52
     *
53
     * Sets the dynamic properties
54
     *
55
     * Children should always call the parent constructor!
56
     *
57
     * @throws \RuntimeException when the action is disabled
58
     */
59
    public function __construct() {
60
        global $ID;
61
        $this->id = $ID;
62
        $this->type = $this->getType();
63
        $this->params['do'] = $this->type;
64
65
        if(!actionOK($this->type)) throw new \RuntimeException("action disabled: {$this->type}");
66
    }
67
68
    /**
69
     * Return this item's label
70
     *
71
     * When the label property was set, it is simply returned. Otherwise, the action's type
72
     * is used to look up the translation in the main language file and, if used, the replacement
73
     * is applied.
74
     *
75
     * @return string
76
     */
77
    public function getLabel() {
78
        if($this->label !== '') return $this->label;
79
80
        /** @var array $lang */
81
        global $lang;
82
        $label = $lang['btn_' . $this->type];
83
        if(strpos($label, '%s')) {
84
            $label = sprintf($label, $this->replacement);
85
        }
86
        if($label === '') $label = '[' . $this->type . ']';
87
        return $label;
88
    }
89
90
    /**
91
     * Return the link this item links to
92
     *
93
     * Basically runs wl() on $id and $params. However if the ID is a hash it is used directly
94
     * as the link
95
     *
96
     * Please note that the generated URL is *not* XML escaped.
97
     *
98
     * @see wl()
99
     * @return string
100
     */
101
    public function getLink() {
102
        if($this->id[0] == '#') {
103
            return $this->id;
104
        } else {
105
            return wl($this->id, $this->params, false, '&');
106
        }
107
    }
108
109
    /**
110
     * Convenience method to get the attributes for constructing an <a> element
111
     *
112
     * @see buildAttributes()
113
     * @param string|false $classprefix create a class from type with this prefix, false for no class
114
     * @return array
115
     */
116
    public function getLinkAttributes($classprefix = 'menuitem ') {
117
        $attr = array(
118
            'href' => $this->getLink(),
119
            'title' => $this->getLabel(),
120
        );
121
        if($this->isNofollow()) $attr['rel'] = 'nofollow';
122
        if($this->getAccesskey()) {
123
            $attr['accesskey'] = $this->getAccesskey();
124
            $attr['title'] .= ' [' . $this->getAccesskey() . ']';
125
        }
126
        if($classprefix !== false) $attr['class'] = $classprefix . $this->getType();
127
128
        return $attr;
129
    }
130
131
    /**
132
     * Convenience method to create a full <a> element
133
     *
134
     * Wraps around the label and SVG image
135
     *
136
     * @param string|false $classprefix create a class from type with this prefix, false for no class
137
     * @param bool $svg add SVG icon to the link
138
     * @return string
139
     */
140
    public function asHtmlLink($classprefix = 'menuitem ', $svg = true) {
141
        $attr = buildAttributes($this->getLinkAttributes($classprefix));
142
        $html = "<a $attr>";
143
        if($svg) {
144
            $html .= '<span>' . hsc($this->getLabel()) . '</span>';
145
            $html .= inlineSVG($this->getSvg());
146
        } else {
147
            $html .= hsc($this->getLabel());
148
        }
149
        $html .= "</a>";
150
151
        return $html;
152
    }
153
154
    /**
155
     * Should this item be shown in the given context
156
     *
157
     * @param int $ctx the current context
158
     * @return bool
159
     */
160
    public function visibleInContext($ctx) {
161
        return (bool) ($ctx & $this->context);
162
    }
163
164
    /**
165
     * @return string the name of this item
166
     */
167
    public function getType() {
168
        if($this->type === '') {
169
            $this->type = strtolower(substr(strrchr(get_class($this), '\\'), 1));
170
        }
171
        return $this->type;
172
    }
173
174
    /**
175
     * @return string
176
     */
177
    public function getAccesskey() {
178
        return $this->accesskey;
179
    }
180
181
    /**
182
     * @return array
183
     */
184
    public function getParams() {
185
        return $this->params;
186
    }
187
188
    /**
189
     * @return bool
190
     */
191
    public function isNofollow() {
192
        return $this->nofollow;
193
    }
194
195
    /**
196
     * @return string
197
     */
198
    public function getSvg() {
199
        return $this->svg;
200
    }
201
202
    /**
203
     * Return this Item's settings as an array as used in tpl_get_action()
204
     *
205
     * @return array
206
     */
207
    public function getLegacyData() {
208
        return array(
209
            'accesskey' => $this->accesskey ? $this->accesskey : null,
210
            'type' => $this->type,
211
            'id' => $this->id,
212
            'method' => $this->method,
213
            'params' => $this->params,
214
            'nofollow' => $this->nofollow,
215
            'replacement' => $this->replacement
216
        );
217
    }
218
}
219