Also fix note check in archiveorg plugin, and regression on vintage template.
Documentation regarding relative path has been added.
Fixes #1548
> Note: In PHP, `parse_ini_file()` seems to want strings to be between by quotes `"` in the ini file.
+### Understanding relative paths
+
+Because Shaarli is a self-hosted tool, an instance can either be installed at the root directory, or under a subfolder.
+This means that you can *never* use absolute paths (eg `/plugins/mything/file.png`).
+
+If a file needs to be included in server end, use simple relative path:
+`PluginManager::$PLUGINS_PATH . '/mything/template.html'`.
+
+If it needs to be included in front end side (e.g. an image),
+the relative path must be prefixed with special data `_BASE_PATH_`:
+`($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH . '/mything/picture.png`.
+
+Note that special placeholders for CSS and JS files (respectively `css_files` and `js_files`) are already prefixed
+with the base path in template files.
### It's not working!
$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'])) {
+ $isNote = startsWith($value['real_url'], '/shaare/');
+ if ($value['private'] && $isNote) {
continue;
}
- $archive = sprintf($archive_html, $value['url'], $path, t('View on archive.org'));
+ $url = $isNote ? rtrim(index_url($_SERVER), '/') . $value['real_url'] : $value['real_url'];
+ $archive = sprintf($archive_html, $url, $path, t('View on archive.org'));
$value['link_plugin'][] = $archive;
}
$isso = sprintf($issoHtml, $issoUrl, $issoUrl, $link['id'], $link['id']);
$data['plugin_end_zone'][] = $isso;
} else {
- $button = '<span><a href="?%s#isso-thread">';
+ $button = '<span><a href="'. ($data['_BASE_PATH_'] ?? '') . '/shaare/%s#isso-thread">';
// For the default theme we use a FontAwesome icon which is better than an image
if ($conf->get('resource.theme') === 'default') {
$button .= '<i class="linklist-plugin-icon fa fa-comment"></i>';
function hook_qrcode_render_footer($data)
{
if ($data['_PAGE_'] == TemplatePage::LINKLIST) {
- $data['js_files'][] = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH . '/qrcode/shaarli-qrcode.js';
+ $data['js_files'][] = PluginManager::$PLUGINS_PATH . '/qrcode/shaarli-qrcode.js';
}
return $data;
function hook_qrcode_render_includes($data)
{
if ($data['_PAGE_'] == TemplatePage::LINKLIST) {
- $data['css_files'][] = ($data['_BASE_PATH_'] ?? '') . '/' . PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.css';
+ $data['css_files'][] = PluginManager::$PLUGINS_PATH . '/qrcode/qrcode.css';
}
return $data;
<?php
+
namespace Shaarli\Plugin\Archiveorg;
/**
* PluginArchiveorgTest.php
*/
+use PHPUnit\Framework\TestCase;
use Shaarli\Plugin\PluginManager;
require_once 'plugins/archiveorg/archiveorg.php';
* Class PluginArchiveorgTest
* Unit test for the archiveorg plugin
*/
-class PluginArchiveorgTest extends \PHPUnit\Framework\TestCase
+class PluginArchiveorgTest extends TestCase
{
+ protected $savedScriptName;
+
/**
* Reset plugin path
*/
- public function setUp()
+ public function setUp(): void
{
PluginManager::$PLUGINS_PATH = 'plugins';
+
+ // plugins manipulate global vars
+ $_SERVER['SERVER_PORT'] = '80';
+ $_SERVER['SERVER_NAME'] = 'shaarli.shaarli';
+ $this->savedScriptName = $_SERVER['SCRIPT_NAME'] ?? null;
+ $_SERVER['SCRIPT_NAME'] = '/index.php';
+ }
+
+ public function tearDown(): void
+ {
+ unset($_SERVER['SERVER_PORT']);
+ unset($_SERVER['SERVER_NAME']);
+ $_SERVER['SCRIPT_NAME'] = $this->savedScriptName;
}
/**
* Test render_linklist hook on external bookmarks.
*/
- public function testArchiveorgLinklistOnExternalLinks()
+ public function testArchiveorgLinklistOnExternalLinks(): void
{
$str = 'http://randomstr.com/test';
/**
* Test render_linklist hook on internal bookmarks.
*/
- public function testArchiveorgLinklistOnInternalLinks()
+ public function testArchiveorgLinklistOnInternalLinks(): void
{
- $internalLink1 = 'http://shaarli.shaarli/?qvMAqg';
- $internalLinkRealURL1 = '?qvMAqg';
+ $internalLink1 = 'http://shaarli.shaarli/shaare/qvMAqg';
+ $internalLinkRealURL1 = '/shaare/qvMAqg';
- $internalLink2 = 'http://shaarli.shaarli/?2_7zww';
- $internalLinkRealURL2 = '?2_7zww';
+ $internalLink2 = 'http://shaarli.shaarli/shaare/2_7zww';
+ $internalLinkRealURL2 = '/shaare/2_7zww';
- $internalLink3 = 'http://shaarli.shaarli/?z7u-_Q';
- $internalLinkRealURL3 = '?z7u-_Q';
+ $internalLink3 = 'http://shaarli.shaarli/shaare/z7u-_Q';
+ $internalLinkRealURL3 = '/shaare/z7u-_Q';
$data = array(
'title' => $internalLink1,
namespace Shaarli\Plugin\Isso;
use DateTime;
+use PHPUnit\Framework\TestCase;
use Shaarli\Bookmark\Bookmark;
use Shaarli\Config\ConfigManager;
use Shaarli\Plugin\PluginManager;
*
* Test the Isso plugin (comment system).
*/
-class PluginIssoTest extends \PHPUnit\Framework\TestCase
+class PluginIssoTest extends TestCase
{
/**
* Reset plugin path
*/
- public function setUp()
+ public function setUp(): void
{
PluginManager::$PLUGINS_PATH = 'plugins';
}
/**
* Test Isso init without errors.
*/
- public function testIssoInitNoError()
+ public function testIssoInitNoError(): void
{
$conf = new ConfigManager('');
$conf->set('plugins.ISSO_SERVER', 'value');
/**
* Test Isso init with errors.
*/
- public function testIssoInitError()
+ public function testIssoInitError(): void
{
$conf = new ConfigManager('');
$errors = isso_init($conf);
/**
* Test render_linklist hook with valid settings to display the comment form.
*/
- public function testIssoDisplayed()
+ public function testIssoDisplayed(): void
{
$conf = new ConfigManager('');
$conf->set('plugins.ISSO_SERVER', 'value');
/**
* Test isso plugin when multiple bookmarks are displayed (shouldn't be displayed).
*/
- public function testIssoMultipleLinks()
+ public function testIssoMultipleLinks(): void
{
$conf = new ConfigManager('');
$conf->set('plugins.ISSO_SERVER', 'value');
$processed = hook_isso_render_linklist($data, $conf);
// link_plugin should be added for the icon
- $this->assertContains('<a href="?'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]);
- $this->assertContains('<a href="?'. $short2 .'#isso-thread">', $processed['links'][1]['link_plugin'][0]);
+ $this->assertContains('<a href="/shaare/'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]);
+ $this->assertContains('<a href="/shaare/'. $short2 .'#isso-thread">', $processed['links'][1]['link_plugin'][0]);
}
/**
* Test isso plugin when using search (shouldn't be displayed).
*/
- public function testIssoNotDisplayedWhenSearch()
+ public function testIssoNotDisplayedWhenSearch(): void
{
$conf = new ConfigManager('');
$conf->set('plugins.ISSO_SERVER', 'value');
$processed = hook_isso_render_linklist($data, $conf);
// link_plugin should be added for the icon
- $this->assertContains('<a href="?'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]);
+ $this->assertContains('<a href="/shaare/'. $short1 .'#isso-thread">', $processed['links'][0]['link_plugin'][0]);
}
/**
* Test isso plugin without server configuration (shouldn't be displayed).
*/
- public function testIssoWithoutConf()
+ public function testIssoWithoutConf(): void
{
$data = 'abc';
$conf = new ConfigManager('');
</form>
</div>
{if="$previous_page_url"} <a href="{$previous_page_url}" class="paging_older">◄Older</a> {/if}
- <div class="paging_current">page {$page_current} / {$page_max} </div>
+ {if="$page_max>1"}<div class="paging_current">page {$page_current} / {$page_max} </div>{/if}
{if="$next_page_url"} <a href="{$next_page_url}" class="paging_newer">Newer►</a> {/if}
</div>