7.46KiB; PHP | 2020-08-25 23:29:59+02 | SLOC 231
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 1
    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_COMPAT . '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 string the tooltip title, defaults to $label */
48
    protected $title = '';
49
    /** @var int the context this titme is shown in */
50
    protected $context = self::CTX_ALL;
51
52
    /**
53
     * AbstractItem constructor.
54
     *
55
     * Sets the dynamic properties
56
     *
57
     * Children should always call the parent constructor!
58
     *
59
     * @throws \RuntimeException when the action is disabled
60
     */
61 2
    public function __construct() {
62 1
        global $ID;
63
        $this->id = $ID;
64
        $this->type = $this->getType();
65
        $this->params['do'] = $this->type;
66
67
        if(!actionOK($this->type)) throw new \RuntimeException("action disabled: {$this->type}");
68
    }
69
70
    /**
71
     * Return this item's label
72
     *
73
     * When the label property was set, it is simply returned. Otherwise, the action's type
74
     * is used to look up the translation in the main language file and, if used, the replacement
75
     * is applied.
76
     *
77
     * @return string
78
     */
79
    public function getLabel() {
80
        if($this->label !== '') return $this->label;
81
82
        /** @var array $lang */
83
        global $lang;
84
        $label = $lang['btn_' . $this->type];
85
        if(strpos($label, '%s')) {
86
            $label = sprintf($label, $this->replacement);
87
        }
88
        if($label === '') $label = '[' . $this->type . ']';
89
        return $label;
90
    }
91
92
    /**
93
     * Return this item's title
94
     *
95
     * This title should be used to display a tooltip (using the HTML title attribute). If
96
     * a title property was not explicitly set, the label will be returned.
97
     *
98
     * @return string
99
     */
100
    public function getTitle() {
101
        if($this->title === '') return $this->getLabel();
102
        return $this->title;
103
    }
104
105
    /**
106
     * Return the link this item links to
107
     *
108
     * Basically runs wl() on $id and $params. However if the ID is a hash it is used directly
109
     * as the link
110
     *
111
     * Please note that the generated URL is *not* XML escaped.
112
     *
113
     * @see wl()
114
     * @return string
115
     */
116
    public function getLink() {
117
        if($this->id && $this->id[0] == '#') {
118
            return $this->id;
119 1
        } else {
120
            return wl($this->id, $this->params, false, '&');
121
        }
122
    }
123
124
    /**
125
     * Convenience method to get the attributes for constructing an <a> element
126
     *
127
     * @see buildAttributes()
128
     * @param string|false $classprefix create a class from type with this prefix, false for no class
129
     * @return array
130
     */
131
    public function getLinkAttributes($classprefix = 'menuitem ') {
132
        $attr = array(
133
            'href' => $this->getLink(),
134
            'title' => $this->getTitle(),
135
        );
136
        if($this->isNofollow()) $attr['rel'] = 'nofollow';
137
        if($this->getAccesskey()) {
138
            $attr['accesskey'] = $this->getAccesskey();
139
            $attr['title'] .= ' [' . $this->getAccesskey() . ']';
140
        }
141
        if($classprefix !== false) $attr['class'] = $classprefix . $this->getType();
142
143
        return $attr;
144
    }
145
146
    /**
147
     * Convenience method to create a full <a> element
148
     *
149
     * Wraps around the label and SVG image
150
     *
151
     * @param string|false $classprefix create a class from type with this prefix, false for no class
152
     * @param bool $svg add SVG icon to the link
153
     * @return string
154
     */
155 1
    public function asHtmlLink($classprefix = 'menuitem ', $svg = true) {
156
        $attr = buildAttributes($this->getLinkAttributes($classprefix));
157
        $html = "<a $attr>";
158
        if($svg) {
159
            $html .= '<span>' . hsc($this->getLabel()) . '</span>';
160
            $html .= inlineSVG($this->getSvg());
161 1
        } else {
ElseExpression The method asHtmlLink uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (kritika/PHPMD) Filter like this
162
            $html .= hsc($this->getLabel());
163
        }
164
        $html .= "</a>";
165
166
        return $html;
167
    }
168
169
    /**
170
     * Convenience method to create a <button> element inside it's own form element
171
     *
172
     * Uses html_btn()
173
     *
174
     * @return string
175
     */
176
    public function asHtmlButton() {
177
        return html_btn(
178
            $this->getType(),
179
            $this->id,
180
            $this->getAccesskey(),
181
            $this->getParams(),
182
            $this->method,
183
            $this->getTitle(),
184
            $this->getLabel(),
185
            $this->getSvg()
186
        );
187
    }
188
189
    /**
190
     * Should this item be shown in the given context
191
     *
192
     * @param int $ctx the current context
193
     * @return bool
194
     */
195
    public function visibleInContext($ctx) {
196
        return (bool) ($ctx & $this->context);
197
    }
198
199
    /**
200
     * @return string the name of this item
201
     */
202
    public function getType() {
203
        if($this->type === '') {
204
            $this->type = strtolower(substr(strrchr(get_class($this), '\\'), 1));
205
        }
206
        return $this->type;
207
    }
208
209
    /**
210
     * @return string
211
     */
212
    public function getAccesskey() {
213
        return $this->accesskey;
214
    }
215
216
    /**
217
     * @return array
218
     */
219
    public function getParams() {
220
        return $this->params;
221
    }
222
223
    /**
224
     * @return bool
225
     */
226
    public function isNofollow() {
227
        return $this->nofollow;
228
    }
229
230
    /**
231
     * @return string
232
     */
233
    public function getSvg() {
234
        return $this->svg;
235
    }
236
237
    /**
238
     * Return this Item's settings as an array as used in tpl_get_action()
239
     *
240
     * @return array
241
     */
242
    public function getLegacyData() {
243
        return array(
244
            'accesskey' => $this->accesskey ?: null,
245
            'type' => $this->type,
246
            'id' => $this->id,
247
            'method' => $this->method,
248
            'params' => $this->params,
249
            'nofollow' => $this->nofollow,
250
            'replacement' => $this->replacement
251
        );
252
    }
253
}