xref: /dokuwiki/inc/Menu/Item/AbstractItem.php (revision 93b8c351fad5246a7a91c86418f15bec833dc99f)
1*93b8c351SAndreas Gohr<?php
2*93b8c351SAndreas Gohr
3*93b8c351SAndreas Gohrnamespace dokuwiki\Menu\Item;
4*93b8c351SAndreas Gohr
5*93b8c351SAndreas Gohr/**
6*93b8c351SAndreas Gohr * Class AbstractItem
7*93b8c351SAndreas Gohr *
8*93b8c351SAndreas Gohr * This class defines a single Item to be displayed in one of DokuWiki's menus. Plugins
9*93b8c351SAndreas Gohr * can extend those menus through action plugins and add their own instances of this class,
10*93b8c351SAndreas Gohr * overwriting some of its properties.
11*93b8c351SAndreas Gohr *
12*93b8c351SAndreas Gohr * Items may be shown multiple times in different contexts. Eg. for the default template
13*93b8c351SAndreas Gohr * all menus are shown in a Dropdown list on mobile, but are split into several places on
14*93b8c351SAndreas Gohr * desktop. The item's $context property can be used to hide the item depending on the current
15*93b8c351SAndreas Gohr * context.
16*93b8c351SAndreas Gohr *
17*93b8c351SAndreas Gohr * Children usually just need to overwrite the different properties, but for complex things
18*93b8c351SAndreas Gohr * the accessors may be overwritten instead.
19*93b8c351SAndreas Gohr */
20*93b8c351SAndreas Gohrabstract class AbstractItem {
21*93b8c351SAndreas Gohr
22*93b8c351SAndreas Gohr    /** menu item is to be shown on desktop screens only */
23*93b8c351SAndreas Gohr    const CTX_DESKTOP = 1;
24*93b8c351SAndreas Gohr    /** menu item is to be shown on mobile screens only */
25*93b8c351SAndreas Gohr    const CTX_MOBILE = 2;
26*93b8c351SAndreas Gohr    /** menu item is to be shown in all contexts */
27*93b8c351SAndreas Gohr    const CTX_ALL = 3;
28*93b8c351SAndreas Gohr
29*93b8c351SAndreas Gohr    protected $type        = '';
30*93b8c351SAndreas Gohr    protected $accesskey   = '';
31*93b8c351SAndreas Gohr    protected $id          = '';
32*93b8c351SAndreas Gohr    protected $method      = 'get';
33*93b8c351SAndreas Gohr    protected $params      = array();
34*93b8c351SAndreas Gohr    protected $nofollow    = true;
35*93b8c351SAndreas Gohr    protected $replacement = '';
36*93b8c351SAndreas Gohr    protected $category    = 'page';
37*93b8c351SAndreas Gohr    protected $svg         = DOKU_BASE . 'lib/images/menu/00-default_checkbox-blank-circle-outline.svg';
38*93b8c351SAndreas Gohr    protected $label       = '';
39*93b8c351SAndreas Gohr    protected $context     = self::CTX_ALL;
40*93b8c351SAndreas Gohr
41*93b8c351SAndreas Gohr    public function __construct() {
42*93b8c351SAndreas Gohr        global $ID;
43*93b8c351SAndreas Gohr        $this->id = $ID;
44*93b8c351SAndreas Gohr        $this->type = strtolower(substr(strrchr(get_class($this), '\\'), 1));
45*93b8c351SAndreas Gohr        $this->params['do'] = $this->type;
46*93b8c351SAndreas Gohr
47*93b8c351SAndreas Gohr        if(!actionOK($this->type)) throw new \RuntimeException("action disabled: {$this->type}");
48*93b8c351SAndreas Gohr    }
49*93b8c351SAndreas Gohr
50*93b8c351SAndreas Gohr    /**
51*93b8c351SAndreas Gohr     * Return this item's label
52*93b8c351SAndreas Gohr     *
53*93b8c351SAndreas Gohr     * When the label property was set, it is simply returned. Otherwise, the action's type
54*93b8c351SAndreas Gohr     * is used to look up the translation in the main language file and, if used, the replacement
55*93b8c351SAndreas Gohr     * is applied.
56*93b8c351SAndreas Gohr     *
57*93b8c351SAndreas Gohr     * @return string
58*93b8c351SAndreas Gohr     */
59*93b8c351SAndreas Gohr    public function getLabel() {
60*93b8c351SAndreas Gohr        if($this->label !== '') return $this->label;
61*93b8c351SAndreas Gohr
62*93b8c351SAndreas Gohr        /** @var array $lang */
63*93b8c351SAndreas Gohr        global $lang;
64*93b8c351SAndreas Gohr        $label = $lang['btn_' . $this->type];
65*93b8c351SAndreas Gohr        if(strpos($label, '%s')) {
66*93b8c351SAndreas Gohr            $label = sprintf($label, $this->replacement);
67*93b8c351SAndreas Gohr        }
68*93b8c351SAndreas Gohr        if($label === '') $label = '[' . $this->type . ']';
69*93b8c351SAndreas Gohr        return $label;
70*93b8c351SAndreas Gohr    }
71*93b8c351SAndreas Gohr
72*93b8c351SAndreas Gohr    /**
73*93b8c351SAndreas Gohr     * Return the link this item links to
74*93b8c351SAndreas Gohr     *
75*93b8c351SAndreas Gohr     * Basically runs wl() on $id and $params. However if the ID is a hash it is used directly
76*93b8c351SAndreas Gohr     * as the link
77*93b8c351SAndreas Gohr     *
78*93b8c351SAndreas Gohr     * @see wl()
79*93b8c351SAndreas Gohr     * @return string
80*93b8c351SAndreas Gohr     */
81*93b8c351SAndreas Gohr    public function getLink() {
82*93b8c351SAndreas Gohr        if($this->id[0] == '#') {
83*93b8c351SAndreas Gohr            return $this->id;
84*93b8c351SAndreas Gohr        } else {
85*93b8c351SAndreas Gohr            return wl($this->id, $this->params);
86*93b8c351SAndreas Gohr        }
87*93b8c351SAndreas Gohr    }
88*93b8c351SAndreas Gohr
89*93b8c351SAndreas Gohr    /**
90*93b8c351SAndreas Gohr     * Convenience method to get the attributes for constructing an <a> element
91*93b8c351SAndreas Gohr     *
92*93b8c351SAndreas Gohr     * @see buildAttributes()
93*93b8c351SAndreas Gohr     * @param string|false $classprefix create a class from type with this prefix, false for no class
94*93b8c351SAndreas Gohr     * @return array
95*93b8c351SAndreas Gohr     */
96*93b8c351SAndreas Gohr    public function getLinkAttributes($classprefix = 'menuitem ') {
97*93b8c351SAndreas Gohr        $attr = array(
98*93b8c351SAndreas Gohr            'href' => $this->getLink(),
99*93b8c351SAndreas Gohr            'title' => $this->getLabel(),
100*93b8c351SAndreas Gohr        );
101*93b8c351SAndreas Gohr        if($this->isNofollow()) $attr['rel'] = 'nofollow';
102*93b8c351SAndreas Gohr        if($this->getAccesskey()) {
103*93b8c351SAndreas Gohr            $attr['accesskey'] = $this->getAccesskey();
104*93b8c351SAndreas Gohr            $attr['title'] .= ' [' . $this->getAccesskey() . ']';
105*93b8c351SAndreas Gohr        }
106*93b8c351SAndreas Gohr        if($classprefix !== false) $attr['class'] = $classprefix . $this->getType();
107*93b8c351SAndreas Gohr
108*93b8c351SAndreas Gohr        return $attr;
109*93b8c351SAndreas Gohr    }
110*93b8c351SAndreas Gohr
111*93b8c351SAndreas Gohr    /**
112*93b8c351SAndreas Gohr     * Convenience method to create a full <a> element
113*93b8c351SAndreas Gohr     *
114*93b8c351SAndreas Gohr     * Wraps around the label and SVG image
115*93b8c351SAndreas Gohr     *
116*93b8c351SAndreas Gohr     * @param string|false $classprefix create a class from type with this prefix, false for no class
117*93b8c351SAndreas Gohr     * @return string
118*93b8c351SAndreas Gohr     */
119*93b8c351SAndreas Gohr    public function asHtmlLink($classprefix = 'menuitem ') {
120*93b8c351SAndreas Gohr        $attr = buildAttributes($this->getLinkAttributes($classprefix));
121*93b8c351SAndreas Gohr        $html = "<a $attr>";
122*93b8c351SAndreas Gohr        $html .= '<span>' . hsc($this->getLabel()) . '</span>';
123*93b8c351SAndreas Gohr        $html .= inlinSVG($this->getSvg());
124*93b8c351SAndreas Gohr        $html .= "</a>";
125*93b8c351SAndreas Gohr
126*93b8c351SAndreas Gohr        return $html;
127*93b8c351SAndreas Gohr    }
128*93b8c351SAndreas Gohr
129*93b8c351SAndreas Gohr    /**
130*93b8c351SAndreas Gohr     * Should this item be shown in the given context
131*93b8c351SAndreas Gohr     *
132*93b8c351SAndreas Gohr     * @param int $ctx the current context
133*93b8c351SAndreas Gohr     * @return bool
134*93b8c351SAndreas Gohr     */
135*93b8c351SAndreas Gohr    public function visibleInContext($ctx) {
136*93b8c351SAndreas Gohr        return (bool) ($ctx & $this->context);
137*93b8c351SAndreas Gohr    }
138*93b8c351SAndreas Gohr
139*93b8c351SAndreas Gohr    /**
140*93b8c351SAndreas Gohr     * @return string the name of this item
141*93b8c351SAndreas Gohr     */
142*93b8c351SAndreas Gohr    public function getType() {
143*93b8c351SAndreas Gohr        return $this->type;
144*93b8c351SAndreas Gohr    }
145*93b8c351SAndreas Gohr
146*93b8c351SAndreas Gohr    /**
147*93b8c351SAndreas Gohr     * @return string
148*93b8c351SAndreas Gohr     */
149*93b8c351SAndreas Gohr    public function getAccesskey() {
150*93b8c351SAndreas Gohr        return $this->accesskey;
151*93b8c351SAndreas Gohr    }
152*93b8c351SAndreas Gohr
153*93b8c351SAndreas Gohr    /**
154*93b8c351SAndreas Gohr     * @return array
155*93b8c351SAndreas Gohr     */
156*93b8c351SAndreas Gohr    public function getParams() {
157*93b8c351SAndreas Gohr        return $this->params;
158*93b8c351SAndreas Gohr    }
159*93b8c351SAndreas Gohr
160*93b8c351SAndreas Gohr    /**
161*93b8c351SAndreas Gohr     * @return bool
162*93b8c351SAndreas Gohr     */
163*93b8c351SAndreas Gohr    public function isNofollow() {
164*93b8c351SAndreas Gohr        return $this->nofollow;
165*93b8c351SAndreas Gohr    }
166*93b8c351SAndreas Gohr
167*93b8c351SAndreas Gohr    /**
168*93b8c351SAndreas Gohr     * @return string
169*93b8c351SAndreas Gohr     */
170*93b8c351SAndreas Gohr    public function getSvg() {
171*93b8c351SAndreas Gohr        return $this->svg;
172*93b8c351SAndreas Gohr    }
173*93b8c351SAndreas Gohr
174*93b8c351SAndreas Gohr}
175