From 3c27983bf31e688c6e84d5897c5aaa8cff430918 Mon Sep 17 00:00:00 2001
From: Andreas Gohr <andi@splitbrain.org>
Date: Sat, 21 Jan 2017 12:25:40 +0100
Subject: [PATCH] Use inline SVG for Admin Plugin icons and style them via CSS

This introduces an embedSVG() function that can be used at other places.
---
 inc/common.php                  | 26 ++++++++++++++++++
 inc/html.php                    | 11 +++-----
 lib/plugins/admin.php           | 38 +++++++++-----------------
 lib/tpl/dokuwiki/css/_admin.css | 47 ++++++++++++++++++---------------
 4 files changed, 68 insertions(+), 54 deletions(-)

diff --git a/inc/common.php b/inc/common.php
index ff32fe17a..64c6941ba 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -2013,4 +2013,30 @@ function stripsourcemaps(&$text){
     $text = preg_replace('/^(\/\/|\/\*)[@#]\s+sourceMappingURL=.*?(\*\/)?$/im', '\\1\\2', $text);
 }
 
+/**
+ * Embeds the contents of a given SVG file in the current context
+ *
+ * Inlining SVGs saves on HTTP requests and more importantly allows for styling them through
+ * CSS. However it should used with small SVGs only. The $maxsize setting ensures only small
+ * files are embedded.
+ *
+ * @param string $file full path to the SVG file
+ * @param int $maxsize maximum allowed size for the SVG to be embedded
+ * @return bool true if the file was embedded, false otherwise
+ */
+function embedSVG($file, $maxsize = 1024) {
+    $file = trim($file);
+    if($file === '') return false;
+    if(!file_exists($file)) return false;
+    if(filesize($file) > $maxsize) return false;
+    if(!is_readable($file)) return false;
+    $content = file_get_contents($file);
+    $content = preg_replace('/<\?xml .*?\?>/i', '', $content);
+    $content = preg_replace('/<!DOCTYPE .*?>/i', '', $content);
+    $content = trim($content);
+    if(substr($content, 0, 5) !== '<svg ') return false;
+    echo $content;
+    return true;
+}
+
 //Setup VIM: ex: et ts=2 :
diff --git a/inc/html.php b/inc/html.php
index 4f729aa98..66eb470d8 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -2073,7 +2073,7 @@ function html_admin(){
 
         $menu[$p] = array('plugin' => $p,
                 'prompt' => $obj->getMenuText($conf['lang']),
-                'icon' => $obj->getMenuIconSvgOnly(),
+                'icon' => $obj->getMenuIcon(),
                 'sort' => $obj->getMenuSort(),
                 );
     }
