14fd6a1d7SAndreas Gohr<?php 24fd6a1d7SAndreas Gohr 34fd6a1d7SAndreas Gohrnamespace dokuwiki\plugin\extension; 44fd6a1d7SAndreas Gohr 54fd6a1d7SAndreas Gohrclass GuiExtension extends Gui 64fd6a1d7SAndreas Gohr{ 74fd6a1d7SAndreas Gohr const THUMB_WIDTH = 120; 84fd6a1d7SAndreas Gohr const THUMB_HEIGHT = 70; 94fd6a1d7SAndreas Gohr 104fd6a1d7SAndreas Gohr 114fd6a1d7SAndreas Gohr protected Extension $extension; 124fd6a1d7SAndreas Gohr 134fd6a1d7SAndreas Gohr public function __construct(Extension $extension) 144fd6a1d7SAndreas Gohr { 154fd6a1d7SAndreas Gohr parent::__construct(); 164fd6a1d7SAndreas Gohr $this->extension = $extension; 174fd6a1d7SAndreas Gohr } 184fd6a1d7SAndreas Gohr 194fd6a1d7SAndreas Gohr 204fd6a1d7SAndreas Gohr public function render() 214fd6a1d7SAndreas Gohr { 224fd6a1d7SAndreas Gohr 234fd6a1d7SAndreas Gohr $classes = $this->getClasses(); 244fd6a1d7SAndreas Gohr 254fd6a1d7SAndreas Gohr $html = "<section class=\"$classes\">"; 26*20db0ca9SAndreas Gohr 27*20db0ca9SAndreas Gohr $html .= '<div class="screenshot">'; 284fd6a1d7SAndreas Gohr $html .= $this->thumbnail(); 29*20db0ca9SAndreas Gohr $html .= '</div>'; 30*20db0ca9SAndreas Gohr 31*20db0ca9SAndreas Gohr $html.= '<h2>'; 32*20db0ca9SAndreas Gohr $html .= '<bdi>' . hsc($this->extension->getDisplayName()) . '</bdi>'; 33*20db0ca9SAndreas Gohr if ($this->extension->isBundled()) { 34*20db0ca9SAndreas Gohr $html .= ' <span class="version">' . hsc('<' . $this->getLang('status_bundled') . '>') . '</span>'; 35*20db0ca9SAndreas Gohr } elseif ($this->extension->getInstalledVersion()) { 36*20db0ca9SAndreas Gohr $html .= ' <span class="version">' . hsc($this->extension->getInstalledVersion()) . '</span>'; 37*20db0ca9SAndreas Gohr } 384fd6a1d7SAndreas Gohr $html .= $this->popularity(); 39*20db0ca9SAndreas Gohr $html .= '</h2>'; 40*20db0ca9SAndreas Gohr 41*20db0ca9SAndreas Gohr $html .= '<div class="main">'; 42*20db0ca9SAndreas Gohr $html .= '<h3>' . $this->author() . '</h3>'; 43*20db0ca9SAndreas Gohr $html .= '<p>' . hsc($this->extension->getDescription()) . '</p>'; 44*20db0ca9SAndreas Gohr $html .= '</div>'; 45*20db0ca9SAndreas Gohr 46*20db0ca9SAndreas Gohr 47*20db0ca9SAndreas Gohr 48*20db0ca9SAndreas Gohr 49*20db0ca9SAndreas Gohr $html .= '<div class="details">'; 504fd6a1d7SAndreas Gohr $html .= $this->notices(); 514fd6a1d7SAndreas Gohr $html .= $this->mainLinks(); 524fd6a1d7SAndreas Gohr $html .= $this->details(); 53*20db0ca9SAndreas Gohr $html .= '</div>'; 54*20db0ca9SAndreas Gohr 55*20db0ca9SAndreas Gohr // show the available version if there is one 56*20db0ca9SAndreas Gohr if ($this->extension->getDownloadURL() && $this->extension->getLastUpdate()) { 57*20db0ca9SAndreas Gohr $html .= ' <div class="version">' . $this->getLang('available_version') . ' ' . 58*20db0ca9SAndreas Gohr hsc($this->extension->getLastUpdate()) . '</div>'; 59*20db0ca9SAndreas Gohr } 60*20db0ca9SAndreas Gohr 61*20db0ca9SAndreas Gohr $html .= '<div class="actions">'; 624fd6a1d7SAndreas Gohr $html .= $this->actions(); 63*20db0ca9SAndreas Gohr $html .= '</div>'; 644fd6a1d7SAndreas Gohr 654fd6a1d7SAndreas Gohr 664fd6a1d7SAndreas Gohr $html .= '</section>'; 674fd6a1d7SAndreas Gohr 684fd6a1d7SAndreas Gohr return $html; 694fd6a1d7SAndreas Gohr } 704fd6a1d7SAndreas Gohr 714fd6a1d7SAndreas Gohr // region sections 724fd6a1d7SAndreas Gohr 734fd6a1d7SAndreas Gohr /** 744fd6a1d7SAndreas Gohr * Get the link and image tag for the screenshot/thumbnail 754fd6a1d7SAndreas Gohr * 764fd6a1d7SAndreas Gohr * @return string The HTML code 774fd6a1d7SAndreas Gohr */ 784fd6a1d7SAndreas Gohr protected function thumbnail() 794fd6a1d7SAndreas Gohr { 804fd6a1d7SAndreas Gohr $screen = $this->extension->getScreenshotURL(); 814fd6a1d7SAndreas Gohr $thumb = $this->extension->getThumbnailURL(); 824fd6a1d7SAndreas Gohr 834fd6a1d7SAndreas Gohr $link = []; 844fd6a1d7SAndreas Gohr $img = [ 854fd6a1d7SAndreas Gohr 'width' => self::THUMB_WIDTH, 864fd6a1d7SAndreas Gohr 'height' => self::THUMB_HEIGHT, 874fd6a1d7SAndreas Gohr 'alt' => '', 884fd6a1d7SAndreas Gohr ]; 894fd6a1d7SAndreas Gohr 904fd6a1d7SAndreas Gohr if ($screen) { 914fd6a1d7SAndreas Gohr $link = [ 924fd6a1d7SAndreas Gohr 'href' => $screen, 934fd6a1d7SAndreas Gohr 'target' => '_blank', 944fd6a1d7SAndreas Gohr 'class' => 'extension_screenshot', 954fd6a1d7SAndreas Gohr 'title' => sprintf($this->getLang('screenshot'), $this->extension->getDisplayName()) 964fd6a1d7SAndreas Gohr ]; 974fd6a1d7SAndreas Gohr 984fd6a1d7SAndreas Gohr $img['src'] = $thumb; 994fd6a1d7SAndreas Gohr $img['alt'] = $link['title']; 1004fd6a1d7SAndreas Gohr } elseif ($this->extension->isTemplate()) { 1014fd6a1d7SAndreas Gohr $img['src'] = DOKU_BASE . 'lib/plugins/extension/images/template.png'; 1024fd6a1d7SAndreas Gohr } else { 1034fd6a1d7SAndreas Gohr $img['src'] = DOKU_BASE . 'lib/plugins/extension/images/plugin.png'; 1044fd6a1d7SAndreas Gohr } 1054fd6a1d7SAndreas Gohr 106*20db0ca9SAndreas Gohr $html = ''; 1074fd6a1d7SAndreas Gohr if ($link) $html .= '<a ' . buildAttributes($link) . '>'; 1084fd6a1d7SAndreas Gohr $html .= '<img ' . buildAttributes($img) . ' />'; 1094fd6a1d7SAndreas Gohr if ($link) $html .= '</a>'; 1104fd6a1d7SAndreas Gohr 1114fd6a1d7SAndreas Gohr return $html; 1124fd6a1d7SAndreas Gohr 1134fd6a1d7SAndreas Gohr } 1144fd6a1d7SAndreas Gohr 1154fd6a1d7SAndreas Gohr /** 1164fd6a1d7SAndreas Gohr * The main information about the extension 1174fd6a1d7SAndreas Gohr * 1184fd6a1d7SAndreas Gohr * @return string 1194fd6a1d7SAndreas Gohr */ 1204fd6a1d7SAndreas Gohr protected function info() 1214fd6a1d7SAndreas Gohr { 1224fd6a1d7SAndreas Gohr 1234fd6a1d7SAndreas Gohr 1244fd6a1d7SAndreas Gohr 1254fd6a1d7SAndreas Gohr return $html; 1264fd6a1d7SAndreas Gohr } 1274fd6a1d7SAndreas Gohr 1284fd6a1d7SAndreas Gohr /** 1294fd6a1d7SAndreas Gohr * Display the available notices for the extension 1304fd6a1d7SAndreas Gohr * 1314fd6a1d7SAndreas Gohr * @return string 1324fd6a1d7SAndreas Gohr */ 1334fd6a1d7SAndreas Gohr protected function notices() 1344fd6a1d7SAndreas Gohr { 1354fd6a1d7SAndreas Gohr $notices = Notice::list($this->extension); 1364fd6a1d7SAndreas Gohr 1374fd6a1d7SAndreas Gohr $html = ''; 1384fd6a1d7SAndreas Gohr foreach ($notices as $type => $messages) { 1394fd6a1d7SAndreas Gohr foreach ($messages as $message) { 1404fd6a1d7SAndreas Gohr $message = hsc($message); 1414fd6a1d7SAndreas Gohr $message = preg_replace('/`([^`]+)`/', '<bdi>$1</bdi>', $message); 1424fd6a1d7SAndreas Gohr $html .= '<div class="msg ' . $type . '">' . $message . '</div>'; 1434fd6a1d7SAndreas Gohr } 1444fd6a1d7SAndreas Gohr } 1454fd6a1d7SAndreas Gohr return $html; 1464fd6a1d7SAndreas Gohr } 1474fd6a1d7SAndreas Gohr 1484fd6a1d7SAndreas Gohr /** 1494fd6a1d7SAndreas Gohr * Generate the link bar HTML code 1504fd6a1d7SAndreas Gohr * 1514fd6a1d7SAndreas Gohr * @return string The HTML code 1524fd6a1d7SAndreas Gohr */ 1534fd6a1d7SAndreas Gohr public function mainLinks() 1544fd6a1d7SAndreas Gohr { 1554fd6a1d7SAndreas Gohr $html = '<div class="linkbar">'; 1564fd6a1d7SAndreas Gohr 1574fd6a1d7SAndreas Gohr 1584fd6a1d7SAndreas Gohr $homepage = $this->extension->getURL(); 1594fd6a1d7SAndreas Gohr if ($homepage) { 1604fd6a1d7SAndreas Gohr $params = $this->prepareLinkAttributes($homepage, 'homepage'); 1614fd6a1d7SAndreas Gohr $html .= ' <a ' . buildAttributes($params, true) . '>' . $this->getLang('homepage_link') . '</a>'; 1624fd6a1d7SAndreas Gohr } 1634fd6a1d7SAndreas Gohr 1644fd6a1d7SAndreas Gohr $bugtracker = $this->extension->getBugtrackerURL(); 1654fd6a1d7SAndreas Gohr if ($bugtracker) { 1664fd6a1d7SAndreas Gohr $params = $this->prepareLinkAttributes($bugtracker, 'bugs'); 1674fd6a1d7SAndreas Gohr $html .= ' <a ' . buildAttributes($params, true) . '>' . $this->getLang('bugs_features') . '</a>'; 1684fd6a1d7SAndreas Gohr } 1694fd6a1d7SAndreas Gohr 1704fd6a1d7SAndreas Gohr if ($this->extension->getDonationURL()) { 1714fd6a1d7SAndreas Gohr $params = $this->prepareLinkAttributes($this->extension->getDonationURL(), 'donate'); 1724fd6a1d7SAndreas Gohr $html .= ' <a ' . buildAttributes($params, true) . '>' . $this->getLang('donate_action') . '</a>'; 1734fd6a1d7SAndreas Gohr } 1744fd6a1d7SAndreas Gohr 1754fd6a1d7SAndreas Gohr 1764fd6a1d7SAndreas Gohr $html .= '</div>'; 1774fd6a1d7SAndreas Gohr 1784fd6a1d7SAndreas Gohr return $html; 1794fd6a1d7SAndreas Gohr } 1804fd6a1d7SAndreas Gohr 1814fd6a1d7SAndreas Gohr /** 1824fd6a1d7SAndreas Gohr * Create the details section 1834fd6a1d7SAndreas Gohr * 1844fd6a1d7SAndreas Gohr * @return string 1854fd6a1d7SAndreas Gohr */ 1864fd6a1d7SAndreas Gohr protected function details() 1874fd6a1d7SAndreas Gohr { 1884fd6a1d7SAndreas Gohr $html = '<details>'; 1894fd6a1d7SAndreas Gohr $html .= '<summary>' . 'FIXME label' . '</summary>'; 1904fd6a1d7SAndreas Gohr 1914fd6a1d7SAndreas Gohr 1924fd6a1d7SAndreas Gohr $default = $this->getLang('unknown'); 1934fd6a1d7SAndreas Gohr $list = []; 1944fd6a1d7SAndreas Gohr 1954fd6a1d7SAndreas Gohr if (!$this->extension->isBundled()) { 1964fd6a1d7SAndreas Gohr $list['downloadurl'] = $this->shortlink($this->extension->getDownloadURL(), 'download', $default); 1974fd6a1d7SAndreas Gohr $list['repository'] = $this->shortlink($this->extension->getSourcerepoURL(), 'repo', $default); 1984fd6a1d7SAndreas Gohr } 1994fd6a1d7SAndreas Gohr 2004fd6a1d7SAndreas Gohr if ($this->extension->isInstalled()) { 2014fd6a1d7SAndreas Gohr if ($this->extension->isBundled()) { 2024fd6a1d7SAndreas Gohr $list['installed_version'] = $this->getLang('status_bundled'); 2034fd6a1d7SAndreas Gohr } else { 2044fd6a1d7SAndreas Gohr if ($this->extension->getInstalledVersion()) { 2054fd6a1d7SAndreas Gohr $list['installed_version'] = hsc($this->extension->getInstalledVersion()); 2064fd6a1d7SAndreas Gohr } 2074fd6a1d7SAndreas Gohr if (!$this->extension->isBundled()) { 2084fd6a1d7SAndreas Gohr $updateDate = $this->extension->getManager()->getLastUpdate(); 2094fd6a1d7SAndreas Gohr $list['install_date'] = $updateDate ? hsc($updateDate) : $default; 2104fd6a1d7SAndreas Gohr } 2114fd6a1d7SAndreas Gohr } 2124fd6a1d7SAndreas Gohr } 2134fd6a1d7SAndreas Gohr 2144fd6a1d7SAndreas Gohr if (!$this->extension->isInstalled() || $this->extension->isUpdateAvailable()) { 2154fd6a1d7SAndreas Gohr $list['available_version'] = $this->extension->getLastUpdate() 2164fd6a1d7SAndreas Gohr ? hsc($this->extension->getLastUpdate()) 2174fd6a1d7SAndreas Gohr : $default; 2184fd6a1d7SAndreas Gohr } 2194fd6a1d7SAndreas Gohr 2204fd6a1d7SAndreas Gohr 2214fd6a1d7SAndreas Gohr if (!$this->extension->isBundled() && $this->extension->getCompatibleVersions()) { 2224fd6a1d7SAndreas Gohr $list['compatible'] = join(', ', array_map( 2234fd6a1d7SAndreas Gohr function ($date, $version) { 2244fd6a1d7SAndreas Gohr return '<bdi>' . $version['label'] . ' (' . $date . ')</bdi>'; 2254fd6a1d7SAndreas Gohr }, 2264fd6a1d7SAndreas Gohr array_keys($this->extension->getCompatibleVersions()), 2274fd6a1d7SAndreas Gohr array_values($this->extension->getCompatibleVersions()) 2284fd6a1d7SAndreas Gohr )); 2294fd6a1d7SAndreas Gohr } 2304fd6a1d7SAndreas Gohr 2314fd6a1d7SAndreas Gohr $tags = $this->extension->getTags(); 2324fd6a1d7SAndreas Gohr if ($tags) { 2334fd6a1d7SAndreas Gohr $list['tags'] = join(', ', array_map(function ($tag) { 2344fd6a1d7SAndreas Gohr $url = $this->tabURL('search', ['q' => 'tag:' . $tag]); 2354fd6a1d7SAndreas Gohr return '<bdi><a href="' . $url . '">' . hsc($tag) . '</a></bdi>'; 2364fd6a1d7SAndreas Gohr }, $tags)); 2374fd6a1d7SAndreas Gohr } 2384fd6a1d7SAndreas Gohr 2394fd6a1d7SAndreas Gohr if ($this->extension->getDependencyList()) { 2404fd6a1d7SAndreas Gohr $list['depends'] = $this->linkExtensions($this->extension->getDependencyList()); 2414fd6a1d7SAndreas Gohr } 2424fd6a1d7SAndreas Gohr 2434fd6a1d7SAndreas Gohr if ($this->extension->getSimilarList()) { 2444fd6a1d7SAndreas Gohr $list['similar'] = $this->linkExtensions($this->extension->getSimilarList()); 2454fd6a1d7SAndreas Gohr } 2464fd6a1d7SAndreas Gohr 2474fd6a1d7SAndreas Gohr if ($this->extension->getConflictList()) { 2484fd6a1d7SAndreas Gohr $list['conflicts'] = $this->linkExtensions($this->extension->getConflictList()); 2494fd6a1d7SAndreas Gohr } 2504fd6a1d7SAndreas Gohr 251*20db0ca9SAndreas Gohr $html .= '<dl>'; 2524fd6a1d7SAndreas Gohr foreach ($list as $key => $value) { 2534fd6a1d7SAndreas Gohr $html .= '<dt>' . $this->getLang($key) . '</dt>'; 2544fd6a1d7SAndreas Gohr $html .= '<dd>' . $value . '</dd>'; 2554fd6a1d7SAndreas Gohr } 256*20db0ca9SAndreas Gohr $html .= '</dl>'; 2574fd6a1d7SAndreas Gohr 2584fd6a1d7SAndreas Gohr $html .= '</details>'; 2594fd6a1d7SAndreas Gohr return $html; 2604fd6a1d7SAndreas Gohr } 2614fd6a1d7SAndreas Gohr 2624fd6a1d7SAndreas Gohr /** 2634fd6a1d7SAndreas Gohr * Generate a link to the author of the extension 2644fd6a1d7SAndreas Gohr * 2654fd6a1d7SAndreas Gohr * @return string The HTML code of the link 2664fd6a1d7SAndreas Gohr */ 2674fd6a1d7SAndreas Gohr protected function author() 2684fd6a1d7SAndreas Gohr { 2694fd6a1d7SAndreas Gohr if (!$this->extension->getAuthor()) { 2704fd6a1d7SAndreas Gohr return '<em class="author">' . $this->getLang('unknown_author') . '</em>'; 2714fd6a1d7SAndreas Gohr } 2724fd6a1d7SAndreas Gohr 2734fd6a1d7SAndreas Gohr $mailid = $this->extension->getEmailID(); 2744fd6a1d7SAndreas Gohr if ($mailid) { 2754fd6a1d7SAndreas Gohr $url = $this->tabURL('search', ['q' => 'authorid:' . $mailid]); 2764fd6a1d7SAndreas Gohr $html = '<a href="' . $url . '" class="author" title="' . $this->getLang('author_hint') . '" >' . 2774fd6a1d7SAndreas Gohr '<img src="//www.gravatar.com/avatar/' . $mailid . 2784fd6a1d7SAndreas Gohr '?s=60&d=mm" width="20" height="20" alt="" /> ' . 2794fd6a1d7SAndreas Gohr hsc($this->extension->getAuthor()) . '</a>'; 2804fd6a1d7SAndreas Gohr } else { 2814fd6a1d7SAndreas Gohr $html = '<span class="author">' . hsc($this->extension->getAuthor()) . '</span>'; 2824fd6a1d7SAndreas Gohr } 2834fd6a1d7SAndreas Gohr return '<bdi>' . $html . '</bdi>'; 2844fd6a1d7SAndreas Gohr } 2854fd6a1d7SAndreas Gohr 2864fd6a1d7SAndreas Gohr /** 2874fd6a1d7SAndreas Gohr * The popularity bar 2884fd6a1d7SAndreas Gohr * 2894fd6a1d7SAndreas Gohr * @return string 2904fd6a1d7SAndreas Gohr */ 2914fd6a1d7SAndreas Gohr protected function popularity() 2924fd6a1d7SAndreas Gohr { 2934fd6a1d7SAndreas Gohr $popularity = $this->extension->getPopularity(); 2944fd6a1d7SAndreas Gohr if (!$popularity) return ''; 2954fd6a1d7SAndreas Gohr if ($this->extension->isBundled()) return ''; 2964fd6a1d7SAndreas Gohr 2974fd6a1d7SAndreas Gohr $popularityText = sprintf($this->getLang('popularity'), round($popularity * 100, 2)); 2984fd6a1d7SAndreas Gohr return '<div class="popularity" title="' . $popularityText . '">' . 2994fd6a1d7SAndreas Gohr '<div style="width: ' . ($popularity * 100) . '%;">' . 3004fd6a1d7SAndreas Gohr '<span class="a11y">' . $popularityText . '</span>' . 3014fd6a1d7SAndreas Gohr '</div></div>'; 3024fd6a1d7SAndreas Gohr 3034fd6a1d7SAndreas Gohr } 3044fd6a1d7SAndreas Gohr 3054fd6a1d7SAndreas Gohr protected function actions() 3064fd6a1d7SAndreas Gohr { 3074fd6a1d7SAndreas Gohr global $conf; 3084fd6a1d7SAndreas Gohr 3094fd6a1d7SAndreas Gohr $html = ''; 3104fd6a1d7SAndreas Gohr $actions = []; 3114fd6a1d7SAndreas Gohr $errors = []; 3124fd6a1d7SAndreas Gohr 3134fd6a1d7SAndreas Gohr // gather available actions and possible errors to show 3144fd6a1d7SAndreas Gohr try { 3154fd6a1d7SAndreas Gohr Installer::ensurePermissions($this->extension); 3164fd6a1d7SAndreas Gohr 3174fd6a1d7SAndreas Gohr if ($this->extension->isInstalled()) { 3184fd6a1d7SAndreas Gohr 3194fd6a1d7SAndreas Gohr if (!$this->extension->isProtected()) $actions[] = 'uninstall'; 3204fd6a1d7SAndreas Gohr if ($this->extension->getDownloadURL()) { 3214fd6a1d7SAndreas Gohr $actions[] = $this->extension->isUpdateAvailable() ? 'update' : 'reinstall'; 3224fd6a1d7SAndreas Gohr 3234fd6a1d7SAndreas Gohr if ($this->extension->isGitControlled()) { 3244fd6a1d7SAndreas Gohr $errors[] = $this->getLang('git'); 3254fd6a1d7SAndreas Gohr } 3264fd6a1d7SAndreas Gohr } 3274fd6a1d7SAndreas Gohr 3284fd6a1d7SAndreas Gohr if (!$this->extension->isProtected() && !$this->extension->isTemplate()) { // no enable/disable for templates 3294fd6a1d7SAndreas Gohr $actions[] = $this->extension->isEnabled() ? 'disable' : 'enable'; 3304fd6a1d7SAndreas Gohr 3314fd6a1d7SAndreas Gohr if ( 3324fd6a1d7SAndreas Gohr $this->extension->isEnabled() && 3334fd6a1d7SAndreas Gohr in_array('Auth', $this->extension->getComponentTypes()) && 3344fd6a1d7SAndreas Gohr $conf['authtype'] != $this->extension->getID() 3354fd6a1d7SAndreas Gohr ) { 3364fd6a1d7SAndreas Gohr $errors[] = $this->getLang('auth'); 3374fd6a1d7SAndreas Gohr } 3384fd6a1d7SAndreas Gohr } 3394fd6a1d7SAndreas Gohr } else { 3404fd6a1d7SAndreas Gohr if ($this->extension->getDownloadURL()) { 3414fd6a1d7SAndreas Gohr $actions[] = 'install'; 3424fd6a1d7SAndreas Gohr } 3434fd6a1d7SAndreas Gohr } 3444fd6a1d7SAndreas Gohr } catch (\Exception $e) { 3454fd6a1d7SAndreas Gohr $errors[] = $e->getMessage(); 3464fd6a1d7SAndreas Gohr } 3474fd6a1d7SAndreas Gohr 3484fd6a1d7SAndreas Gohr foreach ($actions as $action) { 3494fd6a1d7SAndreas Gohr $html .= '<button name="fn[' . $action . '][' . $this->extension->getID() . ']" class="button" type="submit">' . 3504fd6a1d7SAndreas Gohr $this->getLang('btn_' . $action) . '</button>'; 3514fd6a1d7SAndreas Gohr } 3524fd6a1d7SAndreas Gohr 3534fd6a1d7SAndreas Gohr foreach ($errors as $error) { 3544fd6a1d7SAndreas Gohr $html .= '<div class="msg error">' . hsc($error) . '</div>'; 3554fd6a1d7SAndreas Gohr } 3564fd6a1d7SAndreas Gohr 3574fd6a1d7SAndreas Gohr return $html; 3584fd6a1d7SAndreas Gohr } 3594fd6a1d7SAndreas Gohr 3604fd6a1d7SAndreas Gohr 3614fd6a1d7SAndreas Gohr // endregion 3624fd6a1d7SAndreas Gohr // region utility functions 3634fd6a1d7SAndreas Gohr 3644fd6a1d7SAndreas Gohr /** 3654fd6a1d7SAndreas Gohr * Create the classes representing the state of the extension 3664fd6a1d7SAndreas Gohr * 3674fd6a1d7SAndreas Gohr * @return string 3684fd6a1d7SAndreas Gohr */ 3694fd6a1d7SAndreas Gohr protected function getClasses() 3704fd6a1d7SAndreas Gohr { 3714fd6a1d7SAndreas Gohr $classes = ['extension', $this->extension->getType()]; 3724fd6a1d7SAndreas Gohr if ($this->extension->isInstalled()) $classes[] = 'installed'; 3734fd6a1d7SAndreas Gohr if ($this->extension->isUpdateAvailable()) $classes[] = 'update'; 3744fd6a1d7SAndreas Gohr $classes[] = $this->extension->isEnabled() ? 'enabled' : 'disabled'; 3754fd6a1d7SAndreas Gohr return implode(' ', $classes); 3764fd6a1d7SAndreas Gohr } 3774fd6a1d7SAndreas Gohr 3784fd6a1d7SAndreas Gohr /** 3794fd6a1d7SAndreas Gohr * Create an attributes array for a link 3804fd6a1d7SAndreas Gohr * 3814fd6a1d7SAndreas Gohr * Handles interwiki links to dokuwiki.org 3824fd6a1d7SAndreas Gohr * 3834fd6a1d7SAndreas Gohr * @param string $url The URL to link to 3844fd6a1d7SAndreas Gohr * @param string $class Additional classes to add 3854fd6a1d7SAndreas Gohr * @return array 3864fd6a1d7SAndreas Gohr */ 3874fd6a1d7SAndreas Gohr protected function prepareLinkAttributes($url, $class) 3884fd6a1d7SAndreas Gohr { 3894fd6a1d7SAndreas Gohr global $conf; 3904fd6a1d7SAndreas Gohr 3914fd6a1d7SAndreas Gohr $attributes = [ 3924fd6a1d7SAndreas Gohr 'href' => $url, 3934fd6a1d7SAndreas Gohr 'class' => 'urlextern', 3944fd6a1d7SAndreas Gohr 'target' => $conf['target']['extern'], 3954fd6a1d7SAndreas Gohr 'rel' => 'noopener', 3964fd6a1d7SAndreas Gohr 'title' => $url, 3974fd6a1d7SAndreas Gohr ]; 3984fd6a1d7SAndreas Gohr 3994fd6a1d7SAndreas Gohr if ($conf['relnofollow']) { 4004fd6a1d7SAndreas Gohr $attributes['rel'] .= ' ugc nofollow'; 4014fd6a1d7SAndreas Gohr } 4024fd6a1d7SAndreas Gohr 4034fd6a1d7SAndreas Gohr if (preg_match('/^https?:\/\/(www\.)?dokuwiki\.org\//i', $url)) { 4044fd6a1d7SAndreas Gohr $attributes['class'] = 'interwiki iw_doku'; 4054fd6a1d7SAndreas Gohr $attributes['target'] = $conf['target']['interwiki']; 4064fd6a1d7SAndreas Gohr $attributes['rel'] = ''; 4074fd6a1d7SAndreas Gohr } 4084fd6a1d7SAndreas Gohr 4094fd6a1d7SAndreas Gohr $attributes['class'] .= ' ' . $class; 4104fd6a1d7SAndreas Gohr return $attributes; 4114fd6a1d7SAndreas Gohr } 4124fd6a1d7SAndreas Gohr 4134fd6a1d7SAndreas Gohr /** 4144fd6a1d7SAndreas Gohr * Create a link from the given URL 4154fd6a1d7SAndreas Gohr * 4164fd6a1d7SAndreas Gohr * Shortens the URL for display 4174fd6a1d7SAndreas Gohr * 4184fd6a1d7SAndreas Gohr * @param string $url 4194fd6a1d7SAndreas Gohr * @param string $class Additional classes to add 4204fd6a1d7SAndreas Gohr * @param string $fallback If URL is empty return this fallback 4214fd6a1d7SAndreas Gohr * @return string HTML link 4224fd6a1d7SAndreas Gohr */ 4234fd6a1d7SAndreas Gohr protected function shortlink($url, $class, $fallback = '') 4244fd6a1d7SAndreas Gohr { 4254fd6a1d7SAndreas Gohr if (!$url) return hsc($fallback); 4264fd6a1d7SAndreas Gohr 4274fd6a1d7SAndreas Gohr $link = parse_url($url); 4284fd6a1d7SAndreas Gohr $base = $link['host']; 4294fd6a1d7SAndreas Gohr if (!empty($link['port'])) $base .= $base . ':' . $link['port']; 4304fd6a1d7SAndreas Gohr $long = $link['path']; 4314fd6a1d7SAndreas Gohr if (!empty($link['query'])) $long .= $link['query']; 4324fd6a1d7SAndreas Gohr 4334fd6a1d7SAndreas Gohr $name = shorten($base, $long, 55); 4344fd6a1d7SAndreas Gohr 4354fd6a1d7SAndreas Gohr $params = $this->prepareLinkAttributes($url, $class); 4364fd6a1d7SAndreas Gohr $html = '<a ' . buildAttributes($params, true) . '>' . hsc($name) . '</a>'; 4374fd6a1d7SAndreas Gohr return $html; 4384fd6a1d7SAndreas Gohr } 4394fd6a1d7SAndreas Gohr 4404fd6a1d7SAndreas Gohr /** 4414fd6a1d7SAndreas Gohr * Generate a list of links for extensions 4424fd6a1d7SAndreas Gohr * 4434fd6a1d7SAndreas Gohr * Links to the search tab with the extension name 4444fd6a1d7SAndreas Gohr * 4454fd6a1d7SAndreas Gohr * @param array $extensions The extension names 4464fd6a1d7SAndreas Gohr * @return string The HTML code 4474fd6a1d7SAndreas Gohr */ 4484fd6a1d7SAndreas Gohr public function linkExtensions($extensions) 4494fd6a1d7SAndreas Gohr { 4504fd6a1d7SAndreas Gohr $html = ''; 4514fd6a1d7SAndreas Gohr foreach ($extensions as $link) { 4524fd6a1d7SAndreas Gohr $html .= '<bdi><a href="' . 4534fd6a1d7SAndreas Gohr $this->tabURL('search', ['q' => 'ext:' . $link]) . '">' . 4544fd6a1d7SAndreas Gohr hsc($link) . '</a></bdi>, '; 4554fd6a1d7SAndreas Gohr } 4564fd6a1d7SAndreas Gohr return rtrim($html, ', '); 4574fd6a1d7SAndreas Gohr } 4584fd6a1d7SAndreas Gohr 4594fd6a1d7SAndreas Gohr // endregion 4604fd6a1d7SAndreas Gohr} 461