Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin system #164

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions COPYING
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Files: inc/reset.css
License: BSD (http://opensource.org/licenses/BSD-3-Clause)
Copyright: (c) 2010, Yahoo! Inc.

Files: images/calendar.png, images/edit_icon.png, images/feed-icon-14x14.png, images/private.png, images/private_16x16.png, images/private_16x16_active.png, images/qrcode.png, images/tag_blue.png
Files: images/calendar.png, images/edit_icon.png, images/feed-icon-14x14.png, images/private.png, images/private_16x16.png, images/private_16x16_active.png, tpl/plugins/qrcode/qrcode.png, images/tag_blue.png
License: CC-BY (http://creativecommons.org/licenses/by/3.0/)
Copyright: (c) 2014 Yusuke Kamiyamane
Source: http://p.yusukekamiyamane.com/
Expand Down Expand Up @@ -54,7 +54,7 @@ Files: inc/blazy*.js
License: MIT License (http://opensource.org/licenses/MIT)
Copyright: (C) Bjoern Klinggaard - @bklinggaard - http://dinbror.dk/blazy

Files: inc/qr.js
Files: tpl/plugins/qrcode/qr.*js
License: GPLv3 License (http://opensource.org/licenses/gpl-3.0)
Copyright: (C) 2014 Alasdair Mercer, http://neocotic.com, https://github.com/neocotic/qr.js

Expand Down
8 changes: 4 additions & 4 deletions inc/shaarli.css
Original file line number Diff line number Diff line change
Expand Up @@ -368,12 +368,12 @@ h1 {
}
*/

.linkdate, .linkarchive {
.linkdate {
font-size:8pt;
color:#888;
}

.linkdate a, .linkarchive a {
.linkdate a {
color:#E28E3F;
}

Expand Down Expand Up @@ -414,12 +414,12 @@ a.qrcode img {
color: #F57900;
}

.linkdate, .linkarchive {
.linkdate {
font-size: 8pt;
color: #888;
}

.linkdate a, .linkarchive a {
.linkdate a {
background-image: url('../images/calendar.png');
padding: 2px 0 3px 20px;
background-repeat: no-repeat;
Expand Down
75 changes: 55 additions & 20 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
$GLOBALS['config']['UPDATECHECK_FILENAME'] = $GLOBALS['config']['DATADIR'].'/lastupdatecheck.txt'; // For updates check of Shaarli.
$GLOBALS['config']['UPDATECHECK_INTERVAL'] = 86400 ; // Updates check frequency for Shaarli. 86400 seconds=24 hours
// Note: You must have publisher.php in the same directory as Shaarli index.php
$GLOBALS['config']['ARCHIVE_ORG'] = false; // For each link, add a link to an archived version on archive.org
$GLOBALS['config']['ENABLE_RSS_PERMALINKS'] = true; // Enable RSS permalinks by default. This corresponds to the default behavior of shaarli before this was added as an option.
$GLOBALS['config']['PLUGINS'] = array('archiveorg', 'playvideos', 'qrcode', 'readityourself', 'wallabag'); // List of enabled plugins
$GLOBALS['config']['WALLABAG_URL'] = "https://demo.wallabag.org/"; // Base URL for the Wallabag plugin. You probably want to change this to your own wallabag instance
// -----------------------------------------------------------------------------------------------
// You should not touch below (or at your own risks!)
// Optional config file.
Expand Down Expand Up @@ -1225,19 +1226,68 @@ function showDaily()
exit;
}

// Renders the linklist
function showLinkList($PAGE, $LINKSDB) {
buildLinkList($PAGE,$LINKSDB); // Compute list of links to display
$PAGE->renderPage('linklist');
}


// ------------------------------------------------------------------------------------------
// Render HTML page (according to URL parameters and user rights)
function renderPage()
{
$LINKSDB=new linkdb(isLoggedIn() || $GLOBALS['config']['OPEN_SHAARLI']); // Read links from database (and filter private links if used it not logged in).

$PAGE = new pageBuilder;
// This may not be used in a few cases, like logging out. Don't care.
// 1) this removes repeated initialization
// 2) this allows us to setup the plugin system
// Build the plugin list
$linklist_plugins = array();
$footer_plugins = array();
$toolbar_plugins = array();
$includes_plugins = array();
foreach ($GLOBALS['config']['PLUGINS'] as $plugin) {
// Checking where the plugins should be inserted
// Basically, if $plugin.linklist.html exists, we need to use it as a
// linklist plugin, if $plugin.header.html exists we need to use it as a
// header plugin, and so on. This way we don't have to check for existance
// in the template. This reduces logic in the templates and makes them
// more maintainable.
$plugin_base = sprintf('plugins/%s/%s', $plugin, $plugin);
$plugin_linklist = $plugin_base . ".linklist";
$plugin_footer = $plugin_base . ".footer";
$plugin_toolbar = $plugin_base . ".toolbar";
$plugin_includes = $plugin_base . ".includes";

// We don't need the .html, RainTPL automatically adds in when inserting the template.
// (Also it crashes horribly if we add the .html because it searches for $plugin.html.html)
// We also need to concat tpl/ after because the path will be different once we ask rtpl to render
if (file_exists($GLOBALS['config']['RAINTPL_TPL'] . $plugin_toolbar . ".html")) {
$toolbar_plugins[] = $plugin_toolbar;
}
if (file_exists($GLOBALS['config']['RAINTPL_TPL'] . $plugin_linklist . ".html")) {
$linklist_plugins[] = $plugin_linklist;
}
if (file_exists($GLOBALS['config']['RAINTPL_TPL'] . $plugin_footer . ".html")) {
$footer_plugins[] = $plugin_footer;
}
if (file_exists($GLOBALS['config']['RAINTPL_TPL'] . $plugin_include . ".html")) {
$includes_plugins[] = $plugin_includes;
}

}
$PAGE->assign("plugins_footer", $footer_plugins);
$PAGE->assign("plugins_toolbar", $toolbar_plugins);
$PAGE->assign("plugins_linklist", $linklist_plugins);
$PAGE->assign("plugins_includes", $linklist_includes);

// -------- Display login form.
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=login'))
{
if ($GLOBALS['config']['OPEN_SHAARLI']) { header('Location: ?'); exit; } // No need to login for open Shaarli
$token=''; if (ban_canLogin()) $token=getToken(); // Do not waste token generation if not useful.
$PAGE = new pageBuilder;
$PAGE->assign('token',$token);
$PAGE->assign('returnurl',(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER']:''));
$PAGE->renderPage('loginform');
Expand Down Expand Up @@ -1275,7 +1325,6 @@ function renderPage()
$linksToDisplay[]=$link; // Add to array.
}
}
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('linksToDisplay',$linksToDisplay);
$PAGE->renderPage('picwall');
Expand All @@ -1296,7 +1345,6 @@ function renderPage()
{
$tagList[$key] = array('count'=>$value,'size'=>log($value, 15) / log($maxcount, 30) * (22-6) + 6);
}
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('tags',$tagList);
$PAGE->renderPage('tagcloud');
Expand Down Expand Up @@ -1398,10 +1446,7 @@ function renderPage()
header('Location: ?do=login&post=');
exit;
}

$PAGE = new pageBuilder;
buildLinkList($PAGE,$LINKSDB); // Compute list of links to display
$PAGE->renderPage('linklist');
showLinkList($PAGE, $LINKSDB);
exit; // Never remove this one! All operations below are reserved for logged in user.
}

Expand All @@ -1410,7 +1455,6 @@ function renderPage()
// -------- Display the Tools menu if requested (import/export/bookmarklet...)
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=tools'))
{
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('pageabsaddr',indexUrl());
$PAGE->renderPage('tools');
Expand All @@ -1437,7 +1481,6 @@ function renderPage()
}
else // show the change password form.
{
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('token',getToken());
$PAGE->renderPage('changepassword');
Expand Down Expand Up @@ -1470,7 +1513,6 @@ function renderPage()
}
else // Show the configuration form.
{
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('token',getToken());
$PAGE->assign('title',htmlspecialchars( empty($GLOBALS['title']) ? '' : $GLOBALS['title'] , ENT_QUOTES));
Expand All @@ -1488,7 +1530,6 @@ function renderPage()
{
if (empty($_POST['fromtag']))
{
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('token',getToken());
$PAGE->renderPage('changetag');
Expand Down Expand Up @@ -1534,7 +1575,6 @@ function renderPage()
// -------- User wants to add a link without using the bookmarklet: Show form.
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=addlink'))
{
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->renderPage('addlink');
exit;
Expand Down Expand Up @@ -1628,7 +1668,6 @@ function renderPage()
{
$link = $LINKSDB[$_GET['edit_link']]; // Read database
if (!$link) { header('Location: ?'); exit; } // Link not found in database.
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('link',$link);
$PAGE->assign('link_is_new',false);
Expand Down Expand Up @@ -1699,7 +1738,6 @@ function renderPage()
$link = array('linkdate'=>$linkdate,'title'=>$title,'url'=>$url,'description'=>$description,'tags'=>$tags,'private'=>$private);
}

$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('link',$link);
$PAGE->assign('link_is_new',$link_is_new);
Expand All @@ -1714,7 +1752,6 @@ function renderPage()
{
if (empty($_GET['what']))
{
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->renderPage('export');
exit;
Expand Down Expand Up @@ -1768,7 +1805,6 @@ function renderPage()
// -------- Show upload/import dialog:
if (isset($_SERVER["QUERY_STRING"]) && startswith($_SERVER["QUERY_STRING"],'do=import'))
{
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
$PAGE->assign('token',getToken());
$PAGE->assign('maxfilesize',getMaxFileSize());
Expand All @@ -1777,10 +1813,8 @@ function renderPage()
}

// -------- Otherwise, simply display search form and links:
$PAGE = new pageBuilder;
$PAGE->assign('linkcount',count($LINKSDB));
buildLinkList($PAGE,$LINKSDB); // Compute list of links to display
$PAGE->renderPage('linklist');
showLinkList($PAGE, $LINKSDB);
exit;
}

Expand Down Expand Up @@ -1946,6 +1980,7 @@ function buildLinkList($PAGE,$LINKSDB)
$taglist = explode(' ',$link['tags']);
uasort($taglist, 'strcasecmp');
$link['taglist']=$taglist;
$link['shorturl'] = smallHash($link['linkdate']);
$linkDisp[$keys[$i]] = $link;
$i++;
}
Expand Down
3 changes: 3 additions & 0 deletions tpl/includes.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@
<link type="text/css" rel="stylesheet" href="../inc/reset.css" />
<link type="text/css" rel="stylesheet" href="../inc/shaarli.css" />
{if="is_file('inc/user.css')"}<link type="text/css" rel="stylesheet" href="../inc/user.css" />{/if}
{loop="$plugins_includes"}
<span>{include="$value"}</span>
{/loop}
77 changes: 10 additions & 67 deletions tpl/linklist.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<ul>
{loop="links"}
<li{if="$value.class"} class="{$value.class}"{/if}>
<a id="{$value.linkdate|smallHash}"></a>
<a id="{$value.shorturl}"></a>
<div class="thumbnail">{$value.url|thumbnail}</div>
<div class="linkcontainer">
{if="isLoggedIn()"}
Expand All @@ -44,16 +44,17 @@
<br>
{if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if}
{if="!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()"}
<span class="linkdate" title="Permalink"><a href="?{$value.linkdate|smallHash}">{$value.localdate|htmlspecialchars} - permalink</a> - </span>
<span class="linkdate" title="Permalink"><a href="?{$value.shorturl}">{$value.localdate|htmlspecialchars} - permalink</a> - </span>
{else}
<span class="linkdate" title="Short link here"><a href="?{$value.linkdate|smallHash}">permalink</a> - </span>
<span class="linkdate" title="Short link here"><a href="?{$value.shorturl}">permalink</a> - </span>
{/if}
{if="$GLOBALS['config']['ARCHIVE_ORG']"}
<span class="linkarchive"><a href="https://web.archive.org/web/{$value.url|htmlspecialchars}">archive</a> - </span>
{/if}
<div class="linkqrcode"><a href="http://qrfree.kaywa.com/?l=1&amp;s=8&amp;d={$scripturl|urlencode}%3F{$value.linkdate|smallHash}"
onclick="return showQrCode(this);" class="qrcode" data-permalink="{$scripturl}?{$value.linkdate|smallHash}">
<img src="images/qrcode.png#" alt="QR-Code" title="{$value.localdate|htmlspecialchars}"></a></div> -
<!-- We need to assign those because include'ing changes the scope for $value, and
looping does too
Funfact: don't add spaces when assigning. IT doesn't assign and prints the value -->
{$link=$value}
{loop="$plugins_linklist"}
<span>{include="$value"}</span>
{/loop}
<a href="{$value.url|htmlspecialchars}"><span class="linkurl" title="Short link">{$value.url|htmlspecialchars}</span></a><br>
{if="$value.tags"}
<div class="linktaglist">
Expand All @@ -71,63 +72,5 @@

{include="page.footer"}

<script>
// Remove any displayed QR-Code
function remove_qrcode()
{
var elem = document.getElementById("permalinkQrcode");
if (elem) elem.parentNode.removeChild(elem);
return false;
}

function isCanvasSupported(){
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
}

// Show the QR-Code of a permalink (when the QR-Code icon is clicked).
function showQrCode(caller,loading)
{
if( !isCanvasSupported() ) return true;

// 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.
{
loading = typeof loading !== 'undefined' ? loading : false;
if (!loading) // If javascript lib is still loading, do not append script to body.
{
var element = document.createElement("script");
element.src = "inc/qr-1.1.3.min.js";
document.body.appendChild(element);
}
setTimeout(function() { showQrCode(caller,true);}, 200); // Retry in 200 milliseconds.
return false;
}

// Remove previous qrcode if present.
remove_qrcode();

// Build the div which contains the QR-Code:
var element = document.createElement('div');
element.id="permalinkQrcode";

// Make QR-Code div commit sepuku when clicked:
element.addEventListener('click', remove_qrcode ); // Works on every canvas supported browser

// Build the QR-Code:
var image = qr.image({size: 8,value: caller.getAttribute('data-permalink')});
if (image)
{
element.appendChild(image);
element.innerHTML+= "<br>Click to close";
caller.parentNode.appendChild(element);
}
else
{
element.innerHTML="Your browser does not seem to be HTML5 compatible.";
}
return false;
}
</script>
</body>
</html>
3 changes: 3 additions & 0 deletions tpl/page.footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
{if="isLoggedIn()"}
<script>function confirmDeleteLink() { var agree=confirm("Are you sure you want to delete this link ?"); if (agree) return true ; else return false ; }</script>
{/if}
{loop="$plugins_footer"}
<span>{include="$value"}</span>
{/loop}
3 changes: 3 additions & 0 deletions tpl/page.header.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<a href="?do=tagcloud">Tag cloud</a>
<a href="?do=picwall{$searchcrits}">Picture wall</a>
<a href="?do=daily">Daily</a>
{loop="$plugins_toolbar"}
{include="$value"}
{/loop}
{/if}
<div class="clear"></div>

Expand Down
Loading