@@ -2172,15 +2172,12 @@ function html_admin(){
         // output the menu
         ptln('<div class="clearer"></div>');
         print p_locale_xhtml('adminplugins');
-        ptln('<ul class="admin_plugins icon">');       
+        ptln('<ul class="admin_plugins">');
         foreach ($menu as $item) {
             if (!$item['prompt']) continue;
-            ptln('<li><div class="li admin_plugin_container">');
+            ptln('<li><div class="li">');
             ptln('<div class="admin_plugin_icon">');
-            //add icon to the item, in case of being specified
-            if(strlen($item['icon']) > 0){
-                 ptln('<img src="'.$item['icon'].'" alt="admin_icon_'.hsc($item['prompt']).'"></img>');
-            }
+            embedSVG($item['icon']);
             ptln('</div>');
             ptln('<div class="admin_plugin_name"><a href="'.wl($ID, 'do=admin&amp;page='.$item['plugin']).'">');
             ptln($item['prompt']);
diff --git a/lib/plugins/admin.php b/lib/plugins/admin.php
index fd849bd38..ed0c56f6c 100644
--- a/lib/plugins/admin.php
+++ b/lib/plugins/admin.php
@@ -32,34 +32,22 @@ class DokuWiki_Admin_Plugin extends DokuWiki_Plugin {
 
     /**
      * Return the path to the icon being displayed in the main admin menu.
-     * Default means, there won't be any icon.
+     * By default it tries to find an 'admin.svg' file in the plugin directory.
      * (Override this function for setting another image)
-     * 
-     * CAUTION:
-     * Only svg-files are allowed
-     * 
-     */
-    public function getMenuIcon(){
-        return '';
-    }
-    
-    /**
-     * Return the path to the icon being displayed in the main admin menu.
-     * In case of file mime-type not being SVG, an empty string will be returned.
-     * @return string menu icon url or empty
+     *
+     * Important: you have to return a single path, monochrome SVG icon! It has to be
+     * under 1024 bytes!
+     *
+     * We recommend icons from https://materialdesignicons.com/ or to use a matching
+     * style.
+     *
+     * @return string full path to the icon file
      */
-    public function getMenuIconSvgOnly(){
-        $returnValue = '';        
-        
-        if(strlen($this->getMenuIcon()) != '' && is_file(DOKU_INC.substr($this->getMenuIcon(), strlen(DOKU_BASE)))){
-           $calculated = mimetype(DOKU_INC.substr($this->getMenuIcon(), strlen(DOKU_BASE)), false);
-           if(is_array($calculated) && $calculated[0] == 'svg') {
-               $returnValue = $this->getMenuIcon();
-           }
-        }
-        return $returnValue;
+    public function getMenuIcon() {
+        $plugin = $this->getPluginName();
+        return DOKU_PLUGIN . $plugin . '/admin.svg';
     }
-    
+
     /**
      * Determine position in list in admin window
      * Lower values are sorted up
diff --git a/lib/tpl/dokuwiki/css/_admin.css b/lib/tpl/dokuwiki/css/_admin.css
index c2af93e2c..3cdb1542e 100644
--- a/lib/tpl/dokuwiki/css/_admin.css
+++ b/lib/tpl/dokuwiki/css/_admin.css
@@ -52,51 +52,54 @@
 /* DokuWiki additional plugins below */
 .dokuwiki ul.admin_plugins {
 	float: left;
-	width: 40%;
-}
-
-.dokuwiki ul.admin_plugins.no_icon{
-	float: left;
-	width: 40%;
-}
-
-.dokuwiki ul.admin_plugins.icon{
-	list-style-type: none;
+    list-style-type: none;
 }
 
 .dokuwiki ul.admin_plugins li {
-	pading-left: 35px;
 	margin: 0 0 0.4em 0;
 	color: inherit;
 	background: transparent none no-repeat scroll 0 0;
-}
 
-.dokuwiki ul.admin_plugins li .admin_plugin_container {
-	display: block;
-	height: 20px;
-	vertical-align: middle;
+}
+.dokuwiki ul.admin_plugins li div {
+    display: block;
+    height: 20px;
+    vertical-align: middle;
 }
 
-.dokuwiki ul.admin_plugins li .admin_plugin_container div.admin_plugin_icon {
-	width: 20px;
-	height: 20px;
+.dokuwiki ul.admin_plugins li div.admin_plugin_icon {
 	display: inline-block;
-	vertical-align: middle;
+    height: 20px;
+    width: 20px;
+}
+
+.dokuwiki ul.admin_plugins li div.admin_plugin_icon svg {
+    height: 20px;
+    width: 20px;
+}
+.dokuwiki ul.admin_plugins li div.admin_plugin_icon svg path {
+    fill: @ini_link;
+}
+
+.dokuwiki ul.admin_plugins li div.admin_plugin_name {
+    padding-left: 0.5em;
+    display: inline-block;
 }
 
+/*
 .dokuwiki ul.admin_plugins li .admin_plugin_container div.admin_plugin_icon img {
 	height: 20px;
 	width: 20px;
 }
 
 .dokuwiki ul.admin_plugins li .admin_plugin_container div.admin_plugin_name {
-	padding-left: 0.5em;
+
 	vertical-align: middle;
 	display: inline-block;
 	text-align: center;
 	margin: 0 auto;
 }
-
+*/
 
 /* DokuWiki version below */
 .dokuwiki #admin__version {
-- 
GitLab