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