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 * @return string 118 */ 119 public function asHtmlLink($classprefix = 'menuitem ') { 120 $attr = buildAttributes($this->getLinkAttributes($classprefix)); 121 $html = "<a $attr>"; 122 $html .= '<span>' . hsc($this->getLabel()) . '</span>'; 123 $html .= inlinSVG($this->getSvg()); 124 $html .= "</a>"; 125 126 return $html; 127 } 128 129 /** 130 * Should this item be shown in the given context 131 * 132 * @param int $ctx the current context 133 * @return bool 134 */ 135 public function visibleInContext($ctx) { 136 return (bool) ($ctx & $this->context); 137 } 138 139 /** 140 * @return string the name of this item 141 */ 142 public function getType() { 143 return $this->type; 144 } 145 146 /** 147 * @return string 148 */ 149 public function getAccesskey() { 150 return $this->accesskey; 151 } 152 153 /** 154 * @return array 155 */ 156 public function getParams() { 157 return $this->params; 158 } 159 160 /** 161 * @return bool 162 */ 163 public function isNofollow() { 164 return $this->nofollow; 165 } 166 167 /** 168 * @return string 169 */ 170 public function getSvg() { 171 return $this->svg; 172 } 173 174} 175