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&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