aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/inc/Menu/Item
diff options
context:
space:
mode:
authorAndreas Gohr <andi@splitbrain.org>2017-05-19 15:08:35 +0200
committerAndreas Gohr <andi@splitbrain.org>2017-05-19 17:02:13 +0200
commit93b8c351fad5246a7a91c86418f15bec833dc99f (patch)
tree5ad78fe9f2a8639f8c2e095690506972b76aa326 /inc/Menu/Item
parent08ee0671938eeed96f27428c408e3877a01120c9 (diff)
downloaddokuwiki-93b8c351fad5246a7a91c86418f15bec833dc99f.tar.gz
dokuwiki-93b8c351fad5246a7a91c86418f15bec833dc99f.zip
beginning of a complete refactoring of the menues
This is an attempt to: * get rid of the super long, complex functions in in/template.php * make it easy for plugin authors to add their own items to any of our menus, regardless of the used template * continue the progress to make use of SVG in the menues This takes a similar approach as my actionrefactor branch. Originially I thought both refactorings could be done in one, merging the functionality of DokuWiki actions and the menu items. However I couldn't make it work. So instead we have two separate but similar things. Maybe they can converge later on.
Diffstat (limited to 'inc/Menu/Item')
-rw-r--r--inc/Menu/Item/AbstractItem.php174
-rw-r--r--inc/Menu/Item/Admin.php19
-rw-r--r--inc/Menu/Item/Back.php22
-rw-r--r--inc/Menu/Item/Backlink.php9
-rw-r--r--inc/Menu/Item/Edit.php59
-rw-r--r--inc/Menu/Item/ImgBackto.php19
-rw-r--r--inc/Menu/Item/Index.php22
-rw-r--r--inc/Menu/Item/Login.php23
-rw-r--r--inc/Menu/Item/Media.php16
-rw-r--r--inc/Menu/Item/MediaManager.php27
-rw-r--r--inc/Menu/Item/Profile.php17
-rw-r--r--inc/Menu/Item/Recent.php15
-rw-r--r--inc/Menu/Item/Register.php19
-rw-r--r--inc/Menu/Item/Resendpwd.php19
-rw-r--r--inc/Menu/Item/Revert.php21
-rw-r--r--inc/Menu/Item/Revisions.php16
-rw-r--r--inc/Menu/Item/Subscribe.php19
-rw-r--r--inc/Menu/Item/Top.php13
18 files changed, 529 insertions, 0 deletions
diff --git a/inc/Menu/Item/AbstractItem.php b/inc/Menu/Item/AbstractItem.php
new file mode 100644
index 000000000..c999cb919
--- /dev/null
+++ b/inc/Menu/Item/AbstractItem.php
@@ -0,0 +1,174 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+/**
+ * Class AbstractItem
+ *
+ * This class defines a single Item to be displayed in one of DokuWiki's menus. Plugins
+ * can extend those menus through action plugins and add their own instances of this class,
+ * overwriting some of its properties.
+ *
+ * Items may be shown multiple times in different contexts. Eg. for the default template
+ * all menus are shown in a Dropdown list on mobile, but are split into several places on
+ * desktop. The item's $context property can be used to hide the item depending on the current
+ * context.
+ *
+ * Children usually just need to overwrite the different properties, but for complex things
+ * the accessors may be overwritten instead.
+ */
+abstract class AbstractItem {
+
+ /** menu item is to be shown on desktop screens only */
+ const CTX_DESKTOP = 1;
+ /** menu item is to be shown on mobile screens only */
+ const CTX_MOBILE = 2;
+ /** menu item is to be shown in all contexts */
+ const CTX_ALL = 3;
+
+ protected $type = '';
+ protected $accesskey = '';
+ protected $id = '';
+ protected $method = 'get';
+ protected $params = array();
+ protected $nofollow = true;
+ protected $replacement = '';
+ protected $category = 'page';
+ protected $svg = DOKU_BASE . 'lib/images/menu/00-default_checkbox-blank-circle-outline.svg';
+ protected $label = '';
+ protected $context = self::CTX_ALL;
+
+ public function __construct() {
+ global $ID;
+ $this->id = $ID;
+ $this->type = strtolower(substr(strrchr(get_class($this), '\\'), 1));
+ $this->params['do'] = $this->type;
+
+ if(!actionOK($this->type)) throw new \RuntimeException("action disabled: {$this->type}");
+ }
+
+ /**
+ * Return this item's label
+ *
+ * When the label property was set, it is simply returned. Otherwise, the action's type
+ * is used to look up the translation in the main language file and, if used, the replacement
+ * is applied.
+ *
+ * @return string
+ */
+ public function getLabel() {
+ if($this->label !== '') return $this->label;
+
+ /** @var array $lang */
+ global $lang;
+ $label = $lang['btn_' . $this->type];
+ if(strpos($label, '%s')) {
+ $label = sprintf($label, $this->replacement);
+ }
+ if($label === '') $label = '[' . $this->type . ']';
+ return $label;
+ }
+
+ /**
+ * Return the link this item links to
+ *
+ * Basically runs wl() on $id and $params. However if the ID is a hash it is used directly
+ * as the link
+ *
+ * @see wl()
+ * @return string
+ */
+ public function getLink() {
+ if($this->id[0] == '#') {
+ return $this->id;
+ } else {
+ return wl($this->id, $this->params);
+ }
+ }
+
+ /**
+ * Convenience method to get the attributes for constructing an <a> element
+ *
+ * @see buildAttributes()
+ * @param string|false $classprefix create a class from type with this prefix, false for no class
+ * @return array
+ */
+ public function getLinkAttributes($classprefix = 'menuitem ') {
+ $attr = array(
+ 'href' => $this->getLink(),
+ 'title' => $this->getLabel(),
+ );
+ if($this->isNofollow()) $attr['rel'] = 'nofollow';
+ if($this->getAccesskey()) {
+ $attr['accesskey'] = $this->getAccesskey();
+ $attr['title'] .= ' [' . $this->getAccesskey() . ']';
+ }
+ if($classprefix !== false) $attr['class'] = $classprefix . $this->getType();
+
+ return $attr;
+ }
+
+ /**
+ * Convenience method to create a full <a> element
+ *
+ * Wraps around the label and SVG image
+ *
+ * @param string|false $classprefix create a class from type with this prefix, false for no class
+ * @return string
+ */
+ public function asHtmlLink($classprefix = 'menuitem ') {
+ $attr = buildAttributes($this->getLinkAttributes($classprefix));
+ $html = "<a $attr>";
+ $html .= '<span>' . hsc($this->getLabel()) . '</span>';
+ $html .= inlinSVG($this->getSvg());
+ $html .= "</a>";
+
+ return $html;
+ }
+
+ /**
+ * Should this item be shown in the given context
+ *
+ * @param int $ctx the current context
+ * @return bool
+ */
+ public function visibleInContext($ctx) {
+ return (bool) ($ctx & $this->context);
+ }
+
+ /**
+ * @return string the name of this item
+ */
+ public function getType() {
+ return $this->type;
+ }
+
+ /**
+ * @return string
+ */
+ public function getAccesskey() {
+ return $this->accesskey;
+ }
+
+ /**
+ * @return array
+ */
+ public function getParams() {
+ return $this->params;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isNofollow() {
+ return $this->nofollow;
+ }
+
+ /**
+ * @return string
+ */
+ public function getSvg() {
+ return $this->svg;
+ }
+
+}
diff --git a/inc/Menu/Item/Admin.php b/inc/Menu/Item/Admin.php
new file mode 100644
index 000000000..e4135c6d4
--- /dev/null
+++ b/inc/Menu/Item/Admin.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Admin extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $INFO;
+ parent::__construct();
+
+ $this->category = 'user';
+
+ if(!$INFO['ismanager']) {
+ throw new \RuntimeException("admin is for managers only");
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/Back.php b/inc/Menu/Item/Back.php
new file mode 100644
index 000000000..708bdc587
--- /dev/null
+++ b/inc/Menu/Item/Back.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Back extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $ID;
+ parent::__construct();
+
+ $parent = tpl_getparent($ID);
+ if(!$parent) {
+ throw new \RuntimeException("No parent for back action");
+ }
+
+ $this->id = $parent;
+ $this->params = array('do' => '');
+ $this->accesskey = 'b';
+ }
+
+}
diff --git a/inc/Menu/Item/Backlink.php b/inc/Menu/Item/Backlink.php
new file mode 100644
index 000000000..5d4901753
--- /dev/null
+++ b/inc/Menu/Item/Backlink.php
@@ -0,0 +1,9 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Backlink extends AbstractItem {
+
+ protected $svg = DOKU_BASE . 'lib/images/menu/08-backlink_link-variant.svg';
+
+}
diff --git a/inc/Menu/Item/Edit.php b/inc/Menu/Item/Edit.php
new file mode 100644
index 000000000..45a05eb1e
--- /dev/null
+++ b/inc/Menu/Item/Edit.php
@@ -0,0 +1,59 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Edit extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $ACT;
+ global $INFO;
+ global $REV;
+
+ parent::__construct();
+
+ if($ACT == 'show' || $ACT == 'search') {
+ $this->method = 'post';
+ if($INFO['writable']) {
+ $this->accesskey = 'e';
+ if(!empty($INFO['draft'])) {
+ $this->type = 'draft';
+ $this->params['do'] = 'draft';
+ } else {
+ $this->params['rev'] = $REV;
+ if(!$INFO['exists']) {
+ $this->type = 'create';
+ }
+ }
+ } else {
+ if(!actionOK($this->type)) throw new \RuntimeException("action disabled: source");
+ $params['rev'] = $REV;
+ $this->type = 'source';
+ $this->accesskey = 'v';
+ }
+ } else {
+ $this->params = array('do' => '');
+ $this->type = 'show';
+ $this->accesskey = 'v';
+ }
+
+ $this->svg = $this->setIcon();
+ }
+
+ /**
+ * change the icon according to what type the edit button has
+ */
+ protected function setIcon() {
+ $icons = array(
+ 'edit' => '01-edit_pencil.svg',
+ 'create' => '02-create_pencil.svg',
+ 'draft' => '03-draft_android-studio.svg',
+ 'show' => '04-show_file-document.svg',
+ 'source' => '05-source_file-xml.svg',
+ );
+ if(isset($icons[$this->type])) {
+ $this->svg = DOKU_BASE . 'lib/images/menu/' . $icons[$this->type];
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/ImgBackto.php b/inc/Menu/Item/ImgBackto.php
new file mode 100644
index 000000000..79fda098a
--- /dev/null
+++ b/inc/Menu/Item/ImgBackto.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class ImgBackto extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $ID;
+ parent::__construct();
+
+ $this->svg = DOKU_BASE . 'lib/images/menu/12-back_arrow-left.svg';
+ $this->type = 'img_backto';
+ $this->params = array();
+ $this->accesskey = 'b';
+ $this->replacement = $ID;
+ }
+
+}
diff --git a/inc/Menu/Item/Index.php b/inc/Menu/Item/Index.php
new file mode 100644
index 000000000..33908f073
--- /dev/null
+++ b/inc/Menu/Item/Index.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Index extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ parent::__construct();
+
+ $this->category = 'site';
+ $this->accesskey = 'x';
+
+ // allow searchbots to get to the sitemap from the homepage (when dokuwiki isn't providing a sitemap.xml)
+ global $conf;
+ global $ID;
+ if($conf['start'] == $ID && !$conf['sitemap']) {
+ $this->nofollow = false;
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/Login.php b/inc/Menu/Item/Login.php
new file mode 100644
index 000000000..224296fe6
--- /dev/null
+++ b/inc/Menu/Item/Login.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Login extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $INPUT;
+ parent::__construct();
+
+ $this->category = 'user';
+ $this->params['sectok'] = getSecurityToken();
+ if($INPUT->server->has('REMOTE_USER')) {
+ if(!actionOK('logout')) {
+ throw new \RuntimeException("logout disabled");
+ }
+ $this->params['do'] = 'logout';
+ $this->type = 'logout';
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/Media.php b/inc/Menu/Item/Media.php
new file mode 100644
index 000000000..f5b89d908
--- /dev/null
+++ b/inc/Menu/Item/Media.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Media extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $ID;
+ parent::__construct();
+
+ $this->category = 'site';
+ $params['ns'] = getNS($ID);
+ }
+
+}
diff --git a/inc/Menu/Item/MediaManager.php b/inc/Menu/Item/MediaManager.php
new file mode 100644
index 000000000..e8a44e0f3
--- /dev/null
+++ b/inc/Menu/Item/MediaManager.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class MediaManager extends AbstractItem {
+
+ protected $svg = DOKU_BASE . 'lib/images/menu/11-mediamanager_folder-image.svg';
+
+ /** @inheritdoc */
+ public function __construct() {
+ parent::__construct();
+
+ // View image in media manager
+ global $IMG;
+ $imgNS = getNS($IMG);
+ $authNS = auth_quickaclcheck("$imgNS:*");
+ if($authNS < AUTH_UPLOAD) {
+ throw new \RuntimeException("media manager link only with upload permissions");
+ }
+ $this->params = array(
+ 'ns' => $imgNS,
+ 'image' => $IMG,
+ 'do' => 'media'
+ );
+ }
+
+}
diff --git a/inc/Menu/Item/Profile.php b/inc/Menu/Item/Profile.php
new file mode 100644
index 000000000..7fe8e7502
--- /dev/null
+++ b/inc/Menu/Item/Profile.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Profile extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $INPUT;
+ parent::__construct();
+
+ if(!$INPUT->server->str('REMOTE_USER')) {
+ throw new \RuntimeException("profile is only for logged in users");
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/Recent.php b/inc/Menu/Item/Recent.php
new file mode 100644
index 000000000..fd38404ef
--- /dev/null
+++ b/inc/Menu/Item/Recent.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Recent extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ parent::__construct();
+
+ $this->category = 'site';
+ $this->accesskey = 'r';
+ }
+
+}
diff --git a/inc/Menu/Item/Register.php b/inc/Menu/Item/Register.php
new file mode 100644
index 000000000..7fb76e8d5
--- /dev/null
+++ b/inc/Menu/Item/Register.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Register extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $INPUT;
+ parent::__construct();
+
+ $this->category = 'user';
+
+ if($INPUT->server->str('REMOTE_USER')) {
+ throw new \RuntimeException("no register when already logged in");
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/Resendpwd.php b/inc/Menu/Item/Resendpwd.php
new file mode 100644
index 000000000..080052483
--- /dev/null
+++ b/inc/Menu/Item/Resendpwd.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Resendpwd extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $INPUT;
+ parent::__construct();
+
+ $this->category = 'user';
+
+ if($INPUT->server->str('REMOTE_USER')) {
+ throw new \RuntimeException("no resendpwd when already logged in");
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/Revert.php b/inc/Menu/Item/Revert.php
new file mode 100644
index 000000000..d1fc8f34c
--- /dev/null
+++ b/inc/Menu/Item/Revert.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Revert extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $REV;
+ global $INFO;
+ parent::__construct();
+
+ if(!$INFO['ismanager'] || !$REV || !$INFO['writable']) {
+ throw new \RuntimeException('revert not available');
+ }
+ $this->params['rev'] = $REV;
+ $this->params['sectok'] = getSecurityToken();
+ $this->svg = DOKU_BASE . 'lib/images/menu/06-revert_replay.svg';
+ }
+
+}
diff --git a/inc/Menu/Item/Revisions.php b/inc/Menu/Item/Revisions.php
new file mode 100644
index 000000000..415eaddd7
--- /dev/null
+++ b/inc/Menu/Item/Revisions.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Revisions extends AbstractItem {
+
+ /** @inheritdoc */
+ public function __construct() {
+ parent::__construct();
+
+ $this->type = 'revs';
+ $this->params['do'] = 'revs';
+ $this->svg = DOKU_BASE . 'lib/images/menu/07-revisions_history.svg';
+ }
+
+}
diff --git a/inc/Menu/Item/Subscribe.php b/inc/Menu/Item/Subscribe.php
new file mode 100644
index 000000000..b2c2492f9
--- /dev/null
+++ b/inc/Menu/Item/Subscribe.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Subscribe extends AbstractItem {
+
+ protected $svg = DOKU_BASE . 'lib/images/menu/09-subscribe_email-outline.svg';
+
+ /** @inheritdoc */
+ public function __construct() {
+ global $INPUT;
+ parent::__construct();
+
+ if(!$INPUT->server->str('REMOTE_USER')) {
+ throw new \RuntimeException("subscribe is only for logged in users");
+ }
+ }
+
+}
diff --git a/inc/Menu/Item/Top.php b/inc/Menu/Item/Top.php
new file mode 100644
index 000000000..7d67fd4ba
--- /dev/null
+++ b/inc/Menu/Item/Top.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace dokuwiki\Menu\Item;
+
+class Top extends AbstractItem {
+
+ protected $svg = DOKU_BASE . 'lib/images/menu/10-top_arrow-up.svg';
+ protected $accesskey = 't';
+ protected $params = array('do' => '');
+ protected $id = '#dokuwiki__top';
+ protected $context = self::CTX_DESKTOP;
+
+}