Initial commit
This commit is contained in:
1298
content/lib/plugins/extension/helper/extension.php
Normal file
1298
content/lib/plugins/extension/helper/extension.php
Normal file
File diff suppressed because it is too large
Load Diff
237
content/lib/plugins/extension/helper/gui.php
Normal file
237
content/lib/plugins/extension/helper/gui.php
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
/**
|
||||
* DokuWiki Plugin extension (Helper Component)
|
||||
*
|
||||
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*/
|
||||
|
||||
use dokuwiki\Form\Form;
|
||||
|
||||
/**
|
||||
* Class helper_plugin_extension_list takes care of the overall GUI
|
||||
*/
|
||||
class helper_plugin_extension_gui extends DokuWiki_Plugin
|
||||
{
|
||||
protected $tabs = array('plugins', 'templates', 'search', 'install');
|
||||
|
||||
/** @var string the extension that should have an open info window FIXME currently broken */
|
||||
protected $infoFor = '';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* initializes requested info window
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
global $INPUT;
|
||||
$this->infoFor = $INPUT->str('info');
|
||||
}
|
||||
|
||||
/**
|
||||
* display the plugin tab
|
||||
*/
|
||||
public function tabPlugins()
|
||||
{
|
||||
echo '<div class="panelHeader">';
|
||||
echo $this->locale_xhtml('intro_plugins');
|
||||
echo '</div>';
|
||||
|
||||
$pluginlist = plugin_list('', true);
|
||||
/* @var helper_plugin_extension_extension $extension */
|
||||
$extension = $this->loadHelper('extension_extension');
|
||||
/* @var helper_plugin_extension_list $list */
|
||||
$list = $this->loadHelper('extension_list');
|
||||
|
||||
$form = new Form([
|
||||
'action' => $this->tabURL('', [], '&'),
|
||||
'id' => 'extension__list',
|
||||
]);
|
||||
$list->startForm();
|
||||
foreach ($pluginlist as $name) {
|
||||
$extension->setExtension($name);
|
||||
$list->addRow($extension, $extension->getID() == $this->infoFor);
|
||||
}
|
||||
$list->endForm();
|
||||
$form->addHTML($list->render(true));
|
||||
echo $form->toHTML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the template tab
|
||||
*/
|
||||
public function tabTemplates()
|
||||
{
|
||||
echo '<div class="panelHeader">';
|
||||
echo $this->locale_xhtml('intro_templates');
|
||||
echo '</div>';
|
||||
|
||||
// FIXME do we have a real way?
|
||||
$tpllist = glob(DOKU_INC.'lib/tpl/*', GLOB_ONLYDIR);
|
||||
$tpllist = array_map('basename', $tpllist);
|
||||
sort($tpllist);
|
||||
|
||||
/* @var helper_plugin_extension_extension $extension */
|
||||
$extension = $this->loadHelper('extension_extension');
|
||||
/* @var helper_plugin_extension_list $list */
|
||||
$list = $this->loadHelper('extension_list');
|
||||
|
||||
$form = new Form([
|
||||
'action' => $this->tabURL('', [], '&'),
|
||||
'id' => 'extension__list',
|
||||
]);
|
||||
$list->startForm();
|
||||
foreach ($tpllist as $name) {
|
||||
$extension->setExtension("template:$name");
|
||||
$list->addRow($extension, $extension->getID() == $this->infoFor);
|
||||
}
|
||||
$list->endForm();
|
||||
$form->addHTML($list->render(true));
|
||||
echo $form->toHTML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the search tab
|
||||
*/
|
||||
public function tabSearch()
|
||||
{
|
||||
global $INPUT;
|
||||
echo '<div class="panelHeader">';
|
||||
echo $this->locale_xhtml('intro_search');
|
||||
echo '</div>';
|
||||
|
||||
$form = new Form([
|
||||
'action' => $this->tabURL('', [], '&'),
|
||||
'class' => 'search',
|
||||
]);
|
||||
$form->addTagOpen('div')->addClass('no');
|
||||
$form->addTextInput('q', $this->getLang('search_for'))
|
||||
->addClass('edit')
|
||||
->val($INPUT->str('q'));
|
||||
$form->addButton('submit', $this->getLang('search'))
|
||||
->attrs(['type' => 'submit', 'title' => $this->getLang('search')]);
|
||||
$form->addTagClose('div');
|
||||
echo $form->toHTML();
|
||||
|
||||
if (!$INPUT->bool('q')) return;
|
||||
|
||||
/* @var helper_plugin_extension_repository $repository FIXME should we use some gloabl instance? */
|
||||
$repository = $this->loadHelper('extension_repository');
|
||||
$result = $repository->search($INPUT->str('q'));
|
||||
|
||||
/* @var helper_plugin_extension_extension $extension */
|
||||
$extension = $this->loadHelper('extension_extension');
|
||||
/* @var helper_plugin_extension_list $list */
|
||||
$list = $this->loadHelper('extension_list');
|
||||
|
||||
$form = new Form([
|
||||
'action' => $this->tabURL('', [], '&'),
|
||||
'id' => 'extension__list',
|
||||
]);
|
||||
$list->startForm();
|
||||
if ($result) {
|
||||
foreach ($result as $name) {
|
||||
$extension->setExtension($name);
|
||||
$list->addRow($extension, $extension->getID() == $this->infoFor);
|
||||
}
|
||||
} else {
|
||||
$list->nothingFound();
|
||||
}
|
||||
$list->endForm();
|
||||
$form->addHTML($list->render(true));
|
||||
echo $form->toHTML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the template tab
|
||||
*/
|
||||
public function tabInstall()
|
||||
{
|
||||
global $lang;
|
||||
echo '<div class="panelHeader">';
|
||||
echo $this->locale_xhtml('intro_install');
|
||||
echo '</div>';
|
||||
|
||||
$form = new Form([
|
||||
'action' => $this->tabURL('', [], '&'),
|
||||
'enctype' => 'multipart/form-data',
|
||||
'class' => 'install',
|
||||
]);
|
||||
$form->addTagOpen('div')->addClass('no');
|
||||
$form->addTextInput('installurl', $this->getLang('install_url'))
|
||||
->addClass('block')
|
||||
->attrs(['type' => 'url']);
|
||||
$form->addTag('br');
|
||||
$form->addTextInput('installfile', $this->getLang('install_upload'))
|
||||
->addClass('block')
|
||||
->attrs(['type' => 'file']);
|
||||
$form->addTag('br');
|
||||
$form->addCheckbox('overwrite', $lang['js']['media_overwrt'])
|
||||
->addClass('block');
|
||||
$form->addTag('br');
|
||||
$form->addButton('', $this->getLang('btn_install'))
|
||||
->attrs(['type' => 'submit', 'title' => $this->getLang('btn_install')]);
|
||||
$form->addTagClose('div');
|
||||
echo $form->toHTML();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the tab navigation
|
||||
*
|
||||
* @fixme style active one
|
||||
*/
|
||||
public function tabNavigation()
|
||||
{
|
||||
echo '<ul class="tabs">';
|
||||
foreach ($this->tabs as $tab) {
|
||||
$url = $this->tabURL($tab);
|
||||
if ($this->currentTab() == $tab) {
|
||||
$class = ' active';
|
||||
} else {
|
||||
$class = '';
|
||||
}
|
||||
echo '<li class="'.$tab.$class.'"><a href="'.$url.'">'.$this->getLang('tab_'.$tab).'</a></li>';
|
||||
}
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently selected tab
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function currentTab()
|
||||
{
|
||||
global $INPUT;
|
||||
|
||||
$tab = $INPUT->str('tab', 'plugins', true);
|
||||
if (!in_array($tab, $this->tabs)) $tab = 'plugins';
|
||||
return $tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an URL inside the extension manager
|
||||
*
|
||||
* @param string $tab tab to load, empty for current tab
|
||||
* @param array $params associative array of parameter to set
|
||||
* @param string $sep seperator to build the URL
|
||||
* @param bool $absolute create absolute URLs?
|
||||
* @return string
|
||||
*/
|
||||
public function tabURL($tab = '', $params = [], $sep = '&', $absolute = false)
|
||||
{
|
||||
global $ID;
|
||||
global $INPUT;
|
||||
|
||||
if (!$tab) $tab = $this->currentTab();
|
||||
$defaults = array(
|
||||
'do' => 'admin',
|
||||
'page' => 'extension',
|
||||
'tab' => $tab,
|
||||
);
|
||||
if ($tab == 'search') $defaults['q'] = $INPUT->str('q');
|
||||
|
||||
return wl($ID, array_merge($defaults, $params), $absolute, $sep);
|
||||
}
|
||||
}
|
674
content/lib/plugins/extension/helper/list.php
Normal file
674
content/lib/plugins/extension/helper/list.php
Normal file
@@ -0,0 +1,674 @@
|
||||
<?php
|
||||
/**
|
||||
* DokuWiki Plugin extension (Helper Component)
|
||||
*
|
||||
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
|
||||
* @author Michael Hamann <michael@content-space.de>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class helper_plugin_extension_list takes care of creating a HTML list of extensions
|
||||
*/
|
||||
class helper_plugin_extension_list extends DokuWiki_Plugin
|
||||
{
|
||||
protected $form = '';
|
||||
/** @var helper_plugin_extension_gui */
|
||||
protected $gui;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* loads additional helpers
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->gui = plugin_load('helper', 'extension_gui');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the extension table form
|
||||
*/
|
||||
public function startForm()
|
||||
{
|
||||
$this->form .= '<ul class="extensionList">';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build single row of extension table
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension that shall be added
|
||||
* @param bool $showinfo Show the info area
|
||||
*/
|
||||
public function addRow(helper_plugin_extension_extension $extension, $showinfo = false)
|
||||
{
|
||||
$this->startRow($extension);
|
||||
$this->populateColumn('legend', $this->makeLegend($extension, $showinfo));
|
||||
$this->populateColumn('actions', $this->makeActions($extension));
|
||||
$this->endRow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a header to the form
|
||||
*
|
||||
* @param string $id The id of the header
|
||||
* @param string $header The content of the header
|
||||
* @param int $level The level of the header
|
||||
*/
|
||||
public function addHeader($id, $header, $level = 2)
|
||||
{
|
||||
$this->form .='<h'.$level.' id="'.$id.'">'.hsc($header).'</h'.$level.'>'.DOKU_LF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a paragraph to the form
|
||||
*
|
||||
* @param string $data The content
|
||||
*/
|
||||
public function addParagraph($data)
|
||||
{
|
||||
$this->form .= '<p>'.hsc($data).'</p>'.DOKU_LF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add hidden fields to the form with the given data
|
||||
*
|
||||
* @param array $data key-value list of fields and their values to add
|
||||
*/
|
||||
public function addHidden(array $data)
|
||||
{
|
||||
$this->form .= '<div class="no">';
|
||||
foreach ($data as $key => $value) {
|
||||
$this->form .= '<input type="hidden" name="'.hsc($key).'" value="'.hsc($value).'" />';
|
||||
}
|
||||
$this->form .= '</div>'.DOKU_LF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add closing tags
|
||||
*/
|
||||
public function endForm()
|
||||
{
|
||||
$this->form .= '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Show message when no results are found
|
||||
*/
|
||||
public function nothingFound()
|
||||
{
|
||||
global $lang;
|
||||
$this->form .= '<li class="notfound">'.$lang['nothingfound'].'</li>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the form
|
||||
*
|
||||
* @param bool $returnonly whether to return html or print
|
||||
*/
|
||||
public function render($returnonly = false)
|
||||
{
|
||||
if ($returnonly) return $this->form;
|
||||
echo $this->form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the HTML for the row for the extension
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension
|
||||
*/
|
||||
private function startRow(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
$this->form .= '<li id="extensionplugin__'.hsc($extension->getID()).
|
||||
'" class="'.$this->makeClass($extension).'">';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a column with the given class and content
|
||||
* @param string $class The class name
|
||||
* @param string $html The content
|
||||
*/
|
||||
private function populateColumn($class, $html)
|
||||
{
|
||||
$this->form .= '<div class="'.$class.' col">'.$html.'</div>'.DOKU_LF;
|
||||
}
|
||||
|
||||
/**
|
||||
* End the row
|
||||
*/
|
||||
private function endRow()
|
||||
{
|
||||
$this->form .= '</li>'.DOKU_LF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the link to the plugin homepage
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeHomepageLink(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
global $conf;
|
||||
$url = $extension->getURL();
|
||||
if (strtolower(parse_url($url, PHP_URL_HOST)) == 'www.dokuwiki.org') {
|
||||
$linktype = 'interwiki';
|
||||
} else {
|
||||
$linktype = 'extern';
|
||||
}
|
||||
$param = array(
|
||||
'href' => $url,
|
||||
'title' => $url,
|
||||
'class' => ($linktype == 'extern') ? 'urlextern' : 'interwiki iw_doku',
|
||||
'target' => $conf['target'][$linktype],
|
||||
'rel' => ($linktype == 'extern') ? 'noopener' : '',
|
||||
);
|
||||
if ($linktype == 'extern' && $conf['relnofollow']) {
|
||||
$param['rel'] = implode(' ', [$param['rel'], 'ugc nofollow']);
|
||||
}
|
||||
$html = ' <a '. buildAttributes($param, true).'>'.
|
||||
$this->getLang('homepage_link').'</a>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the class name for the row of the extension
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension object
|
||||
* @return string The class name
|
||||
*/
|
||||
public function makeClass(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
$class = ($extension->isTemplate()) ? 'template' : 'plugin';
|
||||
if ($extension->isInstalled()) {
|
||||
$class.=' installed';
|
||||
$class.= ($extension->isEnabled()) ? ' enabled':' disabled';
|
||||
if ($extension->updateAvailable()) $class .= ' updatable';
|
||||
}
|
||||
if (!$extension->canModify()) $class.= ' notselect';
|
||||
if ($extension->isProtected()) $class.= ' protected';
|
||||
//if($this->showinfo) $class.= ' showinfo';
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a link to the author of the extension
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension object
|
||||
* @return string The HTML code of the link
|
||||
*/
|
||||
public function makeAuthor(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
if ($extension->getAuthor()) {
|
||||
$mailid = $extension->getEmailID();
|
||||
if ($mailid) {
|
||||
$url = $this->gui->tabURL('search', array('q' => 'authorid:'.$mailid));
|
||||
$html = '<a href="'.$url.'" class="author" title="'.$this->getLang('author_hint').'" >'.
|
||||
'<img src="//www.gravatar.com/avatar/'.$mailid.
|
||||
'?s=20&d=mm" width="20" height="20" alt="" /> '.
|
||||
hsc($extension->getAuthor()).'</a>';
|
||||
} else {
|
||||
$html = '<span class="author">'.hsc($extension->getAuthor()).'</span>';
|
||||
}
|
||||
$html = '<bdi>'.$html.'</bdi>';
|
||||
} else {
|
||||
$html = '<em class="author">'.$this->getLang('unknown_author').'</em>'.DOKU_LF;
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the link and image tag for the screenshot/thumbnail
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension object
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeScreenshot(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
$screen = $extension->getScreenshotURL();
|
||||
$thumb = $extension->getThumbnailURL();
|
||||
|
||||
if ($screen) {
|
||||
// use protocol independent URLs for images coming from us #595
|
||||
$screen = str_replace('http://www.dokuwiki.org', '//www.dokuwiki.org', $screen);
|
||||
$thumb = str_replace('http://www.dokuwiki.org', '//www.dokuwiki.org', $thumb);
|
||||
|
||||
$title = sprintf($this->getLang('screenshot'), hsc($extension->getDisplayName()));
|
||||
$img = '<a href="'.hsc($screen).'" target="_blank" class="extension_screenshot">'.
|
||||
'<img alt="'.$title.'" width="120" height="70" src="'.hsc($thumb).'" />'.
|
||||
'</a>';
|
||||
} elseif ($extension->isTemplate()) {
|
||||
$img = '<img alt="" width="120" height="70" src="'.DOKU_BASE.
|
||||
'lib/plugins/extension/images/template.png" />';
|
||||
} else {
|
||||
$img = '<img alt="" width="120" height="70" src="'.DOKU_BASE.
|
||||
'lib/plugins/extension/images/plugin.png" />';
|
||||
}
|
||||
$html = '<div class="screenshot" >'.$img.'<span></span></div>'.DOKU_LF;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension main description
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension object
|
||||
* @param bool $showinfo Show the info section
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeLegend(helper_plugin_extension_extension $extension, $showinfo = false)
|
||||
{
|
||||
$html = '<div>';
|
||||
$html .= '<h2>';
|
||||
$html .= sprintf(
|
||||
$this->getLang('extensionby'),
|
||||
'<bdi>'.hsc($extension->getDisplayName()).'</bdi>',
|
||||
$this->makeAuthor($extension)
|
||||
);
|
||||
$html .= '</h2>'.DOKU_LF;
|
||||
|
||||
$html .= $this->makeScreenshot($extension);
|
||||
|
||||
$popularity = $extension->getPopularity();
|
||||
if ($popularity !== false && !$extension->isBundled()) {
|
||||
$popularityText = sprintf($this->getLang('popularity'), round($popularity*100, 2));
|
||||
$html .= '<div class="popularity" title="'.$popularityText.'">'.
|
||||
'<div style="width: '.($popularity * 100).'%;">'.
|
||||
'<span class="a11y">'.$popularityText.'</span>'.
|
||||
'</div></div>'.DOKU_LF;
|
||||
}
|
||||
|
||||
if ($extension->getDescription()) {
|
||||
$html .= '<p><bdi>';
|
||||
$html .= hsc($extension->getDescription()).' ';
|
||||
$html .= '</bdi></p>'.DOKU_LF;
|
||||
}
|
||||
|
||||
$html .= $this->makeLinkbar($extension);
|
||||
|
||||
if ($showinfo) {
|
||||
$url = $this->gui->tabURL('');
|
||||
$class = 'close';
|
||||
} else {
|
||||
$url = $this->gui->tabURL('', array('info' => $extension->getID()));
|
||||
$class = '';
|
||||
}
|
||||
$html .= ' <a href="'.$url.'#extensionplugin__'.$extension->getID().
|
||||
'" class="info '.$class.'" title="'.$this->getLang('btn_info').
|
||||
'" data-extid="'.$extension->getID().'">'.$this->getLang('btn_info').'</a>';
|
||||
|
||||
if ($showinfo) {
|
||||
$html .= $this->makeInfo($extension);
|
||||
}
|
||||
$html .= $this->makeNoticeArea($extension);
|
||||
$html .= '</div>'.DOKU_LF;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the link bar HTML code
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension instance
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeLinkbar(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
global $conf;
|
||||
$html = '<div class="linkbar">';
|
||||
$html .= $this->makeHomepageLink($extension);
|
||||
|
||||
$bugtrackerURL = $extension->getBugtrackerURL();
|
||||
if ($bugtrackerURL) {
|
||||
if (strtolower(parse_url($bugtrackerURL, PHP_URL_HOST)) == 'www.dokuwiki.org') {
|
||||
$linktype = 'interwiki';
|
||||
} else {
|
||||
$linktype = 'extern';
|
||||
}
|
||||
$param = array(
|
||||
'href' => $bugtrackerURL,
|
||||
'title' => $bugtrackerURL,
|
||||
'class' => 'bugs',
|
||||
'target' => $conf['target'][$linktype],
|
||||
'rel' => ($linktype == 'extern') ? 'noopener' : '',
|
||||
);
|
||||
if ($conf['relnofollow']) {
|
||||
$param['rel'] = implode(' ', [$param['rel'], 'ugc nofollow']);
|
||||
}
|
||||
$html .= ' <a '.buildAttributes($param, true).'>'.
|
||||
$this->getLang('bugs_features').'</a>';
|
||||
}
|
||||
if ($extension->getTags()) {
|
||||
$first = true;
|
||||
$html .= ' <span class="tags">'.$this->getLang('tags').' ';
|
||||
foreach ($extension->getTags() as $tag) {
|
||||
if (!$first) {
|
||||
$html .= ', ';
|
||||
} else {
|
||||
$first = false;
|
||||
}
|
||||
$url = $this->gui->tabURL('search', ['q' => 'tag:'.$tag]);
|
||||
$html .= '<bdi><a href="'.$url.'">'.hsc($tag).'</a></bdi>';
|
||||
}
|
||||
$html .= '</span>';
|
||||
}
|
||||
$html .= '</div>'.DOKU_LF;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notice area
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeNoticeArea(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
$html = '';
|
||||
$missing_dependencies = $extension->getMissingDependencies();
|
||||
if (!empty($missing_dependencies)) {
|
||||
$html .= '<div class="msg error">' .
|
||||
sprintf(
|
||||
$this->getLang('missing_dependency'),
|
||||
'<bdi>' . implode(', ', $missing_dependencies) . '</bdi>'
|
||||
) .
|
||||
'</div>';
|
||||
}
|
||||
if ($extension->isInWrongFolder()) {
|
||||
$html .= '<div class="msg error">' .
|
||||
sprintf(
|
||||
$this->getLang('wrong_folder'),
|
||||
'<bdi>' . hsc($extension->getInstallName()) . '</bdi>',
|
||||
'<bdi>' . hsc($extension->getBase()) . '</bdi>'
|
||||
) .
|
||||
'</div>';
|
||||
}
|
||||
if (($securityissue = $extension->getSecurityIssue()) !== false) {
|
||||
$html .= '<div class="msg error">'.
|
||||
sprintf($this->getLang('security_issue'), '<bdi>'.hsc($securityissue).'</bdi>').
|
||||
'</div>';
|
||||
}
|
||||
if (($securitywarning = $extension->getSecurityWarning()) !== false) {
|
||||
$html .= '<div class="msg notify">'.
|
||||
sprintf($this->getLang('security_warning'), '<bdi>'.hsc($securitywarning).'</bdi>').
|
||||
'</div>';
|
||||
}
|
||||
if ($extension->updateAvailable()) {
|
||||
$html .= '<div class="msg notify">'.
|
||||
sprintf($this->getLang('update_available'), hsc($extension->getLastUpdate())).
|
||||
'</div>';
|
||||
}
|
||||
if ($extension->hasDownloadURLChanged()) {
|
||||
$html .= '<div class="msg notify">' .
|
||||
sprintf(
|
||||
$this->getLang('url_change'),
|
||||
'<bdi>' . hsc($extension->getDownloadURL()) . '</bdi>',
|
||||
'<bdi>' . hsc($extension->getLastDownloadURL()) . '</bdi>'
|
||||
) .
|
||||
'</div>';
|
||||
}
|
||||
return $html.DOKU_LF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a link from the given URL
|
||||
*
|
||||
* Shortens the URL for display
|
||||
*
|
||||
* @param string $url
|
||||
* @return string HTML link
|
||||
*/
|
||||
public function shortlink($url)
|
||||
{
|
||||
$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);
|
||||
|
||||
$html = '<a href="'.hsc($url).'" class="urlextern">'.hsc($name).'</a>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin/template details
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeInfo(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
$default = $this->getLang('unknown');
|
||||
$html = '<dl class="details">';
|
||||
|
||||
$html .= '<dt>'.$this->getLang('status').'</dt>';
|
||||
$html .= '<dd>'.$this->makeStatus($extension).'</dd>';
|
||||
|
||||
if ($extension->getDonationURL()) {
|
||||
$html .= '<dt>'.$this->getLang('donate').'</dt>';
|
||||
$html .= '<dd>';
|
||||
$html .= '<a href="'.$extension->getDonationURL().'" class="donate">'.
|
||||
$this->getLang('donate_action').'</a>';
|
||||
$html .= '</dd>';
|
||||
}
|
||||
|
||||
if (!$extension->isBundled()) {
|
||||
$html .= '<dt>'.$this->getLang('downloadurl').'</dt>';
|
||||
$html .= '<dd><bdi>';
|
||||
$html .= ($extension->getDownloadURL()
|
||||
? $this->shortlink($extension->getDownloadURL())
|
||||
: $default);
|
||||
$html .= '</bdi></dd>';
|
||||
|
||||
$html .= '<dt>'.$this->getLang('repository').'</dt>';
|
||||
$html .= '<dd><bdi>';
|
||||
$html .= ($extension->getSourcerepoURL()
|
||||
? $this->shortlink($extension->getSourcerepoURL())
|
||||
: $default);
|
||||
$html .= '</bdi></dd>';
|
||||
}
|
||||
|
||||
if ($extension->isInstalled()) {
|
||||
if ($extension->getInstalledVersion()) {
|
||||
$html .= '<dt>'.$this->getLang('installed_version').'</dt>';
|
||||
$html .= '<dd>';
|
||||
$html .= hsc($extension->getInstalledVersion());
|
||||
$html .= '</dd>';
|
||||
}
|
||||
if (!$extension->isBundled()) {
|
||||
$html .= '<dt>'.$this->getLang('install_date').'</dt>';
|
||||
$html .= '<dd>';
|
||||
$html .= ($extension->getUpdateDate()
|
||||
? hsc($extension->getUpdateDate())
|
||||
: $this->getLang('unknown'));
|
||||
$html .= '</dd>';
|
||||
}
|
||||
}
|
||||
if (!$extension->isInstalled() || $extension->updateAvailable()) {
|
||||
$html .= '<dt>'.$this->getLang('available_version').'</dt>';
|
||||
$html .= '<dd>';
|
||||
$html .= ($extension->getLastUpdate()
|
||||
? hsc($extension->getLastUpdate())
|
||||
: $this->getLang('unknown'));
|
||||
$html .= '</dd>';
|
||||
}
|
||||
|
||||
$html .= '<dt>'.$this->getLang('provides').'</dt>';
|
||||
$html .= '<dd><bdi>';
|
||||
$html .= ($extension->getTypes()
|
||||
? hsc(implode(', ', $extension->getTypes()))
|
||||
: $default);
|
||||
$html .= '</bdi></dd>';
|
||||
|
||||
if (!$extension->isBundled() && $extension->getCompatibleVersions()) {
|
||||
$html .= '<dt>'.$this->getLang('compatible').'</dt>';
|
||||
$html .= '<dd>';
|
||||
foreach ($extension->getCompatibleVersions() as $date => $version) {
|
||||
$html .= '<bdi>'.$version['label'].' ('.$date.')</bdi>, ';
|
||||
}
|
||||
$html = rtrim($html, ', ');
|
||||
$html .= '</dd>';
|
||||
}
|
||||
if ($extension->getDependencies()) {
|
||||
$html .= '<dt>'.$this->getLang('depends').'</dt>';
|
||||
$html .= '<dd>';
|
||||
$html .= $this->makeLinkList($extension->getDependencies());
|
||||
$html .= '</dd>';
|
||||
}
|
||||
|
||||
if ($extension->getSimilarExtensions()) {
|
||||
$html .= '<dt>'.$this->getLang('similar').'</dt>';
|
||||
$html .= '<dd>';
|
||||
$html .= $this->makeLinkList($extension->getSimilarExtensions());
|
||||
$html .= '</dd>';
|
||||
}
|
||||
|
||||
if ($extension->getConflicts()) {
|
||||
$html .= '<dt>'.$this->getLang('conflicts').'</dt>';
|
||||
$html .= '<dd>';
|
||||
$html .= $this->makeLinkList($extension->getConflicts());
|
||||
$html .= '</dd>';
|
||||
}
|
||||
$html .= '</dl>'.DOKU_LF;
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a list of links for extensions
|
||||
*
|
||||
* @param array $ext The extensions
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeLinkList($ext)
|
||||
{
|
||||
$html = '';
|
||||
foreach ($ext as $link) {
|
||||
$html .= '<bdi><a href="'.
|
||||
$this->gui->tabURL('search', array('q'=>'ext:'.$link)).'">'.
|
||||
hsc($link).'</a></bdi>, ';
|
||||
}
|
||||
return rtrim($html, ', ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the action buttons if they are possible
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeActions(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
global $conf;
|
||||
$html = '';
|
||||
$errors = '';
|
||||
|
||||
if ($extension->isInstalled()) {
|
||||
if (($canmod = $extension->canModify()) === true) {
|
||||
if (!$extension->isProtected()) {
|
||||
$html .= $this->makeAction('uninstall', $extension);
|
||||
}
|
||||
if ($extension->getDownloadURL()) {
|
||||
if ($extension->updateAvailable()) {
|
||||
$html .= $this->makeAction('update', $extension);
|
||||
} else {
|
||||
$html .= $this->makeAction('reinstall', $extension);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$errors .= '<p class="permerror">'.$this->getLang($canmod).'</p>';
|
||||
}
|
||||
|
||||
if (!$extension->isProtected() && !$extension->isTemplate()) { // no enable/disable for templates
|
||||
if ($extension->isEnabled()) {
|
||||
$html .= $this->makeAction('disable', $extension);
|
||||
} else {
|
||||
$html .= $this->makeAction('enable', $extension);
|
||||
}
|
||||
}
|
||||
|
||||
if ($extension->isGitControlled()) {
|
||||
$errors .= '<p class="permerror">'.$this->getLang('git').'</p>';
|
||||
}
|
||||
|
||||
if ($extension->isEnabled() &&
|
||||
in_array('Auth', $extension->getTypes()) &&
|
||||
$conf['authtype'] != $extension->getID()
|
||||
) {
|
||||
$errors .= '<p class="permerror">'.$this->getLang('auth').'</p>';
|
||||
}
|
||||
} else {
|
||||
if (($canmod = $extension->canModify()) === true) {
|
||||
if ($extension->getDownloadURL()) {
|
||||
$html .= $this->makeAction('install', $extension);
|
||||
}
|
||||
} else {
|
||||
$errors .= '<div class="permerror">'.$this->getLang($canmod).'</div>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$extension->isInstalled() && $extension->getDownloadURL()) {
|
||||
$html .= ' <span class="version">'.$this->getLang('available_version').' ';
|
||||
$html .= ($extension->getLastUpdate()
|
||||
? hsc($extension->getLastUpdate())
|
||||
: $this->getLang('unknown')).'</span>';
|
||||
}
|
||||
|
||||
return $html.' '.$errors.DOKU_LF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an action button for an extension
|
||||
*
|
||||
* @param string $action The action
|
||||
* @param helper_plugin_extension_extension $extension The extension
|
||||
* @return string The HTML code
|
||||
*/
|
||||
public function makeAction($action, $extension)
|
||||
{
|
||||
$title = '';
|
||||
|
||||
switch ($action) {
|
||||
case 'install':
|
||||
case 'reinstall':
|
||||
$title = 'title="'.hsc($extension->getDownloadURL()).'"';
|
||||
break;
|
||||
}
|
||||
|
||||
$classes = 'button '.$action;
|
||||
$name = 'fn['.$action.']['.hsc($extension->getID()).']';
|
||||
|
||||
$html = '<button class="'.$classes.'" name="'.$name.'" type="submit" '.$title.'>'.
|
||||
$this->getLang('btn_'.$action).'</button> ';
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin/template status
|
||||
*
|
||||
* @param helper_plugin_extension_extension $extension The extension
|
||||
* @return string The description of all relevant statusses
|
||||
*/
|
||||
public function makeStatus(helper_plugin_extension_extension $extension)
|
||||
{
|
||||
$status = array();
|
||||
|
||||
if ($extension->isInstalled()) {
|
||||
$status[] = $this->getLang('status_installed');
|
||||
if ($extension->isProtected()) {
|
||||
$status[] = $this->getLang('status_protected');
|
||||
} else {
|
||||
$status[] = $extension->isEnabled()
|
||||
? $this->getLang('status_enabled')
|
||||
: $this->getLang('status_disabled');
|
||||
}
|
||||
} else {
|
||||
$status[] = $this->getLang('status_not_installed');
|
||||
}
|
||||
if (!$extension->canModify()) $status[] = $this->getLang('status_unmodifiable');
|
||||
if ($extension->isBundled()) $status[] = $this->getLang('status_bundled');
|
||||
$status[] = $extension->isTemplate()
|
||||
? $this->getLang('status_template')
|
||||
: $this->getLang('status_plugin');
|
||||
return implode(', ', $status);
|
||||
}
|
||||
}
|
203
content/lib/plugins/extension/helper/repository.php
Normal file
203
content/lib/plugins/extension/helper/repository.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
/**
|
||||
* DokuWiki Plugin extension (Helper Component)
|
||||
*
|
||||
* @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
|
||||
* @author Michael Hamann <michael@content-space.de>
|
||||
*/
|
||||
|
||||
use dokuwiki\Cache\Cache;
|
||||
use dokuwiki\HTTP\DokuHTTPClient;
|
||||
use dokuwiki\Extension\PluginController;
|
||||
|
||||
/**
|
||||
* Class helper_plugin_extension_repository provides access to the extension repository on dokuwiki.org
|
||||
*/
|
||||
class helper_plugin_extension_repository extends DokuWiki_Plugin
|
||||
{
|
||||
|
||||
const EXTENSION_REPOSITORY_API = 'http://www.dokuwiki.org/lib/plugins/pluginrepo/api.php';
|
||||
|
||||
private $loaded_extensions = array();
|
||||
private $has_access = null;
|
||||
|
||||
/**
|
||||
* Initialize the repository (cache), fetches data for all installed plugins
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
/* @var PluginController $plugin_controller */
|
||||
global $plugin_controller;
|
||||
if ($this->hasAccess()) {
|
||||
$list = $plugin_controller->getList('', true);
|
||||
$request_data = array('fmt' => 'php');
|
||||
$request_needed = false;
|
||||
foreach ($list as $name) {
|
||||
$cache = new Cache('##extension_manager##'.$name, '.repo');
|
||||
|
||||
if (!isset($this->loaded_extensions[$name]) &&
|
||||
$this->hasAccess() &&
|
||||
!$cache->useCache(array('age' => 3600 * 24))
|
||||
) {
|
||||
$this->loaded_extensions[$name] = true;
|
||||
$request_data['ext'][] = $name;
|
||||
$request_needed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request_needed) {
|
||||
$httpclient = new DokuHTTPClient();
|
||||
$data = $httpclient->post(self::EXTENSION_REPOSITORY_API, $request_data);
|
||||
if ($data !== false) {
|
||||
$extensions = unserialize($data);
|
||||
foreach ($extensions as $extension) {
|
||||
$cache = new Cache('##extension_manager##'.$extension['plugin'], '.repo');
|
||||
$cache->storeCache(serialize($extension));
|
||||
}
|
||||
} else {
|
||||
$this->has_access = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If repository access is available
|
||||
*
|
||||
* @param bool $usecache use cached result if still valid
|
||||
* @return bool If repository access is available
|
||||
*/
|
||||
public function hasAccess($usecache = true) {
|
||||
if ($this->has_access === null) {
|
||||
$cache = new Cache('##extension_manager###hasAccess', '.repo');
|
||||
|
||||
if (!$cache->useCache(array('age' => 60*10, 'purge' => !$usecache))) {
|
||||
$httpclient = new DokuHTTPClient();
|
||||
$httpclient->timeout = 5;
|
||||
$data = $httpclient->get(self::EXTENSION_REPOSITORY_API.'?cmd=ping');
|
||||
if ($data !== false) {
|
||||
$this->has_access = true;
|
||||
$cache->storeCache(1);
|
||||
} else {
|
||||
$this->has_access = false;
|
||||
$cache->storeCache(0);
|
||||
}
|
||||
} else {
|
||||
$this->has_access = ($cache->retrieveCache(false) == 1);
|
||||
}
|
||||
}
|
||||
return $this->has_access;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the remote data of an individual plugin or template
|
||||
*
|
||||
* @param string $name The plugin name to get the data for, template names need to be prefix by 'template:'
|
||||
* @return array The data or null if nothing was found (possibly no repository access)
|
||||
*/
|
||||
public function getData($name)
|
||||
{
|
||||
$cache = new Cache('##extension_manager##'.$name, '.repo');
|
||||
|
||||
if (!isset($this->loaded_extensions[$name]) &&
|
||||
$this->hasAccess() &&
|
||||
!$cache->useCache(array('age' => 3600 * 24))
|
||||
) {
|
||||
$this->loaded_extensions[$name] = true;
|
||||
$httpclient = new DokuHTTPClient();
|
||||
$data = $httpclient->get(self::EXTENSION_REPOSITORY_API.'?fmt=php&ext[]='.urlencode($name));
|
||||
if ($data !== false) {
|
||||
$result = unserialize($data);
|
||||
$cache->storeCache(serialize($result[0]));
|
||||
return $result[0];
|
||||
} else {
|
||||
$this->has_access = false;
|
||||
}
|
||||
}
|
||||
if (file_exists($cache->cache)) {
|
||||
return unserialize($cache->retrieveCache(false));
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for plugins or templates using the given query string
|
||||
*
|
||||
* @param string $q the query string
|
||||
* @return array a list of matching extensions
|
||||
*/
|
||||
public function search($q)
|
||||
{
|
||||
$query = $this->parseQuery($q);
|
||||
$query['fmt'] = 'php';
|
||||
|
||||
$httpclient = new DokuHTTPClient();
|
||||
$data = $httpclient->post(self::EXTENSION_REPOSITORY_API, $query);
|
||||
if ($data === false) return array();
|
||||
$result = unserialize($data);
|
||||
|
||||
$ids = array();
|
||||
|
||||
// store cache info for each extension
|
||||
foreach ($result as $ext) {
|
||||
$name = $ext['plugin'];
|
||||
$cache = new Cache('##extension_manager##'.$name, '.repo');
|
||||
$cache->storeCache(serialize($ext));
|
||||
$ids[] = $name;
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses special queries from the query string
|
||||
*
|
||||
* @param string $q
|
||||
* @return array
|
||||
*/
|
||||
protected function parseQuery($q)
|
||||
{
|
||||
$parameters = array(
|
||||
'tag' => array(),
|
||||
'mail' => array(),
|
||||
'type' => array(),
|
||||
'ext' => array()
|
||||
);
|
||||
|
||||
// extract tags
|
||||
if (preg_match_all('/(^|\s)(tag:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
|
||||
foreach ($matches as $m) {
|
||||
$q = str_replace($m[2], '', $q);
|
||||
$parameters['tag'][] = $m[3];
|
||||
}
|
||||
}
|
||||
// extract author ids
|
||||
if (preg_match_all('/(^|\s)(authorid:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
|
||||
foreach ($matches as $m) {
|
||||
$q = str_replace($m[2], '', $q);
|
||||
$parameters['mail'][] = $m[3];
|
||||
}
|
||||
}
|
||||
// extract extensions
|
||||
if (preg_match_all('/(^|\s)(ext:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
|
||||
foreach ($matches as $m) {
|
||||
$q = str_replace($m[2], '', $q);
|
||||
$parameters['ext'][] = $m[3];
|
||||
}
|
||||
}
|
||||
// extract types
|
||||
if (preg_match_all('/(^|\s)(type:([\S]+))/', $q, $matches, PREG_SET_ORDER)) {
|
||||
foreach ($matches as $m) {
|
||||
$q = str_replace($m[2], '', $q);
|
||||
$parameters['type'][] = $m[3];
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME make integer from type value
|
||||
|
||||
$parameters['q'] = trim($q);
|
||||
return $parameters;
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4:sw=4:et:
|
Reference in New Issue
Block a user