extension = $extension; } public function render() { $classes = $this->getClasses(); $html = "
"; $html .= $this->thumbnail(); $html .= $this->popularity(); $html .= $this->info(); $html .= $this->notices(); $html .= $this->mainLinks(); $html .= $this->details(); $html .= $this->actions(); $html .= '
'; return $html; } // region sections /** * Get the link and image tag for the screenshot/thumbnail * * @return string The HTML code */ protected function thumbnail() { $screen = $this->extension->getScreenshotURL(); $thumb = $this->extension->getThumbnailURL(); $link = []; $img = [ 'width' => self::THUMB_WIDTH, 'height' => self::THUMB_HEIGHT, 'alt' => '', ]; if ($screen) { $link = [ 'href' => $screen, 'target' => '_blank', 'class' => 'extension_screenshot', 'title' => sprintf($this->getLang('screenshot'), $this->extension->getDisplayName()) ]; $img['src'] = $thumb; $img['alt'] = $link['title']; } elseif ($this->extension->isTemplate()) { $img['src'] = DOKU_BASE . 'lib/plugins/extension/images/template.png'; } else { $img['src'] = DOKU_BASE . 'lib/plugins/extension/images/plugin.png'; } $html = '
'; if ($link) $html .= ''; $html .= ''; if ($link) $html .= ''; $html .= '
'; return $html; } /** * The main information about the extension * * @return string */ protected function info() { $html = '

'; $html .= '' . hsc($this->extension->getDisplayName()) . ''; if($this->extension->isBundled()) { $html .= ' ' . hsc('<'.$this->getLang('status_bundled').'>') . ''; } elseif($this->extension->getInstalledVersion()) { $html .= ' ' . hsc($this->extension->getInstalledVersion()) . ''; } $html .= '

'; $html .= $this->author(); $html .= '

' . hsc($this->extension->getDescription()) . '

'; return $html; } /** * Display the available notices for the extension * * @return string */ protected function notices() { $notices = Notice::list($this->extension); $html = ''; foreach ($notices as $type => $messages) { foreach ($messages as $message) { $message = hsc($message); $message = preg_replace('/`([^`]+)`/', '$1', $message); $html .= '
' . $message . '
'; } } return $html; } /** * Generate the link bar HTML code * * @return string The HTML code */ public function mainLinks() { $html = ''; return $html; } /** * Create the details section * * @return string */ protected function details() { $html = '
'; $html .= '' . 'FIXME label' . ''; $default = $this->getLang('unknown'); $list = []; if (!$this->extension->isBundled()) { $list['downloadurl'] = $this->shortlink($this->extension->getDownloadURL(), 'download', $default); $list['repository'] = $this->shortlink($this->extension->getSourcerepoURL(), 'repo', $default); } if ($this->extension->isInstalled()) { if ($this->extension->isBundled()) { $list['installed_version'] = $this->getLang('status_bundled'); } else { if ($this->extension->getInstalledVersion()) { $list['installed_version'] = hsc($this->extension->getInstalledVersion()); } if (!$this->extension->isBundled()) { $updateDate = $this->extension->getManager()->getLastUpdate(); $list['install_date'] = $updateDate ? hsc($updateDate) : $default; } } } if (!$this->extension->isInstalled() || $this->extension->isUpdateAvailable()) { $list['available_version'] = $this->extension->getLastUpdate() ? hsc($this->extension->getLastUpdate()) : $default; } if (!$this->extension->isBundled() && $this->extension->getCompatibleVersions()) { $list['compatible'] = join(', ', array_map( function ($date, $version) { return '' . $version['label'] . ' (' . $date . ')'; }, array_keys($this->extension->getCompatibleVersions()), array_values($this->extension->getCompatibleVersions()) )); } $tags = $this->extension->getTags(); if ($tags) { $list['tags'] = join(', ', array_map(function ($tag) { $url = $this->tabURL('search', ['q' => 'tag:' . $tag]); return '' . hsc($tag) . ''; }, $tags)); } if ($this->extension->getDependencyList()) { $list['depends'] = $this->linkExtensions($this->extension->getDependencyList()); } if ($this->extension->getSimilarList()) { $list['similar'] = $this->linkExtensions($this->extension->getSimilarList()); } if ($this->extension->getConflictList()) { $list['conflicts'] = $this->linkExtensions($this->extension->getConflictList()); } foreach ($list as $key => $value) { $html .= '
' . $this->getLang($key) . '
'; $html .= '
' . $value . '
'; } $html .= '
'; return $html; } /** * Generate a link to the author of the extension * * @return string The HTML code of the link */ protected function author() { if (!$this->extension->getAuthor()) { return '' . $this->getLang('unknown_author') . ''; } $mailid = $this->extension->getEmailID(); if ($mailid) { $url = $this->tabURL('search', ['q' => 'authorid:' . $mailid]); $html = '' . ' ' . hsc($this->extension->getAuthor()) . ''; } else { $html = '' . hsc($this->extension->getAuthor()) . ''; } return '' . $html . ''; } /** * The popularity bar * * @return string */ protected function popularity() { $popularity = $this->extension->getPopularity(); if (!$popularity) return ''; if ($this->extension->isBundled()) return ''; $popularityText = sprintf($this->getLang('popularity'), round($popularity * 100, 2)); return '
' . '
' . '' . $popularityText . '' . '
'; } protected function actions() { global $conf; $html = ''; $actions = []; $errors = []; // show the available version if there is one if ($this->extension->getDownloadURL() && $this->extension->getLastUpdate()) { $html .= ' ' . $this->getLang('available_version') . ' ' . hsc($this->extension->getLastUpdate()) . ''; } // gather available actions and possible errors to show try { Installer::ensurePermissions($this->extension); if ($this->extension->isInstalled()) { if (!$this->extension->isProtected()) $actions[] = 'uninstall'; if ($this->extension->getDownloadURL()) { $actions[] = $this->extension->isUpdateAvailable() ? 'update' : 'reinstall'; if ($this->extension->isGitControlled()) { $errors[] = $this->getLang('git'); } } if (!$this->extension->isProtected() && !$this->extension->isTemplate()) { // no enable/disable for templates $actions[] = $this->extension->isEnabled() ? 'disable' : 'enable'; if ( $this->extension->isEnabled() && in_array('Auth', $this->extension->getComponentTypes()) && $conf['authtype'] != $this->extension->getID() ) { $errors[] = $this->getLang('auth'); } } } else { if ($this->extension->getDownloadURL()) { $actions[] = 'install'; } } } catch (\Exception $e) { $errors[] = $e->getMessage(); } foreach ($actions as $action) { $html .= ''; } foreach ($errors as $error) { $html .= '
' . hsc($error) . '
'; } return $html; } // endregion // region utility functions /** * Create the classes representing the state of the extension * * @return string */ protected function getClasses() { $classes = ['extension', $this->extension->getType()]; if ($this->extension->isInstalled()) $classes[] = 'installed'; if ($this->extension->isUpdateAvailable()) $classes[] = 'update'; $classes[] = $this->extension->isEnabled() ? 'enabled' : 'disabled'; return implode(' ', $classes); } /** * Create an attributes array for a link * * Handles interwiki links to dokuwiki.org * * @param string $url The URL to link to * @param string $class Additional classes to add * @return array */ protected function prepareLinkAttributes($url, $class) { global $conf; $attributes = [ 'href' => $url, 'class' => 'urlextern', 'target' => $conf['target']['extern'], 'rel' => 'noopener', 'title' => $url, ]; if ($conf['relnofollow']) { $attributes['rel'] .= ' ugc nofollow'; } if (preg_match('/^https?:\/\/(www\.)?dokuwiki\.org\//i', $url)) { $attributes['class'] = 'interwiki iw_doku'; $attributes['target'] = $conf['target']['interwiki']; $attributes['rel'] = ''; } $attributes['class'] .= ' ' . $class; return $attributes; } /** * Create a link from the given URL * * Shortens the URL for display * * @param string $url * @param string $class Additional classes to add * @param string $fallback If URL is empty return this fallback * @return string HTML link */ protected function shortlink($url, $class, $fallback = '') { if (!$url) return hsc($fallback); $link = parse_url($url); $base = $link['host']; if (!empty($link['port'])) $base .= $base . ':' . $link['port']; $long = $link['path']; if (!empty($link['query'])) $long .= $link['query']; $name = shorten($base, $long, 55); $params = $this->prepareLinkAttributes($url, $class); $html = '' . hsc($name) . ''; return $html; } /** * Generate a list of links for extensions * * Links to the search tab with the extension name * * @param array $extensions The extension names * @return string The HTML code */ public function linkExtensions($extensions) { $html = ''; foreach ($extensions as $link) { $html .= '' . hsc($link) . ', '; } return rtrim($html, ', '); } // endregion /** * Extension main description * * @return string The HTML code */ public function makeLegend() { $html = '
'; $html .= '

'; $html .= sprintf( $this->getLang('extensionby'), '' . hsc($this->extension->getDisplayName()) . '', $this->author() ); $html .= '

' . DOKU_LF; $html .= $this->makeScreenshot(); $popularity = $this->extension->getPopularity(); if ($popularity !== false && !$this->extension->isBundled()) { $popularityText = sprintf($this->getLang('popularity'), round($popularity * 100, 2)); $html .= '
' . '
' . '' . $popularityText . '' . '
' . DOKU_LF; } if ($this->extension->getDescription()) { $html .= '

'; $html .= hsc($this->extension->getDescription()) . ' '; $html .= '

' . DOKU_LF; } $html .= $this->makeLinkbar(); $html .= $this->makeInfo(); $html .= $this->makeNoticeArea(); $html .= '
' . DOKU_LF; return $html; } /** * Plugin/template details * * @return string The HTML code */ public function makeInfo() { $default = $this->getLang('unknown'); $list = []; $list['status'] = $this->makeStatus(); if ($this->extension->getDonationURL()) { $list['donate'] = ''; } if (!$this->extension->isBundled()) { $list['downloadurl'] = $this->shortlink($this->extension->getDownloadURL(), $default); $list['repository'] = $this->shortlink($this->extension->getSourcerepoURL(), $default); } if ($this->extension->isInstalled()) { if ($this->extension->getInstalledVersion()) { $list['installed_version'] = hsc($this->extension->getInstalledVersion()); } if (!$this->extension->isBundled()) { $updateDate = $this->extension->getManager()->getLastUpdate(); $list['install_date'] = $updateDate ? hsc($updateDate) : $default; } } if (!$this->extension->isInstalled() || $this->extension->isUpdateAvailable()) { $list['available_version'] = $this->extension->getLastUpdate() ? hsc($this->extension->getLastUpdate()) : $default; } if (!$this->extension->isBundled() && $this->extension->getCompatibleVersions()) { $html .= '
' . $this->getLang('compatible') . '
'; $html .= '
'; foreach ($this->extension->getCompatibleVersions() as $date => $version) { $html .= '' . $version['label'] . ' (' . $date . '), '; } $html = rtrim($html, ', '); $html .= '
'; } if ($this->extension->getDependencyList()) { $html .= '
' . $this->getLang('depends') . '
'; $html .= '
'; $html .= $this->makeLinkList($extension->getDependencies()); $html .= '
'; } if ($this->extension->getSimilarExtensions()) { $html .= '
' . $this->getLang('similar') . '
'; $html .= '
'; $html .= $this->makeLinkList($extension->getSimilarExtensions()); $html .= '
'; } if ($this->extension->getConflicts()) { $html .= '
' . $this->getLang('conflicts') . '
'; $html .= '
'; $html .= $this->makeLinkList($extension->getConflicts()); $html .= '
'; } $html .= '' . DOKU_LF; return $html; } }