xref: /dokuwiki/inc/Menu/Item/AbstractItem.php (revision c2b9771a2c4f3934d170bc387b7fd0137cdb2c93)
193b8c351SAndreas Gohr<?php
293b8c351SAndreas Gohr
393b8c351SAndreas Gohrnamespace dokuwiki\Menu\Item;
493b8c351SAndreas Gohr
593b8c351SAndreas Gohr/**
693b8c351SAndreas Gohr * Class AbstractItem
793b8c351SAndreas Gohr *
893b8c351SAndreas Gohr * This class defines a single Item to be displayed in one of DokuWiki's menus. Plugins
993b8c351SAndreas Gohr * can extend those menus through action plugins and add their own instances of this class,
1093b8c351SAndreas Gohr * overwriting some of its properties.
1193b8c351SAndreas Gohr *
1293b8c351SAndreas Gohr * Items may be shown multiple times in different contexts. Eg. for the default template
1393b8c351SAndreas Gohr * all menus are shown in a Dropdown list on mobile, but are split into several places on
1493b8c351SAndreas Gohr * desktop. The item's $context property can be used to hide the item depending on the current
1593b8c351SAndreas Gohr * context.
1693b8c351SAndreas Gohr *
1793b8c351SAndreas Gohr * Children usually just need to overwrite the different properties, but for complex things
1893b8c351SAndreas Gohr * the accessors may be overwritten instead.
1993b8c351SAndreas Gohr */
2093b8c351SAndreas Gohrabstract class AbstractItem {
2193b8c351SAndreas Gohr
2293b8c351SAndreas Gohr    /** menu item is to be shown on desktop screens only */
2393b8c351SAndreas Gohr    const CTX_DESKTOP = 1;
2493b8c351SAndreas Gohr    /** menu item is to be shown on mobile screens only */
2593b8c351SAndreas Gohr    const CTX_MOBILE = 2;
2693b8c351SAndreas Gohr    /** menu item is to be shown in all contexts */
2793b8c351SAndreas Gohr    const CTX_ALL = 3;
2893b8c351SAndreas Gohr
2993b8c351SAndreas Gohr    protected $type        = '';
3093b8c351SAndreas Gohr    protected $accesskey   = '';
3193b8c351SAndreas Gohr    protected $id          = '';
3293b8c351SAndreas Gohr    protected $method      = 'get';
3393b8c351SAndreas Gohr    protected $params      = array();
3493b8c351SAndreas Gohr    protected $nofollow    = true;
3593b8c351SAndreas Gohr    protected $replacement = '';
3693b8c351SAndreas Gohr    protected $category    = 'page';
37*c2b9771aSAndreas Gohr    protected $svg         = DOKU_INC . 'lib/images/menu/00-default_checkbox-blank-circle-outline.svg';
3893b8c351SAndreas Gohr    protected $label       = '';
3993b8c351SAndreas Gohr    protected $context     = self::CTX_ALL;
4093b8c351SAndreas Gohr
4193b8c351SAndreas Gohr    public function __construct() {
4293b8c351SAndreas Gohr        global $ID;
4393b8c351SAndreas Gohr        $this->id = $ID;
4493b8c351SAndreas Gohr        $this->type = strtolower(substr(strrchr(get_class($this), '\\'), 1));
4593b8c351SAndreas Gohr        $this->params['do'] = $this->type;
4693b8c351SAndreas Gohr
4793b8c351SAndreas Gohr        if(!actionOK($this->type)) throw new \RuntimeException("action disabled: {$this->type}");
4893b8c351SAndreas Gohr    }
4993b8c351SAndreas Gohr
5093b8c351SAndreas Gohr    /**
5193b8c351SAndreas Gohr     * Return this item's label
5293b8c351SAndreas Gohr     *
5393b8c351SAndreas Gohr     * When the label property was set, it is simply returned. Otherwise, the action's type
5493b8c351SAndreas Gohr     * is used to look up the translation in the main language file and, if used, the replacement
5593b8c351SAndreas Gohr     * is applied.
5693b8c351SAndreas Gohr     *
5793b8c351SAndreas Gohr     * @return string
5893b8c351SAndreas Gohr     */
5993b8c351SAndreas Gohr    public function getLabel() {
6093b8c351SAndreas Gohr        if($this->label !== '') return $this->label;
6193b8c351SAndreas Gohr
6293b8c351SAndreas Gohr        /** @var array $lang */
6393b8c351SAndreas Gohr        global $lang;
6493b8c351SAndreas Gohr        $label = $lang['btn_' . $this->type];
6593b8c351SAndreas Gohr        if(strpos($label, '%s')) {
6693b8c351SAndreas Gohr            $label = sprintf($label, $this->replacement);
6793b8c351SAndreas Gohr        }
6893b8c351SAndreas Gohr        if($label === '') $label = '[' . $this->type . ']';
6993b8c351SAndreas Gohr        return $label;
7093b8c351SAndreas Gohr    }
7193b8c351SAndreas Gohr
7293b8c351SAndreas Gohr    /**
7393b8c351SAndreas Gohr     * Return the link this item links to
7493b8c351SAndreas Gohr     *
7593b8c351SAndreas Gohr     * Basically runs wl() on $id and $params. However if the ID is a hash it is used directly
7693b8c351SAndreas Gohr     * as the link
7793b8c351SAndreas Gohr     *
7893b8c351SAndreas Gohr     * @see wl()
7993b8c351SAndreas Gohr     * @return string
8093b8c351SAndreas Gohr     */
8193b8c351SAndreas Gohr    public function getLink() {
8293b8c351SAndreas Gohr        if($this->id[0] == '#') {
8393b8c351SAndreas Gohr            return $this->id;
8493b8c351SAndreas Gohr        } else {
8593b8c351SAndreas Gohr            return wl($this->id, $this->params);
8693b8c351SAndreas Gohr        }
8793b8c351SAndreas Gohr    }
8893b8c351SAndreas Gohr
8993b8c351SAndreas Gohr    /**
9093b8c351SAndreas Gohr     * Convenience method to get the attributes for constructing an <a> element
9193b8c351SAndreas Gohr     *
9293b8c351SAndreas Gohr     * @see buildAttributes()
9393b8c351SAndreas Gohr     * @param string|false $classprefix create a class from type with this prefix, false for no class
9493b8c351SAndreas Gohr     * @return array
9593b8c351SAndreas Gohr     */
9693b8c351SAndreas Gohr    public function getLinkAttributes($classprefix = 'menuitem ') {
9793b8c351SAndreas Gohr        $attr = array(
9893b8c351SAndreas Gohr            'href' => $this->getLink(),
9993b8c351SAndreas Gohr            'title' => $this->getLabel(),
10093b8c351SAndreas Gohr        );
10193b8c351SAndreas Gohr        if($this->isNofollow()) $attr['rel'] = 'nofollow';
10293b8c351SAndreas Gohr        if($this->getAccesskey()) {
10393b8c351SAndreas Gohr            $attr['accesskey'] = $this->getAccesskey();
10493b8c351SAndreas Gohr            $attr['title'] .= ' [' . $this->getAccesskey() . ']';
10593b8c351SAndreas Gohr        }
10693b8c351SAndreas Gohr        if($classprefix !== false) $attr['class'] = $classprefix . $this->getType();
10793b8c351SAndreas Gohr
10893b8c351SAndreas Gohr        return $attr;
10993b8c351SAndreas Gohr    }
11093b8c351SAndreas Gohr
11193b8c351SAndreas Gohr    /**
11293b8c351SAndreas Gohr     * Convenience method to create a full <a> element
11393b8c351SAndreas Gohr     *
11493b8c351SAndreas Gohr     * Wraps around the label and SVG image
11593b8c351SAndreas Gohr     *
11693b8c351SAndreas Gohr     * @param string|false $classprefix create a class from type with this prefix, false for no class
11793b8c351SAndreas Gohr     * @return string
11893b8c351SAndreas Gohr     */
11993b8c351SAndreas Gohr    public function asHtmlLink($classprefix = 'menuitem ') {
12093b8c351SAndreas Gohr        $attr = buildAttributes($this->getLinkAttributes($classprefix));
12193b8c351SAndreas Gohr        $html = "<a $attr>";
12293b8c351SAndreas Gohr        $html .= '<span>' . hsc($this->getLabel()) . '</span>';
12393b8c351SAndreas Gohr        $html .= inlinSVG($this->getSvg());
12493b8c351SAndreas Gohr        $html .= "</a>";
12593b8c351SAndreas Gohr
12693b8c351SAndreas Gohr        return $html;
12793b8c351SAndreas Gohr    }
12893b8c351SAndreas Gohr
12993b8c351SAndreas Gohr    /**
13093b8c351SAndreas Gohr     * Should this item be shown in the given context
13193b8c351SAndreas Gohr     *
13293b8c351SAndreas Gohr     * @param int $ctx the current context
13393b8c351SAndreas Gohr     * @return bool
13493b8c351SAndreas Gohr     */
13593b8c351SAndreas Gohr    public function visibleInContext($ctx) {
13693b8c351SAndreas Gohr        return (bool) ($ctx & $this->context);
13793b8c351SAndreas Gohr    }
13893b8c351SAndreas Gohr
13993b8c351SAndreas Gohr    /**
14093b8c351SAndreas Gohr     * @return string the name of this item
14193b8c351SAndreas Gohr     */
14293b8c351SAndreas Gohr    public function getType() {
14393b8c351SAndreas Gohr        return $this->type;
14493b8c351SAndreas Gohr    }
14593b8c351SAndreas Gohr
14693b8c351SAndreas Gohr    /**
14793b8c351SAndreas Gohr     * @return string
14893b8c351SAndreas Gohr     */
14993b8c351SAndreas Gohr    public function getAccesskey() {
15093b8c351SAndreas Gohr        return $this->accesskey;
15193b8c351SAndreas Gohr    }
15293b8c351SAndreas Gohr
15393b8c351SAndreas Gohr    /**
15493b8c351SAndreas Gohr     * @return array
15593b8c351SAndreas Gohr     */
15693b8c351SAndreas Gohr    public function getParams() {
15793b8c351SAndreas Gohr        return $this->params;
15893b8c351SAndreas Gohr    }
15993b8c351SAndreas Gohr
16093b8c351SAndreas Gohr    /**
16193b8c351SAndreas Gohr     * @return bool
16293b8c351SAndreas Gohr     */
16393b8c351SAndreas Gohr    public function isNofollow() {
16493b8c351SAndreas Gohr        return $this->nofollow;
16593b8c351SAndreas Gohr    }
16693b8c351SAndreas Gohr
16793b8c351SAndreas Gohr    /**
16893b8c351SAndreas Gohr     * @return string
16993b8c351SAndreas Gohr     */
17093b8c351SAndreas Gohr    public function getSvg() {
17193b8c351SAndreas Gohr        return $this->svg;
17293b8c351SAndreas Gohr    }
17393b8c351SAndreas Gohr
17493b8c351SAndreas Gohr}
175