1<?php 2 3namespace 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 */ 20abstract 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 protected $type = ''; 30 protected $accesskey = ''; 31 protected $id = ''; 32 protected $method = 'get'; 33 protected $params = array(); 34 protected $nofollow = true; 35 protected $replacement = ''; 36 protected $svg = DOKU_INC . 'lib/images/menu/00-default_checkbox-blank-circle-outline.svg'; 37 protected $label = ''; 38 protected $context = self::CTX_ALL; 39 40 public function __construct() { 41 global $ID; 42 $this->id = $ID; 43 $this->type = strtolower(substr(strrchr(get_class($this), '\\'), 1)); 44 $this->params['do'] = $this->type; 45 46 if(!actionOK($this->type)) throw new \RuntimeException("action disabled: {$this->type}"); 47 } 48 49 /** 50 * Return this item's label 51 * 52 * When the label property was set, it is simply returned. Otherwise, the action's type 53 * is used to look up the translation in the main language file and, if used, the replacement 54 * is applied. 55 * 56 * @return string 57 */ 58 public function getLabel() { 59 if($this->label !== '') return $this->label; 60 61 /** @var array $lang */ 62 global $lang; 63 $label = $lang['btn_' . $this->type]; 64 if(strpos($label, '%s')) { 65 $label = sprintf($label, $this->replacement); 66 } 67 if($label === '') $label = '[' . $this->type . ']'; 68 return $label; 69 } 70 71 /** 72 * Return the link this item links to 73 * 74 * Basically runs wl() on $id and $params. However if the ID is a hash it is used directly 75 * as the link 76 * 77 * @see wl() 78 * @return string 79 */ 80 public function getLink() { 81 if($this->id[0] == '#') { 82 return $this->id; 83 } else { 84 return wl($this->id, $this->params); 85 } 86 } 87 88 /** 89 * Convenience method to get the attributes for constructing an <a> element 90 * 91 * @see buildAttributes() 92 * @param string|false $classprefix create a class from type with this prefix, false for no class 93 * @return array 94 */ 95 public function getLinkAttributes($classprefix = 'menuitem ') { 96 $attr = array( 97 'href' => $this->getLink(), 98 'title' => $this->getLabel(), 99 ); 100 if($this->isNofollow()) $attr['rel'] = 'nofollow'; 101 if($this->getAccesskey()) { 102 $attr['accesskey'] = $this->getAccesskey(); 103 $attr['title'] .= ' [' . $this->getAccesskey() . ']'; 104 } 105 if($classprefix !== false) $attr['class'] = $classprefix . $this->getType(); 106 107 return $attr; 108 } 109 110 /** 111 * Convenience method to create a full <a> element 112 * 113 * Wraps around the label and SVG image 114 * 115 * @param string|false $classprefix create a class from type with this prefix, false for no class 116 * @param bool $svg add SVG icon to the link 117 * @return string 118 */ 119 public function asHtmlLink($classprefix = 'menuitem ', $svg = true) { 120 $attr = buildAttributes($this->getLinkAttributes($classprefix)); 121 $html = "<a $attr>"; 122 if($svg) { 123 $html .= '<span>' . hsc($this->getLabel()) . '</span>'; 124 $html .= inlineSVG($this->getSvg()); 125 } else { 126 $html .= hsc($this->getLabel()); 127 } 128 $html .= "</a>"; 129 130 return $html; 131 } 132 133 /** 134 * Should this item be shown in the given context 135 * 136 * @param int $ctx the current context 137 * @return bool 138 */ 139 public function visibleInContext($ctx) { 140 return (bool) ($ctx & $this->context); 141 } 142 143 /** 144 * @return string the name of this item 145 */ 146 public function getType() { 147 return $this->type; 148 } 149 150 /** 151 * @return string 152 */ 153 public function getAccesskey() { 154 return $this->accesskey; 155 } 156 157 /** 158 * @return array 159 */ 160 public function getParams() { 161 return $this->params; 162 } 163 164 /** 165 * @return bool 166 */ 167 public function isNofollow() { 168 return $this->nofollow; 169 } 170 171 /** 172 * @return string 173 */ 174 public function getSvg() { 175 return $this->svg; 176 } 177 178} 179