xref: /dokuwiki/inc/Ui/Admin.php (revision 85a452e2ffd285848ad7625af094650bb1877624)
10470c28fSAndreas Gohr<?php
2e2d055f5SAndreas Gohr
30470c28fSAndreas Gohrnamespace dokuwiki\Ui;
40470c28fSAndreas Gohr
579a2d784SGerrit Uitslaguse dokuwiki\Extension\AdminPlugin;
6e2d055f5SAndreas Gohruse dokuwiki\Extension\PluginInterface;
72d85e841SAndreas Gohruse dokuwiki\Utf8\Sort;
82d85e841SAndreas Gohr
90470c28fSAndreas Gohr/**
100470c28fSAndreas Gohr * Class Admin
110470c28fSAndreas Gohr *
120470c28fSAndreas Gohr * Displays the Admin screen
130470c28fSAndreas Gohr *
140470c28fSAndreas Gohr * @package dokuwiki\Ui
150470c28fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org>
160470c28fSAndreas Gohr * @author Håkan Sandell <hakan.sandell@home.se>
170470c28fSAndreas Gohr */
18e2d055f5SAndreas Gohrclass Admin extends Ui
19e2d055f5SAndreas Gohr{
20e2d055f5SAndreas Gohr    protected $forAdmins = ['usermanager', 'acl', 'extension', 'config', 'logviewer', 'styling'];
21e2d055f5SAndreas Gohr    protected $forManagers = ['revert', 'popularity'];
2264cdf779SAndreas Gohr    /** @var array[] */
230470c28fSAndreas Gohr    protected $menu;
240470c28fSAndreas Gohr
250470c28fSAndreas Gohr    /**
260470c28fSAndreas Gohr     * Display the UI element
270470c28fSAndreas Gohr     *
280470c28fSAndreas Gohr     * @return void
290470c28fSAndreas Gohr     */
30e2d055f5SAndreas Gohr    public function show()
31e2d055f5SAndreas Gohr    {
320470c28fSAndreas Gohr        $this->menu = $this->getPluginList();
335d2e38cbSAndreas Gohr        echo '<div class="ui-admin">';
340470c28fSAndreas Gohr        echo p_locale_xhtml('admin');
35052e1c84SAndreas Gohr
3664cdf779SAndreas Gohr        $this->showMenu('admin');
3764cdf779SAndreas Gohr        $this->showMenu('manager');
38052e1c84SAndreas Gohr        $this->showSecurityCheck();
390470c28fSAndreas Gohr        $this->showVersion();
4064cdf779SAndreas Gohr        $this->showMenu('other');
41713faa94SAndreas Gohr        echo '</div>';
420470c28fSAndreas Gohr    }
430470c28fSAndreas Gohr
440470c28fSAndreas Gohr    /**
4564cdf779SAndreas Gohr     * Show the given menu of available plugins
4664cdf779SAndreas Gohr     *
4764cdf779SAndreas Gohr     * @param string $type admin|manager|other
480470c28fSAndreas Gohr     */
49e2d055f5SAndreas Gohr    protected function showMenu($type)
50e2d055f5SAndreas Gohr    {
5164cdf779SAndreas Gohr        if (!$this->menu[$type]) return;
520470c28fSAndreas Gohr
5364cdf779SAndreas Gohr        if ($type === 'other') {
540470c28fSAndreas Gohr            echo p_locale_xhtml('adminplugins');
5564cdf779SAndreas Gohr            $class = 'admin_plugins';
5664cdf779SAndreas Gohr        } else {
5764cdf779SAndreas Gohr            $class = 'admin_tasks';
5864cdf779SAndreas Gohr        }
5964cdf779SAndreas Gohr
6064cdf779SAndreas Gohr        echo "<ul class=\"$class\">";
6164cdf779SAndreas Gohr        foreach ($this->menu[$type] as $item) {
620470c28fSAndreas Gohr            $this->showMenuItem($item);
630470c28fSAndreas Gohr        }
640470c28fSAndreas Gohr        echo '</ul>';
650470c28fSAndreas Gohr    }
660470c28fSAndreas Gohr
670470c28fSAndreas Gohr    /**
680470c28fSAndreas Gohr     * Display the DokuWiki version
690470c28fSAndreas Gohr     */
70e2d055f5SAndreas Gohr    protected function showVersion()
71e2d055f5SAndreas Gohr    {
72*85a452e2SAndreas Gohr        global $conf;
73*85a452e2SAndreas Gohr
74*85a452e2SAndreas Gohr        $runtime = getRuntimeVersions();
75*85a452e2SAndreas Gohr        $runtime['php'] .= ' ' . $runtime['sapi'];
76*85a452e2SAndreas Gohr        unset($runtime['sapi']);
77*85a452e2SAndreas Gohr
780470c28fSAndreas Gohr        echo '<div id="admin__version">';
790470c28fSAndreas Gohr        echo getVersion();
8079f150bdSAndreas Gohr        echo '<br>';
81*85a452e2SAndreas Gohr        echo hsc($conf['template']). ' ' . hsc($conf['syntax']);
82*85a452e2SAndreas Gohr        echo '<br>';
83*85a452e2SAndreas Gohr        echo implode('<br>', array_map(hsc(...), array_values($runtime)));
840470c28fSAndreas Gohr        echo '</div>';
850470c28fSAndreas Gohr    }
860470c28fSAndreas Gohr
870470c28fSAndreas Gohr    /**
880470c28fSAndreas Gohr     * data security check
890470c28fSAndreas Gohr     *
900470c28fSAndreas Gohr     * simple check if the 'savedir' is relative and accessible when appended to DOKU_URL
910470c28fSAndreas Gohr     *
920470c28fSAndreas Gohr     * it verifies either:
930470c28fSAndreas Gohr     *   'savedir' has been moved elsewhere, or
940470c28fSAndreas Gohr     *   has protection to prevent the webserver serving files from it
95052e1c84SAndreas Gohr     *
96052e1c84SAndreas Gohr     * The actual check is carried out via JavaScript. See behaviour.js
970470c28fSAndreas Gohr     */
98e2d055f5SAndreas Gohr    protected function showSecurityCheck()
99e2d055f5SAndreas Gohr    {
1000470c28fSAndreas Gohr        global $conf;
1016c16a3a9Sfiwswe        if (!str_starts_with($conf['savedir'], './')) return;
10264159a61SAndreas Gohr        $img = DOKU_URL . $conf['savedir'] .
10364159a61SAndreas Gohr            '/dont-panic-if-you-see-this-in-your-logs-it-means-your-directory-permissions-are-correct.png';
104d3f829c2SAndreas Gohr        echo '<div id="security__check" data-src="' . $img . '"></div>';
1050470c28fSAndreas Gohr    }
1060470c28fSAndreas Gohr
1070470c28fSAndreas Gohr    /**
1080470c28fSAndreas Gohr     * Display a single Admin menu item
1090470c28fSAndreas Gohr     *
1100470c28fSAndreas Gohr     * @param array $item
1110470c28fSAndreas Gohr     */
112e2d055f5SAndreas Gohr    protected function showMenuItem($item)
113e2d055f5SAndreas Gohr    {
1140470c28fSAndreas Gohr        global $ID;
1150470c28fSAndreas Gohr        if (blank($item['prompt'])) return;
1160470c28fSAndreas Gohr        echo '<li><div class="li">';
117220b8a20SAndreas Gohr        echo '<a href="' . wl($ID, 'do=admin&amp;page=' . $item['plugin']) . '">';
118220b8a20SAndreas Gohr        echo '<span class="icon">';
1194cd2074fSAndreas Gohr        echo inlineSVG($item['icon']);
1200470c28fSAndreas Gohr        echo '</span>';
121220b8a20SAndreas Gohr        echo '<span class="prompt">';
1220470c28fSAndreas Gohr        echo $item['prompt'];
123220b8a20SAndreas Gohr        echo '</span>';
1240470c28fSAndreas Gohr        echo '</a>';
1250470c28fSAndreas Gohr        echo '</div></li>';
1260470c28fSAndreas Gohr    }
1270470c28fSAndreas Gohr
1280470c28fSAndreas Gohr    /**
1290470c28fSAndreas Gohr     * Build  list of admin functions from the plugins that handle them
1300470c28fSAndreas Gohr     *
1310470c28fSAndreas Gohr     * Checks the current permissions to decide on manager or admin plugins
1320470c28fSAndreas Gohr     *
1330470c28fSAndreas Gohr     * @return array list of plugins with their properties
1340470c28fSAndreas Gohr     */
135e2d055f5SAndreas Gohr    protected function getPluginList()
136e2d055f5SAndreas Gohr    {
1370470c28fSAndreas Gohr        global $conf;
1380470c28fSAndreas Gohr
1390470c28fSAndreas Gohr        $pluginlist = plugin_list('admin');
14064cdf779SAndreas Gohr        $menu = ['admin' => [], 'manager' => [], 'other' => []];
14164cdf779SAndreas Gohr
1420470c28fSAndreas Gohr        foreach ($pluginlist as $p) {
14379a2d784SGerrit Uitslag            /** @var AdminPlugin $obj */
144e2d055f5SAndreas Gohr            if (!($obj = plugin_load('admin', $p)) instanceof PluginInterface) continue;
1450470c28fSAndreas Gohr
1460470c28fSAndreas Gohr            // check permissions
14764cdf779SAndreas Gohr            if (!$obj->isAccessibleByCurrentUser()) continue;
14831afae8aSAndreas Gohr            if (!$obj->showInMenu()) continue;
1490470c28fSAndreas Gohr
15064cdf779SAndreas Gohr            if (in_array($p, $this->forAdmins, true)) {
15164cdf779SAndreas Gohr                $type = 'admin';
15264cdf779SAndreas Gohr            } elseif (in_array($p, $this->forManagers, true)) {
15364cdf779SAndreas Gohr                $type = 'manager';
15464cdf779SAndreas Gohr            } else {
15564cdf779SAndreas Gohr                $type = 'other';
15664cdf779SAndreas Gohr            }
15764cdf779SAndreas Gohr
158e2d055f5SAndreas Gohr            $menu[$type][$p] = [
1590470c28fSAndreas Gohr                'plugin' => $p,
1600470c28fSAndreas Gohr                'prompt' => $obj->getMenuText($conf['lang']),
1610470c28fSAndreas Gohr                'icon' => $obj->getMenuIcon(),
162e2d055f5SAndreas Gohr                'sort' => $obj->getMenuSort()
163e2d055f5SAndreas Gohr            ];
1640470c28fSAndreas Gohr        }
1650470c28fSAndreas Gohr
1660470c28fSAndreas Gohr        // sort by name, then sort
167093fe67eSAndreas Gohr        uasort($menu['admin'], $this->menuSort(...));
168093fe67eSAndreas Gohr        uasort($menu['manager'], $this->menuSort(...));
169093fe67eSAndreas Gohr        uasort($menu['other'], $this->menuSort(...));
1700470c28fSAndreas Gohr
1710470c28fSAndreas Gohr        return $menu;
1720470c28fSAndreas Gohr    }
1730470c28fSAndreas Gohr
17464cdf779SAndreas Gohr    /**
17564cdf779SAndreas Gohr     * Custom sorting for admin menu
17664cdf779SAndreas Gohr     *
17764cdf779SAndreas Gohr     * We sort alphabetically first, then by sort value
17864cdf779SAndreas Gohr     *
17964cdf779SAndreas Gohr     * @param array $a
18064cdf779SAndreas Gohr     * @param array $b
18164cdf779SAndreas Gohr     * @return int
18264cdf779SAndreas Gohr     */
183e2d055f5SAndreas Gohr    protected function menuSort($a, $b)
184e2d055f5SAndreas Gohr    {
1852d85e841SAndreas Gohr        $strcmp = Sort::strcmp($a['prompt'], $b['prompt']);
18664cdf779SAndreas Gohr        if ($strcmp != 0) return $strcmp;
187e2d055f5SAndreas Gohr        return $a['sort'] <=> $b['sort'];
18864cdf779SAndreas Gohr    }
1890470c28fSAndreas Gohr}
190