<?php
use Shaarli\Config\Exception\PluginConfigOrderException;
+use Shaarli\Plugin\PluginManager;
/**
* Plugin configuration helper functions.
*/
function save_plugin_config($formData)
{
+ // We can only save existing plugins
+ $directories = str_replace(
+ PluginManager::$PLUGINS_PATH . '/',
+ '',
+ glob(PluginManager::$PLUGINS_PATH . '/*')
+ );
+ $formData = array_filter(
+ $formData,
+ function ($value, string $key) use ($directories) {
+ return startsWith($key, 'order') || in_array($key, $directories);
+ },
+ ARRAY_FILTER_USE_BOTH
+ );
+
// Make sure there are no duplicates in orders.
if (!validate_plugin_order($formData)) {
throw new PluginConfigOrderException();
$orders = array();
foreach ($formData as $key => $value) {
// No duplicate order allowed.
- if (in_array($value, $orders)) {
+ if (in_array($value, $orders, true)) {
return false;
}
$response = $response->withStatus($e->getCode());
- return $response->write($this->container->pageBuilder->render('error'));
+ return $response->write($this->container->pageBuilder->render('error', $this->container->basePath));
} catch (UnauthorizedException $e) {
$returnUrl = urlencode($this->container->environment['REQUEST_URI']);
$response = $response->withStatus(500);
- return $response->write($this->container->pageBuilder->render('error'));
+ return $response->write($this->container->pageBuilder->render('error', $this->container->basePath));
}
}
// To preserve backward compatibility with 3rd parties, plugins still use arrays
$formatter = $this->container->formatterFactory->getFormatter('raw');
$data = $formatter->format($bookmark);
- $data = $this->executeHooks('save_link', $data);
+ $this->executePageHooks('save_link', $data);
$bookmark->fromArray($data);
$this->container->bookmarkService->set($bookmark);
}
$data = $formatter->format($bookmark);
- $this->container->pluginManager->executeHooks('delete_link', $data);
+ $this->executePageHooks('delete_link', $data);
$this->container->bookmarkService->remove($bookmark, false);
++ $count;
}
// To preserve backward compatibility with 3rd parties, plugins still use arrays
$data = $formatter->format($bookmark);
- $this->container->pluginManager->executeHooks('save_link', $data);
+ $this->executePageHooks('save_link', $data);
$bookmark->fromArray($data);
$this->container->bookmarkService->set($bookmark, false);
// To preserve backward compatibility with 3rd parties, plugins still use arrays
$data = $formatter->format($bookmark);
- $this->container->pluginManager->executeHooks('save_link', $data);
+ $this->executePageHooks('save_link', $data);
$bookmark->fromArray($data);
$this->container->bookmarkService->set($bookmark);
'default_private_links' => $this->container->conf->get('privacy.default_private_links', false),
];
- $data = $this->executeHooks('render_editlink', $data);
+ $this->executePageHooks('render_editlink', $data, TemplatePage::EDIT_LINK);
foreach ($data as $key => $value) {
$this->assignView($key, $value);
return $response->write($this->render(TemplatePage::EDIT_LINK));
}
-
- /**
- * @param mixed[] $data Variables passed to the template engine
- *
- * @return mixed[] Template data after active plugins render_picwall hook execution.
- */
- protected function executeHooks(string $hook, array $data): array
- {
- $this->container->pluginManager->executeHooks(
- $hook,
- $data
- );
-
- return $data;
- }
}
try {
$parameters = $request->getParams() ?? [];
- $this->executeHooks($parameters);
+ $this->executePageHooks('save_plugin_parameters', $parameters);
if (isset($parameters['parameters_form'])) {
unset($parameters['parameters_form']);
return $this->redirect($response, '/admin/plugins');
}
-
- /**
- * @param mixed[] $data Variables passed to the template engine
- *
- * @return mixed[] Template data after active plugins render_picwall hook execution.
- */
- protected function executeHooks(array $data): array
- {
- $this->container->pluginManager->executeHooks(
- 'save_plugin_parameters',
- $data
- );
-
- return $data;
- }
}
'sslenabled' => is_https($this->container->environment),
];
- $data = $this->executeHooks($data);
+ $this->executePageHooks('render_tools', $data, TemplatePage::TOOLS);
foreach ($data as $key => $value) {
$this->assignView($key, $value);
return $response->write($this->render(TemplatePage::TOOLS));
}
-
- /**
- * @param mixed[] $data Variables passed to the template engine
- *
- * @return mixed[] Template data after active plugins render_picwall hook execution.
- */
- protected function executeHooks(array $data): array
- {
- $this->container->pluginManager->executeHooks(
- 'render_tools',
- $data
- );
-
- return $data;
- }
}
$data['pagetitle'] = ($data['pagetitle'] ?? '') . $this->container->conf->get('general.title', 'Shaarli');
- $this->executeHooks($data);
+ $this->executePageHooks('render_linklist', $data, TemplatePage::LINKLIST);
$this->assignAllView($data);
return $response->write($this->render(TemplatePage::LINKLIST));
]
);
- $this->executeHooks($data);
+ $this->executePageHooks('render_linklist', $data, TemplatePage::LINKLIST);
$this->assignAllView($data);
return $response->write($this->render(TemplatePage::LINKLIST));
return false;
}
- /**
- * @param mixed[] $data Template vars to process in plugins, passed as reference.
- */
- protected function executeHooks(array &$data): void
- {
- $this->container->pluginManager->executeHooks(
- 'render_linklist',
- $data,
- ['loggedin' => $this->container->loginManager->isLoggedIn()]
- );
- }
-
/**
* @return string[] Default template variables without values.
*/
];
// Hooks are called before column construction so that plugins don't have to deal with columns.
- $data = $this->executeHooks($data);
+ $this->executePageHooks('render_daily', $data, TemplatePage::DAILY);
$data['cols'] = $this->calculateColumns($data['linksToDisplay']);
- foreach ($data as $key => $value) {
- $this->assignView($key, $value);
- }
+ $this->assignAllView($data);
$mainTitle = $this->container->conf->get('general.title', 'Shaarli');
$this->assignView(
return $columns;
}
-
- /**
- * @param mixed[] $data Variables passed to the template engine
- *
- * @return mixed[] Template data after active plugins render_picwall hook execution.
- */
- protected function executeHooks(array $data): array
- {
- $this->container->pluginManager->executeHooks(
- 'render_daily',
- $data,
- ['loggedin' => $this->container->loginManager->isLoggedIn()]
- );
-
- return $data;
- }
}
$data = $this->container->feedBuilder->buildData($feedType, $request->getParams());
- $data = $this->executeHooks($data, $feedType);
+ $this->executePageHooks('render_feed', $data, $feedType);
$this->assignAllView($data);
$content = $this->render('feed.'. $feedType);
return $response->write($content);
}
-
- /**
- * @param mixed[] $data Template data
- *
- * @return mixed[] Template data after active plugins hook execution.
- */
- protected function executeHooks(array $data, string $feedType): array
- {
- $this->container->pluginManager->executeHooks(
- 'render_feed',
- $data,
- [
- 'loggedin' => $this->container->loginManager->isLoggedIn(),
- 'target' => $feedType,
- ]
- );
-
- return $data;
- }
}
}
}
- $data = $this->executeHooks($linksToDisplay);
+ $data = ['linksToDisplay' => $linksToDisplay];
+ $this->executePageHooks('render_picwall', $data, TemplatePage::PICTURE_WALL);
+
foreach ($data as $key => $value) {
$this->assignView($key, $value);
}
return $response->write($this->render(TemplatePage::PICTURE_WALL));
}
-
- /**
- * @param mixed[] $linksToDisplay List of formatted bookmarks
- *
- * @return mixed[] Template data after active plugins render_picwall hook execution.
- */
- protected function executeHooks(array $linksToDisplay): array
- {
- $data = [
- 'linksToDisplay' => $linksToDisplay,
- ];
- $this->container->pluginManager->executeHooks(
- 'render_picwall',
- $data,
- ['loggedin' => $this->container->loginManager->isLoggedIn()]
- );
-
- return $data;
- }
}
$this->assignView('privateLinkcount', $this->container->bookmarkService->count(BookmarkFilter::$PRIVATE));
$this->assignView('plugin_errors', $this->container->pluginManager->getErrors());
- /*
- * Define base path (if Shaarli is installed in a domain's subfolder, e.g. `/shaarli`)
- * and the asset path (subfolder/tpl/default for default theme).
- * These MUST be used to create an internal link or to include an asset in templates.
- */
- $this->assignView('base_path', $this->container->basePath);
- $this->assignView(
- 'asset_path',
- $this->container->basePath . '/' .
- rtrim($this->container->conf->get('resource.raintpl_tpl', 'tpl'), '/') . '/' .
- $this->container->conf->get('resource.theme', 'default')
- );
-
$this->executeDefaultHooks($template);
- return $this->container->pageBuilder->render($template);
+ return $this->container->pageBuilder->render($template, $this->container->basePath);
}
/**
$pluginData,
[
'target' => $template,
- 'loggedin' => $this->container->loginManager->isLoggedIn()
+ 'loggedin' => $this->container->loginManager->isLoggedIn(),
+ 'basePath' => $this->container->basePath,
]
);
$this->assignView('plugins_' . $name, $pluginData);
}
}
+ protected function executePageHooks(string $hook, array &$data, string $template = null): void
+ {
+ $params = [
+ 'target' => $template,
+ 'loggedin' => $this->container->loginManager->isLoggedIn(),
+ 'basePath' => $this->container->basePath,
+ ];
+
+ $this->container->pluginManager->executeHooks(
+ $hook,
+ $data,
+ $params
+ );
+ }
+
/**
* Simple helper which prepend the base path to redirect path.
*
'search_tags' => $searchTags,
'tags' => $tags,
];
- $data = $this->executeHooks('tag' . $type, $data);
- foreach ($data as $key => $value) {
- $this->assignView($key, $value);
- }
+ $this->executePageHooks('render_tag' . $type, $data, 'tag.' . $type);
+ $this->assignAllView($data);
$searchTags = !empty($searchTags) ? $searchTags .' - ' : '';
$this->assignView(
$searchTags . t('Tag '. $type) .' - '. $this->container->conf->get('general.title', 'Shaarli')
);
- return $response->write($this->render('tag.'. $type));
+ return $response->write($this->render('tag.' . $type));
}
/**
return $tagList;
}
-
- /**
- * @param mixed[] $data Template data
- *
- * @return mixed[] Template data after active plugins hook execution.
- */
- protected function executeHooks(string $template, array $data): array
- {
- $this->container->pluginManager->executeHooks(
- 'render_'. $template,
- $data,
- ['loggedin' => $this->container->loginManager->isLoggedIn()]
- );
-
- return $data;
- }
}
$data['_LOGGEDIN_'] = $params['loggedin'];
}
+ if (isset($params['basePath'])) {
+ $data['_BASE_PATH_'] = $params['basePath'];
+ }
+
foreach ($this->loadedPlugins as $plugin) {
$hookFunction = $this->buildHookName($hook, $plugin);
namespace Shaarli\Render;
use Exception;
+use exceptions\MissingBasePathException;
use RainTPL;
use Shaarli\ApplicationUtils;
use Shaarli\Bookmark\BookmarkServiceInterface;
* Affect variable after controller processing.
* Used for alert messages.
*/
- protected function finalize(): void
+ protected function finalize(string $basePath): void
{
// TODO: use the SessionManager
$messageKeys = [
unset($_SESSION[$messageKey]);
}
}
+
+ $this->assign('base_path', $basePath);
+ $this->assign(
+ 'asset_path',
+ $basePath . '/' .
+ rtrim($this->conf->get('resource.raintpl_tpl', 'tpl'), '/') . '/' .
+ $this->conf->get('resource.theme', 'default')
+ );
}
/**
return true;
}
- /**
- * Render a specific page (using a template file).
- * e.g. $pb->renderPage('picwall');
- *
- * @param string $page Template filename (without extension).
- */
- public function renderPage($page)
- {
- if ($this->tpl === false) {
- $this->initialize();
- }
-
- $this->finalize();
-
- $this->tpl->draw($page);
- }
-
/**
* Render a specific page as string (using a template file).
* e.g. $pb->render('picwall');
*
* @return string Processed template content
*/
- public function render(string $page): string
+ public function render(string $page, string $basePath): string
{
if ($this->tpl === false) {
$this->initialize();
}
- $this->finalize();
+ $this->finalize($basePath);
return $this->tpl->draw($page, true);
}
$form = array(
'attr' => array(
'method' => 'GET',
- 'action' => '',
+ 'action' => $data['_BASE_PATH_'] . '/admin/shaare',
'name' => 'addform',
'class' => 'addform',
),
<span>
<a href="https://web.archive.org/web/%s">
- <img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
+ <img class="linklist-plugin-icon" src="%s/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
</a>
</span>
function hook_archiveorg_render_linklist($data)
{
$archive_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/archiveorg/archiveorg.html');
+ $path = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH;
foreach ($data['links'] as &$value) {
if ($value['private'] && preg_match('/^\?[a-zA-Z0-9-_@]{6}($|&|#)/', $value['real_url'])) {
continue;
}
- $archive = sprintf($archive_html, $value['url'], t('View on archive.org'));
+ $archive = sprintf($archive_html, $value['url'], $path, t('View on archive.org'));
$value['link_plugin'][] = $archive;
}
$form = array(
'attr' => array(
'method' => 'GET',
- 'action' => '?',
+ 'action' => $data['_BASE_PATH_'] . '/',
'class' => 'addform',
),
'inputs' => array(
+++ /dev/null
-<span>
- <a href="?%s#isso-thread">
- <img class="linklist-plugin-icon" src="plugins/archiveorg/internetarchive.png" title="%s" alt="archive.org" />
- </a>
-</span>
{
$qrcode_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.html');
+ $path = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH;
foreach ($data['links'] as &$value) {
$qrcode = sprintf(
$qrcode_html,
$value['url'],
- PluginManager::$PLUGINS_PATH
+ $path
);
$value['link_plugin'][] = $qrcode;
}
function hook_qrcode_render_footer($data)
{
if ($data['_PAGE_'] == TemplatePage::LINKLIST) {
- $data['js_files'][] = PluginManager::$PLUGINS_PATH . '/qrcode/shaarli-qrcode.js';
+ $data['js_files'][] = PluginManager::$PLUGINS_PATH . '/qrcode/shaarli-qrcode.js';
}
return $data;
// Show the QR-Code of a permalink (when the QR-Code icon is clicked).
function showQrCode(caller,loading)
-{
+{
// Dynamic javascript lib loading: We only load qr.js if the QR code icon is clicked:
if (typeof(qr) == 'undefined') // Load qr.js only if not present.
{
if (!loading) // If javascript lib is still loading, do not append script to body.
{
- var element = document.createElement("script");
- element.src = "plugins/qrcode/qr-1.1.3.min.js";
+ var basePath = document.querySelector('input[name="js_base_path"]').value;
+ var element = document.createElement("script");
+ element.src = basePath + "/plugins/qrcode/qr-1.1.3.min.js";
document.body.appendChild(element);
}
setTimeout(function() { showQrCode(caller,true);}, 200); // Retry in 200 milliseconds.
// Remove previous qrcode if present.
removeQrcode();
-
+
// Build the div which contains the QR-Code:
var element = document.createElement('div');
element.id = 'permalinkQrcode';
// Damn IE
element.setAttribute('onclick', 'this.parentNode.removeChild(this);' );
}
-
+
// Build the QR-Code:
var image = qr.image({size: 8,value: caller.dataset.permalink});
if (image)
- {
+ {
element.appendChild(image);
element.innerHTML += "<br>Click to close";
caller.parentNode.appendChild(element);
elem.parentNode.removeChild(elem);
}
return false;
-}
\ No newline at end of file
+}
$wallabagHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/wallabag/wallabag.html');
$linkTitle = t('Save to wallabag');
+ $path = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH;
+
foreach ($data['links'] as &$value) {
$wallabag = sprintf(
$wallabagHtml,
$wallabagInstance->getWallabagUrl(),
urlencode($value['url']),
- PluginManager::$PLUGINS_PATH,
+ $path,
$linkTitle
);
$value['link_plugin'][] = $wallabag;
namespace Shaarli\Config;
use Shaarli\Config\Exception\PluginConfigOrderException;
+use Shaarli\Plugin\PluginManager;
require_once 'application/config/ConfigPlugin.php';
*/
public function testSavePluginConfigValid()
{
- $data = array(
+ $data = [
'order_plugin1' => 2, // no plugin related
'plugin2' => 0, // new - at the end
'plugin3' => 0, // 2nd
'order_plugin3' => 8,
'plugin4' => 0, // 1st
'order_plugin4' => 5,
- );
+ ];
- $expected = array(
+ $expected = [
'plugin3',
'plugin4',
'plugin2',
- );
+ ];
+
+ mkdir($path = __DIR__ . '/folder');
+ PluginManager::$PLUGINS_PATH = $path;
+ array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, $expected);
$out = save_plugin_config($data);
$this->assertEquals($expected, $out);
+
+ array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, $expected);
+ rmdir($path);
}
/**
->with('raw')
->willReturnCallback(function () use ($bookmark): BookmarkFormatter {
$formatter = $this->createMock(BookmarkFormatter::class);
-
- $formatter->expects(static::once())->method('format')->with($bookmark);
+ $formatter
+ ->expects(static::once())
+ ->method('format')
+ ->with($bookmark)
+ ->willReturn(['formatted' => $bookmark])
+ ;
return $formatter;
})
$this->container->pluginManager
->expects(static::once())
->method('executeHooks')
- ->with('delete_link')
+ ->with('delete_link', ['formatted' => $bookmark])
;
$result = $this->controller->deleteBookmark($request, $response);
->withConsecutive(...array_map(function (Bookmark $bookmark): array {
return [$bookmark];
}, $bookmarks))
+ ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
+ return ['formatted' => $bookmark];
+ }, $bookmarks))
;
return $formatter;
->withConsecutive(...array_map(function (Bookmark $bookmark): array {
return [$bookmark];
}, $bookmarks))
+ ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
+ return ['formatted' => $bookmark];
+ }, $bookmarks))
;
return $formatter;
$this->container->formatterFactory
->expects(static::once())
->method('getFormatter')
- ->willReturn($this->createMock(BookmarkFormatter::class))
+ ->willReturnCallback(function (): BookmarkFormatter {
+ $formatter = $this->createMock(BookmarkFormatter::class);
+ $formatter->method('format')->willReturn(['formatted']);
+
+ return $formatter;
+ })
;
$result = $this->controller->deleteBookmark($request, $response);
use PHPUnit\Framework\TestCase;
use Shaarli\Config\ConfigManager;
use Shaarli\Front\Exception\WrongTokenException;
+use Shaarli\Plugin\PluginManager;
use Shaarli\Security\SessionManager;
use Slim\Http\Request;
use Slim\Http\Response;
{
use FrontAdminControllerMockHelper;
+ const PLUGIN_NAMES = ['plugin1', 'plugin2', 'plugin3', 'plugin4'];
+
/** @var PluginsController */
protected $controller;
$this->createContainer();
$this->controller = new PluginsController($this->container);
+
+ mkdir($path = __DIR__ . '/folder');
+ PluginManager::$PLUGINS_PATH = $path;
+ array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES);
+ }
+
+ public function tearDown()
+ {
+ $path = __DIR__ . '/folder';
+ array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES);
+ rmdir($path);
}
/**
$this->controller = new SessionFilterController($this->container);
}
-
+
/**
* Visibility - Default call for private filter while logged in without current value
*/
static::assertSame(10, $this->assignedValues['linkcount']);
static::assertSame(5, $this->assignedValues['privateLinkcount']);
static::assertSame(['error'], $this->assignedValues['plugin_errors']);
- static::assertSame('/subfolder', $this->assignedValues['base_path']);
- static::assertSame('/subfolder/tpl/default', $this->assignedValues['asset_path']);
static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']);
static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']);
$data = array($str => $str);
$data['_PAGE_'] = TemplatePage::LINKLIST;
$data['_LOGGEDIN_'] = true;
+ $data['_BASE_PATH_'] = '/subfolder';
$data = hook_addlink_toolbar_render_header($data);
$this->assertEquals($str, $data[$str]);
$data = array($str => $str);
$data['_PAGE_'] = $str;
$data['_LOGGEDIN_'] = true;
+ $data['_BASE_PATH_'] = '/subfolder';
+
$data = hook_addlink_toolbar_render_header($data);
$this->assertEquals($str, $data[$str]);
$this->assertArrayNotHasKey('fields_toolbar', $data);
$data = array($str => $str);
$data['_PAGE_'] = TemplatePage::LINKLIST;
$data['_LOGGEDIN_'] = false;
+ $data['_BASE_PATH_'] = '/subfolder';
$data = hook_addlink_toolbar_render_header($data);
$this->assertEquals($str, $data[$str]);
<body onload="document.changepasswordform.oldpassword.focus();">
<div id="pageheader">
{include="page.header"}
- <form method="POST" action="#" name="changepasswordform" id="changepasswordform">
+ <form method="POST" action="{$base_path}/admin/password" name="changepasswordform" id="changepasswordform">
Old password: <input type="password" name="oldpassword">
New password: <input type="password" name="setpassword">
<input type="hidden" name="token" value="{$token}">
</div>
{include="page.footer"}
</body>
-</html>
\ No newline at end of file
+</html>
<body onload="document.changetag.fromtag.focus();">
<div id="pageheader">
{include="page.header"}
- <form method="POST" action="" name="changetag" id="changetag">
+ <form method="POST" action="{$base_path}/admin/tags" name="changetag" id="changetag">
<input type="hidden" name="token" value="{$token}">
<div>
<label for="fromtag">Tag:</label>
<body onload="document.configform.title.focus();">
<div id="pageheader">
{include="page.header"}
- <form method="POST" action="#" name="configform" id="configform">
+ <form method="POST" action="{$base_path}/admin/configure" name="configform" id="configform">
<input type="hidden" name="token" value="{$token}">
<table id="configuration_table">
<!DOCTYPE html>
<html>
<head>{include="includes"}
- <link type="text/css" rel="stylesheet" href="inc/awesomplete.css#" />
</head>
<body
{if="$link.title==''"}onload="document.linkform.lf_title.focus();"
<div id="pageheader">
{include="page.header"}
<div id="shaarli_title"><a href="{$titleLink}">{$shaarlititle}</a></div>
- {/if}
<div id="editlinkform">
- <form method="post" name="linkform">
+ <form method="post" name="linkform" action="{$base_path}/admin/shaare">
<input type="hidden" name="lf_linkdate" value="{$link.linkdate}">
{if="isset($link.id)"}
<input type="hidden" name="lf_id" value="{$link.id}">
<input type="radio" name="selection" value="all" checked="true"> All<br>
<input type="radio" name="selection" value="private"> Private<br>
<input type="radio" name="selection" value="public"> Public<br>
+ <input type="hidden" name="token" value="{$token}">
+
<br>
<input type="checkbox" name="prepend_note_url" id="prepend_note_url">
<label for="prepend_note_url">
<link rel="alternate" type="application/rss+xml" href="{$feedurl}feed/rss?{$searchcrits}#" title="RSS Feed" />
<link rel="alternate" type="application/atom+xml" href="{$feedurl}feed/atom?{$searchcrits}#" title="ATOM Feed" />
<link href="img/favicon.ico" rel="shortcut icon" type="image/x-icon" />
-<link type="text/css" rel="stylesheet" href="css/shaarli.min.css" />
+<link type="text/css" rel="stylesheet" href="{$asset_path}/css/shaarli.min.css#" />
{if="$formatter==='markdown'"}
<link type="text/css" rel="stylesheet" href="{$asset_path}/css/markdown.min.css?v={$version_hash}#" />
{/if}
{loop="$plugins_includes.css_files"}
-<link type="text/css" rel="stylesheet" href="{$value}#"/>
+<link type="text/css" rel="stylesheet" href="{$base_path}/{$value}#"/>
{/loop}
-{if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="data/user.css#" />{/if}
+{if="is_file('data/user.css')"}<link type="text/css" rel="stylesheet" href="{$base_path}/data/user.css#" />{/if}
<link rel="search" type="application/opensearchdescription+xml" href="{$base_path}/open-search#"
title="Shaarli search - {$shaarlititle|htmlspecialchars}" />
{if="! empty($links) && count($links) === 1"}
<div id="install">
<h1>Shaarli</h1>
It looks like it's the first time you run Shaarli. Please configure it:<br>
- <form method="POST" action="#" name="installform" id="installform">
+ <form method="POST" action="{$base_path}/install" name="installform" id="installform">
<table>
<tr><td><b>Login:</b></td><td><input type="text" name="setlogin" size="30"></td></tr>
<tr><td><b>Password:</b></td><td><input type="password" name="setpassword" size="30"></td></tr>
<!DOCTYPE html>
<html>
<head>
- <link type="text/css" rel="stylesheet" href="inc/awesomplete.css#" />
{include="includes"}
</head>
<body>
<div class="thumbnail">
<a href="{$value.real_url}">
{ignore}RainTPL hack: put the 2 src on two different line to avoid path replace bug{/ignore}
- <img data-src="{$value.thumbnail}#" class="b-lazy"
+ <img data-src="{$base_path}/{$value.thumbnail}#" class="b-lazy"
src=""
alt="thumbnail" width="{$thumbnails_width}" height="{$thumbnails_height}" />
</a>
<div class="linkcontainer">
{if="$is_logged_in"}
<div class="linkeditbuttons">
- <form method="GET" class="buttoneditform">
- <input type="hidden" name="edit_link" value="{$value.id}">
- <input type="image" alt="Edit" src="{$asset_path}/img/edit_icon.png#" title="Edit" class="button_edit">
- </form><br>
- <form method="GET" class="buttoneditform">
- <input type="hidden" name="lf_linkdate" value="{$value.id}">
- <input type="hidden" name="token" value="{$token}">
- <input type="hidden" name="delete_link">
- <input type="image" alt="Delete" src="{$asset_path}/img/delete_icon.png#" title="Delete"
- class="button_delete" onClick="return confirmDeleteLink();">
- </form>
+ <a href="{$base_path}/admin/shaare/{$value.id}" title="Edit" class="button_edit">
+ <img src="{$asset_path}/img/edit_icon.png#">
+ </a>
+ <br>
+ <a href="{$base_path}/admin/shaare/delete?id={$value.id}&token={$token}" label="Delete"
+ onClick="return confirmDeleteLink();"
+ class="button_delete"
+ >
+ <img src="{$asset_path}/img/delete_icon.png#">
+ </a>
</div>
{/if}
<span class="linktitle">
{if="!$hide_timestamps || $is_logged_in"}
{$updated=$value.updated_timestamp ? 'Edited: '. format_date($value.updated) : 'Permalink'}
<span class="linkdate" title="Permalink">
- <a href="{$base_path}/?{$value.shorturl}">
+ <a href="{$base_path}/shaare/{$value.shorturl}">
<span title="{$updated}">
{$value.created|format_date}
{if="$value.updated_timestamp"}*{/if}
</a> -
</span>
{else}
- <span class="linkdate" title="Short link here"><a href="{$base_path}/?{$value.shorturl}">permalink</a> - </span>
+ <span class="linkdate" title="Short link here"><a href="{$base_path}/shaare/{$value.shorturl}">permalink</a> - </span>
{/if}
{loop="$value.link_plugin"}
{include="page.header"}
<div id="headerform">
- <form method="post" name="loginform">
+ <form method="post" name="loginform" action="{$base_path}/login">
<label for="login">Login: <input type="text" id="login" name="login" tabindex="1"
{if="!empty($username)"}value="{$username}"{/if}>
</label>
{/if}
{loop="$plugins_footer.js_files"}
- <script src="{$value}#"></script>
+ <script src="{$base_path}/{$value}#"></script>
{/loop}
+
+<input type="hidden" name="js_base_path" value="{$base_path}" />
<input type="submit" value="Save"/>
</div>
</section>
+ <input type="hidden" name="token" value="{$token}">
</form>
<form action="{$base_path}/admin/plugins" method="POST">
</div>
</div>
</section>
+ <input type="hidden" name="token" value="{$token}">
</form>
</div>
<input type="hidden" name="ids" value="{function="implode(',', $ids)"}" />
{include="page.footer"}
-<input type="hidden" name="js_base_path" value="{$base_path}" />
<script src="{$asset_path}/js/thumbnails_update.min.js?v={$version_hash}#"></script>
</body>
</html>