Process Daily RSS feed through Slim controller
The daily RSS template has been entirely rewritten to handle the whole feed through the template engine.
This commit is contained in:
parent
e3d28be967
commit
c4d5be53c2
15 changed files with 366 additions and 155 deletions
|
@ -3,6 +3,7 @@
|
||||||
namespace Shaarli\Bookmark;
|
namespace Shaarli\Bookmark;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use DateTimeInterface;
|
||||||
use Shaarli\Bookmark\Exception\InvalidBookmarkException;
|
use Shaarli\Bookmark\Exception\InvalidBookmarkException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,10 +43,10 @@ class Bookmark
|
||||||
/** @var bool Set to true if the bookmark is set as sticky */
|
/** @var bool Set to true if the bookmark is set as sticky */
|
||||||
protected $sticky;
|
protected $sticky;
|
||||||
|
|
||||||
/** @var DateTime Creation datetime */
|
/** @var DateTimeInterface Creation datetime */
|
||||||
protected $created;
|
protected $created;
|
||||||
|
|
||||||
/** @var DateTime Update datetime */
|
/** @var DateTimeInterface datetime */
|
||||||
protected $updated;
|
protected $updated;
|
||||||
|
|
||||||
/** @var bool True if the bookmark can only be seen while logged in */
|
/** @var bool True if the bookmark can only be seen while logged in */
|
||||||
|
@ -100,7 +101,7 @@ public function validate()
|
||||||
|| ! is_int($this->id)
|
|| ! is_int($this->id)
|
||||||
|| empty($this->shortUrl)
|
|| empty($this->shortUrl)
|
||||||
|| empty($this->created)
|
|| empty($this->created)
|
||||||
|| ! $this->created instanceof DateTime
|
|| ! $this->created instanceof DateTimeInterface
|
||||||
) {
|
) {
|
||||||
throw new InvalidBookmarkException($this);
|
throw new InvalidBookmarkException($this);
|
||||||
}
|
}
|
||||||
|
@ -188,7 +189,7 @@ public function getDescription()
|
||||||
/**
|
/**
|
||||||
* Get the Created.
|
* Get the Created.
|
||||||
*
|
*
|
||||||
* @return DateTime
|
* @return DateTimeInterface
|
||||||
*/
|
*/
|
||||||
public function getCreated()
|
public function getCreated()
|
||||||
{
|
{
|
||||||
|
@ -198,7 +199,7 @@ public function getCreated()
|
||||||
/**
|
/**
|
||||||
* Get the Updated.
|
* Get the Updated.
|
||||||
*
|
*
|
||||||
* @return DateTime
|
* @return DateTimeInterface
|
||||||
*/
|
*/
|
||||||
public function getUpdated()
|
public function getUpdated()
|
||||||
{
|
{
|
||||||
|
@ -270,7 +271,7 @@ public function setDescription($description)
|
||||||
* Set the Created.
|
* Set the Created.
|
||||||
* Note: you shouldn't set this manually except for special cases (like bookmark import)
|
* Note: you shouldn't set this manually except for special cases (like bookmark import)
|
||||||
*
|
*
|
||||||
* @param DateTime $created
|
* @param DateTimeInterface $created
|
||||||
*
|
*
|
||||||
* @return Bookmark
|
* @return Bookmark
|
||||||
*/
|
*/
|
||||||
|
@ -284,7 +285,7 @@ public function setCreated($created)
|
||||||
/**
|
/**
|
||||||
* Set the Updated.
|
* Set the Updated.
|
||||||
*
|
*
|
||||||
* @param DateTime $updated
|
* @param DateTimeInterface $updated
|
||||||
*
|
*
|
||||||
* @return Bookmark
|
* @return Bookmark
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -53,7 +53,7 @@ public function __construct(ConfigManager $conf, History $history, $isLoggedIn)
|
||||||
{
|
{
|
||||||
$this->conf = $conf;
|
$this->conf = $conf;
|
||||||
$this->history = $history;
|
$this->history = $history;
|
||||||
$this->pageCacheManager = new PageCacheManager($this->conf->get('resource.page_cache'));
|
$this->pageCacheManager = new PageCacheManager($this->conf->get('resource.page_cache'), $isLoggedIn);
|
||||||
$this->bookmarksIO = new BookmarkIO($this->conf);
|
$this->bookmarksIO = new BookmarkIO($this->conf);
|
||||||
$this->isLoggedIn = $isLoggedIn;
|
$this->isLoggedIn = $isLoggedIn;
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,10 @@ public function build(): ShaarliContainer
|
||||||
};
|
};
|
||||||
|
|
||||||
$container['pageCacheManager'] = function (ShaarliContainer $container): PageCacheManager {
|
$container['pageCacheManager'] = function (ShaarliContainer $container): PageCacheManager {
|
||||||
return new PageCacheManager($container->conf->get('resource.page_cache'));
|
return new PageCacheManager(
|
||||||
|
$container->conf->get('resource.page_cache'),
|
||||||
|
$container->loginManager->isLoggedIn()
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return $container;
|
return $container;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
namespace Shaarli\Front\Controller;
|
namespace Shaarli\Front\Controller;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use DateTimeImmutable;
|
||||||
use Shaarli\Bookmark\Bookmark;
|
use Shaarli\Bookmark\Bookmark;
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
use Slim\Http\Response;
|
use Slim\Http\Response;
|
||||||
|
@ -18,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
class DailyController extends ShaarliController
|
class DailyController extends ShaarliController
|
||||||
{
|
{
|
||||||
|
public static $DAILY_RSS_NB_DAYS = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller displaying all bookmarks published in a single day.
|
* Controller displaying all bookmarks published in a single day.
|
||||||
* It take a `day` date query parameter (format YYYYMMDD).
|
* It take a `day` date query parameter (format YYYYMMDD).
|
||||||
|
@ -87,6 +90,77 @@ public function index(Request $request, Response $response): Response
|
||||||
return $response->write($this->render('daily'));
|
return $response->write($this->render('daily'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daily RSS feed: 1 RSS entry per day giving all the bookmarks on that day.
|
||||||
|
* Gives the last 7 days (which have bookmarks).
|
||||||
|
* This RSS feed cannot be filtered and does not trigger plugins yet.
|
||||||
|
*/
|
||||||
|
public function rss(Request $request, Response $response): Response
|
||||||
|
{
|
||||||
|
$response = $response->withHeader('Content-Type', 'application/rss+xml; charset=utf-8');
|
||||||
|
|
||||||
|
$pageUrl = page_url($this->container->environment);
|
||||||
|
$cache = $this->container->pageCacheManager->getCachePage($pageUrl);
|
||||||
|
|
||||||
|
$cached = $cache->cachedVersion();
|
||||||
|
if (!empty($cached)) {
|
||||||
|
return $response->write($cached);
|
||||||
|
}
|
||||||
|
|
||||||
|
$days = [];
|
||||||
|
foreach ($this->container->bookmarkService->search() as $bookmark) {
|
||||||
|
$day = $bookmark->getCreated()->format('Ymd');
|
||||||
|
|
||||||
|
// Stop iterating after DAILY_RSS_NB_DAYS entries
|
||||||
|
if (count($days) === static::$DAILY_RSS_NB_DAYS && !isset($days[$day])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$days[$day][] = $bookmark;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the RSS feed.
|
||||||
|
$indexUrl = escape(index_url($this->container->environment));
|
||||||
|
|
||||||
|
$formatter = $this->container->formatterFactory->getFormatter();
|
||||||
|
$formatter->addContextData('index_url', $indexUrl);
|
||||||
|
|
||||||
|
$dataPerDay = [];
|
||||||
|
|
||||||
|
/** @var Bookmark[] $bookmarks */
|
||||||
|
foreach ($days as $day => $bookmarks) {
|
||||||
|
$dayDatetime = DateTimeImmutable::createFromFormat(Bookmark::LINK_DATE_FORMAT, $day.'_000000');
|
||||||
|
$dataPerDay[$day] = [
|
||||||
|
'date' => $dayDatetime,
|
||||||
|
'date_rss' => $dayDatetime->format(DateTime::RSS),
|
||||||
|
'date_human' => format_date($dayDatetime, false, true),
|
||||||
|
'absolute_url' => $indexUrl . '/daily?day=' . $day,
|
||||||
|
'links' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($bookmarks as $key => $bookmark) {
|
||||||
|
$dataPerDay[$day]['links'][$key] = $formatter->format($bookmark);
|
||||||
|
|
||||||
|
// Make permalink URL absolute
|
||||||
|
if ($bookmark->isNote()) {
|
||||||
|
$dataPerDay[$day]['links'][$key]['url'] = $indexUrl . $bookmark->getUrl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assignView('title', $this->container->conf->get('general.title', 'Shaarli'));
|
||||||
|
$this->assignView('index_url', $indexUrl);
|
||||||
|
$this->assignView('page_url', $pageUrl);
|
||||||
|
$this->assignView('hide_timestamps', $this->container->conf->get('privacy.hide_timestamps', false));
|
||||||
|
$this->assignView('days', $dataPerDay);
|
||||||
|
|
||||||
|
$rssContent = $this->render('dailyrss');
|
||||||
|
|
||||||
|
$cache->cache($rssContent);
|
||||||
|
|
||||||
|
return $response->write($rssContent);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We need to spread the articles on 3 columns.
|
* We need to spread the articles on 3 columns.
|
||||||
* did not want to use a JavaScript lib like http://masonry.desandro.com/
|
* did not want to use a JavaScript lib like http://masonry.desandro.com/
|
||||||
|
|
|
@ -369,7 +369,7 @@ function server_url($server)
|
||||||
*/
|
*/
|
||||||
function index_url($server)
|
function index_url($server)
|
||||||
{
|
{
|
||||||
$scriptname = $server['SCRIPT_NAME'];
|
$scriptname = $server['SCRIPT_NAME'] ?? '';
|
||||||
if (endsWith($scriptname, 'index.php')) {
|
if (endsWith($scriptname, 'index.php')) {
|
||||||
$scriptname = substr($scriptname, 0, -9);
|
$scriptname = substr($scriptname, 0, -9);
|
||||||
}
|
}
|
||||||
|
@ -377,7 +377,7 @@ function index_url($server)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the absolute URL of the current script, with the query
|
* Returns the absolute URL of the current script, with current route and query
|
||||||
*
|
*
|
||||||
* If the resource is "index.php", then it is removed (for better-looking URLs)
|
* If the resource is "index.php", then it is removed (for better-looking URLs)
|
||||||
*
|
*
|
||||||
|
@ -387,10 +387,17 @@ function index_url($server)
|
||||||
*/
|
*/
|
||||||
function page_url($server)
|
function page_url($server)
|
||||||
{
|
{
|
||||||
if (! empty($server['QUERY_STRING'])) {
|
$scriptname = $server['SCRIPT_NAME'] ?? '';
|
||||||
return index_url($server).'?'.$server['QUERY_STRING'];
|
if (endsWith($scriptname, 'index.php')) {
|
||||||
|
$scriptname = substr($scriptname, 0, -9);
|
||||||
}
|
}
|
||||||
return index_url($server);
|
|
||||||
|
$route = ltrim($server['REQUEST_URI'] ?? '', $scriptname);
|
||||||
|
if (! empty($server['QUERY_STRING'])) {
|
||||||
|
return index_url($server) . $route . '?' . $server['QUERY_STRING'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return index_url($server) . $route;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -353,7 +353,7 @@ public function save($pageCacheDir)
|
||||||
|
|
||||||
$this->write();
|
$this->write();
|
||||||
|
|
||||||
$pageCacheManager = new PageCacheManager($pageCacheDir);
|
$pageCacheManager = new PageCacheManager($pageCacheDir, $this->loggedIn);
|
||||||
$pageCacheManager->invalidateCaches();
|
$pageCacheManager->invalidateCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Shaarli\Render;
|
namespace Shaarli\Render;
|
||||||
|
|
||||||
|
use Shaarli\Feed\CachedPage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache utilities
|
* Cache utilities
|
||||||
*/
|
*/
|
||||||
|
@ -10,9 +12,13 @@ class PageCacheManager
|
||||||
/** @var string Cache directory */
|
/** @var string Cache directory */
|
||||||
protected $pageCacheDir;
|
protected $pageCacheDir;
|
||||||
|
|
||||||
public function __construct(string $pageCacheDir)
|
/** @var bool */
|
||||||
|
protected $isLoggedIn;
|
||||||
|
|
||||||
|
public function __construct(string $pageCacheDir, bool $isLoggedIn)
|
||||||
{
|
{
|
||||||
$this->pageCacheDir = $pageCacheDir;
|
$this->pageCacheDir = $pageCacheDir;
|
||||||
|
$this->isLoggedIn = $isLoggedIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,4 +48,13 @@ public function invalidateCaches(): void
|
||||||
// Purge page cache shared by sessions.
|
// Purge page cache shared by sessions.
|
||||||
$this->purgeCachedPages();
|
$this->purgeCachedPages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCachePage(string $pageUrl): CachedPage
|
||||||
|
{
|
||||||
|
return new CachedPage(
|
||||||
|
$this->pageCacheDir,
|
||||||
|
$pageUrl,
|
||||||
|
false === $this->isLoggedIn
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
103
index.php
103
index.php
|
@ -300,104 +300,6 @@ function isLoggedIn()
|
||||||
$_SESSION['tokens']=array(); // Token are attached to the session.
|
$_SESSION['tokens']=array(); // Token are attached to the session.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Daily RSS feed: 1 RSS entry per day giving all the bookmarks on that day.
|
|
||||||
* Gives the last 7 days (which have bookmarks).
|
|
||||||
* This RSS feed cannot be filtered.
|
|
||||||
*
|
|
||||||
* @param BookmarkServiceInterface $bookmarkService
|
|
||||||
* @param ConfigManager $conf Configuration Manager instance
|
|
||||||
* @param LoginManager $loginManager LoginManager instance
|
|
||||||
*/
|
|
||||||
function showDailyRSS($bookmarkService, $conf, $loginManager)
|
|
||||||
{
|
|
||||||
// Cache system
|
|
||||||
$query = $_SERVER['QUERY_STRING'];
|
|
||||||
$cache = new CachedPage(
|
|
||||||
$conf->get('config.PAGE_CACHE'),
|
|
||||||
page_url($_SERVER),
|
|
||||||
startsWith($query, 'do=dailyrss') && !$loginManager->isLoggedIn()
|
|
||||||
);
|
|
||||||
$cached = $cache->cachedVersion();
|
|
||||||
if (!empty($cached)) {
|
|
||||||
echo $cached;
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some Shaarlies may have very few bookmarks, so we need to look
|
|
||||||
back in time until we have enough days ($nb_of_days).
|
|
||||||
*/
|
|
||||||
$nb_of_days = 7; // We take 7 days.
|
|
||||||
$today = date('Ymd');
|
|
||||||
$days = array();
|
|
||||||
|
|
||||||
foreach ($bookmarkService->search() as $bookmark) {
|
|
||||||
$day = $bookmark->getCreated()->format('Ymd'); // Extract day (without time)
|
|
||||||
if (strcmp($day, $today) < 0) {
|
|
||||||
if (empty($days[$day])) {
|
|
||||||
$days[$day] = array();
|
|
||||||
}
|
|
||||||
$days[$day][] = $bookmark;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($days) > $nb_of_days) {
|
|
||||||
break; // Have we collected enough days?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the RSS feed.
|
|
||||||
header('Content-Type: application/rss+xml; charset=utf-8');
|
|
||||||
$pageaddr = escape(index_url($_SERVER));
|
|
||||||
echo '<?xml version="1.0" encoding="UTF-8"?><rss version="2.0">';
|
|
||||||
echo '<channel>';
|
|
||||||
echo '<title>Daily - '. $conf->get('general.title') . '</title>';
|
|
||||||
echo '<link>'. $pageaddr .'</link>';
|
|
||||||
echo '<description>Daily shared bookmarks</description>';
|
|
||||||
echo '<language>en-en</language>';
|
|
||||||
echo '<copyright>'. $pageaddr .'</copyright>'. PHP_EOL;
|
|
||||||
|
|
||||||
$factory = new FormatterFactory($conf, $loginManager->isLoggedIn());
|
|
||||||
$formatter = $factory->getFormatter();
|
|
||||||
$formatter->addContextData('index_url', index_url($_SERVER));
|
|
||||||
// For each day.
|
|
||||||
/** @var Bookmark[] $bookmarks */
|
|
||||||
foreach ($days as $day => $bookmarks) {
|
|
||||||
$formattedBookmarks = [];
|
|
||||||
$dayDate = DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, $day.'_000000');
|
|
||||||
$absurl = escape(index_url($_SERVER).'?do=daily&day='.$day); // Absolute URL of the corresponding "Daily" page.
|
|
||||||
|
|
||||||
// We pre-format some fields for proper output.
|
|
||||||
foreach ($bookmarks as $key => $bookmark) {
|
|
||||||
$formattedBookmarks[$key] = $formatter->format($bookmark);
|
|
||||||
// This page is a bit specific, we need raw description to calculate the length
|
|
||||||
$formattedBookmarks[$key]['formatedDescription'] = $formattedBookmarks[$key]['description'];
|
|
||||||
$formattedBookmarks[$key]['description'] = $bookmark->getDescription();
|
|
||||||
|
|
||||||
if ($bookmark->isNote()) {
|
|
||||||
$link['url'] = index_url($_SERVER) . $bookmark->getUrl(); // make permalink URL absolute
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then build the HTML for this day:
|
|
||||||
$tpl = new RainTPL();
|
|
||||||
$tpl->assign('title', $conf->get('general.title'));
|
|
||||||
$tpl->assign('daydate', $dayDate->getTimestamp());
|
|
||||||
$tpl->assign('absurl', $absurl);
|
|
||||||
$tpl->assign('links', $formattedBookmarks);
|
|
||||||
$tpl->assign('rssdate', escape($dayDate->format(DateTime::RSS)));
|
|
||||||
$tpl->assign('hide_timestamps', $conf->get('privacy.hide_timestamps', false));
|
|
||||||
$tpl->assign('index_url', $pageaddr);
|
|
||||||
$html = $tpl->draw('dailyrss', true);
|
|
||||||
|
|
||||||
echo $html . PHP_EOL;
|
|
||||||
}
|
|
||||||
echo '</channel></rss><!-- Cached version of '. escape(page_url($_SERVER)) .' -->';
|
|
||||||
|
|
||||||
$cache->cache(ob_get_contents());
|
|
||||||
ob_end_flush();
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the linklist
|
* Renders the linklist
|
||||||
*
|
*
|
||||||
|
@ -424,7 +326,7 @@ function showLinkList($PAGE, $linkDb, $conf, $pluginManager, $loginManager)
|
||||||
*/
|
*/
|
||||||
function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionManager, $loginManager)
|
function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionManager, $loginManager)
|
||||||
{
|
{
|
||||||
$pageCacheManager = new PageCacheManager($conf->get('resource.page_cache'));
|
$pageCacheManager = new PageCacheManager($conf->get('resource.page_cache'), $loginManager->isLoggedIn());
|
||||||
$updater = new Updater(
|
$updater = new Updater(
|
||||||
UpdaterUtils::read_updates_file($conf->get('resource.updates')),
|
UpdaterUtils::read_updates_file($conf->get('resource.updates')),
|
||||||
$bookmarkService,
|
$bookmarkService,
|
||||||
|
@ -1715,7 +1617,7 @@ function install($conf, $sessionManager, $loginManager)
|
||||||
$linkDb = new BookmarkFileService($conf, $history, $loginManager->isLoggedIn());
|
$linkDb = new BookmarkFileService($conf, $history, $loginManager->isLoggedIn());
|
||||||
|
|
||||||
if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=dailyrss')) {
|
if (isset($_SERVER['QUERY_STRING']) && startsWith($_SERVER['QUERY_STRING'], 'do=dailyrss')) {
|
||||||
showDailyRSS($linkDb, $conf, $loginManager);
|
header('Location: ./daily-rss');
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1747,6 +1649,7 @@ function install($conf, $sessionManager, $loginManager)
|
||||||
$this->get('/tag-cloud', '\Shaarli\Front\Controller\TagCloudController:cloud')->setName('tagcloud');
|
$this->get('/tag-cloud', '\Shaarli\Front\Controller\TagCloudController:cloud')->setName('tagcloud');
|
||||||
$this->get('/tag-list', '\Shaarli\Front\Controller\TagCloudController:list')->setName('taglist');
|
$this->get('/tag-list', '\Shaarli\Front\Controller\TagCloudController:list')->setName('taglist');
|
||||||
$this->get('/daily', '\Shaarli\Front\Controller\DailyController:index')->setName('daily');
|
$this->get('/daily', '\Shaarli\Front\Controller\DailyController:index')->setName('daily');
|
||||||
|
$this->get('/daily-rss', '\Shaarli\Front\Controller\DailyController:rss')->setName('dailyrss');
|
||||||
|
|
||||||
$this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\TagController:addTag')->setName('add-tag');
|
$this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\TagController:addTag')->setName('add-tag');
|
||||||
})->add('\Shaarli\Front\ShaarliMiddleware');
|
})->add('\Shaarli\Front\ShaarliMiddleware');
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
use Shaarli\Bookmark\BookmarkServiceInterface;
|
use Shaarli\Bookmark\BookmarkServiceInterface;
|
||||||
use Shaarli\Config\ConfigManager;
|
use Shaarli\Config\ConfigManager;
|
||||||
use Shaarli\Container\ShaarliContainer;
|
use Shaarli\Container\ShaarliContainer;
|
||||||
|
use Shaarli\Feed\CachedPage;
|
||||||
use Shaarli\Formatter\BookmarkFormatter;
|
use Shaarli\Formatter\BookmarkFormatter;
|
||||||
use Shaarli\Formatter\BookmarkRawFormatter;
|
use Shaarli\Formatter\BookmarkRawFormatter;
|
||||||
use Shaarli\Formatter\FormatterFactory;
|
use Shaarli\Formatter\FormatterFactory;
|
||||||
use Shaarli\Plugin\PluginManager;
|
use Shaarli\Plugin\PluginManager;
|
||||||
use Shaarli\Render\PageBuilder;
|
use Shaarli\Render\PageBuilder;
|
||||||
|
use Shaarli\Render\PageCacheManager;
|
||||||
use Shaarli\Security\LoginManager;
|
use Shaarli\Security\LoginManager;
|
||||||
use Slim\Http\Request;
|
use Slim\Http\Request;
|
||||||
use Slim\Http\Response;
|
use Slim\Http\Response;
|
||||||
|
@ -30,9 +32,10 @@ public function setUp(): void
|
||||||
{
|
{
|
||||||
$this->container = $this->createMock(ShaarliContainer::class);
|
$this->container = $this->createMock(ShaarliContainer::class);
|
||||||
$this->controller = new DailyController($this->container);
|
$this->controller = new DailyController($this->container);
|
||||||
|
DailyController::$DAILY_RSS_NB_DAYS = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testValidControllerInvokeDefault(): void
|
public function testValidIndexControllerInvokeDefault(): void
|
||||||
{
|
{
|
||||||
$this->createValidContainerMockSet();
|
$this->createValidContainerMockSet();
|
||||||
|
|
||||||
|
@ -173,7 +176,7 @@ public function testValidControllerInvokeDefault(): void
|
||||||
/**
|
/**
|
||||||
* Daily page - test that everything goes fine with no future or past bookmarks
|
* Daily page - test that everything goes fine with no future or past bookmarks
|
||||||
*/
|
*/
|
||||||
public function testValidControllerInvokeNoFutureOrPast(): void
|
public function testValidIndexControllerInvokeNoFutureOrPast(): void
|
||||||
{
|
{
|
||||||
$this->createValidContainerMockSet();
|
$this->createValidContainerMockSet();
|
||||||
|
|
||||||
|
@ -247,7 +250,7 @@ public function testValidControllerInvokeNoFutureOrPast(): void
|
||||||
/**
|
/**
|
||||||
* Daily page - test that height adjustment in columns is working
|
* Daily page - test that height adjustment in columns is working
|
||||||
*/
|
*/
|
||||||
public function testValidControllerInvokeHeightAdjustment(): void
|
public function testValidIndexControllerInvokeHeightAdjustment(): void
|
||||||
{
|
{
|
||||||
$this->createValidContainerMockSet();
|
$this->createValidContainerMockSet();
|
||||||
|
|
||||||
|
@ -318,7 +321,7 @@ public function testValidControllerInvokeHeightAdjustment(): void
|
||||||
/**
|
/**
|
||||||
* Daily page - no bookmark
|
* Daily page - no bookmark
|
||||||
*/
|
*/
|
||||||
public function testValidControllerInvokeNoBookmark(): void
|
public function testValidIndexControllerInvokeNoBookmark(): void
|
||||||
{
|
{
|
||||||
$this->createValidContainerMockSet();
|
$this->createValidContainerMockSet();
|
||||||
|
|
||||||
|
@ -364,6 +367,136 @@ public function testValidControllerInvokeNoBookmark(): void
|
||||||
static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']);
|
static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daily RSS - default behaviour
|
||||||
|
*/
|
||||||
|
public function testValidRssControllerInvokeDefault(): void
|
||||||
|
{
|
||||||
|
$this->createValidContainerMockSet();
|
||||||
|
|
||||||
|
$dates = [
|
||||||
|
new \DateTimeImmutable('2020-05-17'),
|
||||||
|
new \DateTimeImmutable('2020-05-15'),
|
||||||
|
new \DateTimeImmutable('2020-05-13'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$this->container->bookmarkService->expects(static::once())->method('search')->willReturn([
|
||||||
|
(new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'),
|
||||||
|
(new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'),
|
||||||
|
(new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'),
|
||||||
|
(new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->container->pageCacheManager
|
||||||
|
->expects(static::once())
|
||||||
|
->method('getCachePage')
|
||||||
|
->willReturnCallback(function (): CachedPage {
|
||||||
|
$cachedPage = $this->createMock(CachedPage::class);
|
||||||
|
$cachedPage->expects(static::once())->method('cache')->with('dailyrss');
|
||||||
|
|
||||||
|
return $cachedPage;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save RainTPL assigned variables
|
||||||
|
$assignedVariables = [];
|
||||||
|
$this->assignTemplateVars($assignedVariables);
|
||||||
|
|
||||||
|
$result = $this->controller->rss($request, $response);
|
||||||
|
|
||||||
|
static::assertSame(200, $result->getStatusCode());
|
||||||
|
static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
|
||||||
|
static::assertSame('dailyrss', (string) $result->getBody());
|
||||||
|
static::assertSame('Shaarli', $assignedVariables['title']);
|
||||||
|
static::assertSame('http://shaarli', $assignedVariables['index_url']);
|
||||||
|
static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']);
|
||||||
|
static::assertFalse($assignedVariables['hide_timestamps']);
|
||||||
|
static::assertCount(2, $assignedVariables['days']);
|
||||||
|
|
||||||
|
$day = $assignedVariables['days'][$dates[0]->format('Ymd')];
|
||||||
|
|
||||||
|
static::assertEquals($dates[0], $day['date']);
|
||||||
|
static::assertSame($dates[0]->format(\DateTimeInterface::RSS), $day['date_rss']);
|
||||||
|
static::assertSame(format_date($dates[0], false), $day['date_human']);
|
||||||
|
static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']);
|
||||||
|
static::assertCount(1, $day['links']);
|
||||||
|
static::assertSame(1, $day['links'][0]['id']);
|
||||||
|
static::assertSame('http://domain.tld/1', $day['links'][0]['url']);
|
||||||
|
static::assertEquals($dates[0], $day['links'][0]['created']);
|
||||||
|
|
||||||
|
$day = $assignedVariables['days'][$dates[1]->format('Ymd')];
|
||||||
|
|
||||||
|
static::assertEquals($dates[1], $day['date']);
|
||||||
|
static::assertSame($dates[1]->format(\DateTimeInterface::RSS), $day['date_rss']);
|
||||||
|
static::assertSame(format_date($dates[1], false), $day['date_human']);
|
||||||
|
static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']);
|
||||||
|
static::assertCount(2, $day['links']);
|
||||||
|
|
||||||
|
static::assertSame(2, $day['links'][0]['id']);
|
||||||
|
static::assertSame('http://domain.tld/2', $day['links'][0]['url']);
|
||||||
|
static::assertEquals($dates[1], $day['links'][0]['created']);
|
||||||
|
static::assertSame(3, $day['links'][1]['id']);
|
||||||
|
static::assertSame('http://domain.tld/3', $day['links'][1]['url']);
|
||||||
|
static::assertEquals($dates[1], $day['links'][1]['created']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daily RSS - trigger cache rendering
|
||||||
|
*/
|
||||||
|
public function testValidRssControllerInvokeTriggerCache(): void
|
||||||
|
{
|
||||||
|
$this->createValidContainerMockSet();
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$this->container->pageCacheManager->method('getCachePage')->willReturnCallback(function (): CachedPage {
|
||||||
|
$cachedPage = $this->createMock(CachedPage::class);
|
||||||
|
$cachedPage->method('cachedVersion')->willReturn('this is cache!');
|
||||||
|
|
||||||
|
return $cachedPage;
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->container->bookmarkService->expects(static::never())->method('search');
|
||||||
|
|
||||||
|
$result = $this->controller->rss($request, $response);
|
||||||
|
|
||||||
|
static::assertSame(200, $result->getStatusCode());
|
||||||
|
static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
|
||||||
|
static::assertSame('this is cache!', (string) $result->getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daily RSS - No bookmark
|
||||||
|
*/
|
||||||
|
public function testValidRssControllerInvokeNoBookmark(): void
|
||||||
|
{
|
||||||
|
$this->createValidContainerMockSet();
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]);
|
||||||
|
|
||||||
|
// Save RainTPL assigned variables
|
||||||
|
$assignedVariables = [];
|
||||||
|
$this->assignTemplateVars($assignedVariables);
|
||||||
|
|
||||||
|
$result = $this->controller->rss($request, $response);
|
||||||
|
|
||||||
|
static::assertSame(200, $result->getStatusCode());
|
||||||
|
static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
|
||||||
|
static::assertSame('dailyrss', (string) $result->getBody());
|
||||||
|
static::assertSame('Shaarli', $assignedVariables['title']);
|
||||||
|
static::assertSame('http://shaarli', $assignedVariables['index_url']);
|
||||||
|
static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']);
|
||||||
|
static::assertFalse($assignedVariables['hide_timestamps']);
|
||||||
|
static::assertCount(0, $assignedVariables['days']);
|
||||||
|
}
|
||||||
|
|
||||||
protected function createValidContainerMockSet(): void
|
protected function createValidContainerMockSet(): void
|
||||||
{
|
{
|
||||||
$loginManager = $this->createMock(LoginManager::class);
|
$loginManager = $this->createMock(LoginManager::class);
|
||||||
|
@ -403,6 +536,17 @@ protected function createValidContainerMockSet(): void
|
||||||
})
|
})
|
||||||
;
|
;
|
||||||
$this->container->formatterFactory = $formatterFactory;
|
$this->container->formatterFactory = $formatterFactory;
|
||||||
|
|
||||||
|
// CacheManager
|
||||||
|
$pageCacheManager = $this->createMock(PageCacheManager::class);
|
||||||
|
$this->container->pageCacheManager = $pageCacheManager;
|
||||||
|
|
||||||
|
// $_SERVER
|
||||||
|
$this->container->environment = [
|
||||||
|
'SERVER_NAME' => 'shaarli',
|
||||||
|
'SERVER_PORT' => '80',
|
||||||
|
'REQUEST_URI' => '/daily-rss',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function assignTemplateVars(array &$variables): void
|
protected function assignTemplateVars(array &$variables): void
|
||||||
|
|
|
@ -71,4 +71,36 @@ public function testOtherResource()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The route is stored in REQUEST_URI
|
||||||
|
*/
|
||||||
|
public function testPageUrlWithRoute()
|
||||||
|
{
|
||||||
|
$this->assertEquals(
|
||||||
|
'http://host.tld/picture-wall',
|
||||||
|
page_url(
|
||||||
|
array(
|
||||||
|
'HTTPS' => 'Off',
|
||||||
|
'SERVER_NAME' => 'host.tld',
|
||||||
|
'SERVER_PORT' => '80',
|
||||||
|
'SCRIPT_NAME' => '/index.php',
|
||||||
|
'REQUEST_URI' => '/picture-wall',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'http://host.tld/admin/picture-wall',
|
||||||
|
page_url(
|
||||||
|
array(
|
||||||
|
'HTTPS' => 'Off',
|
||||||
|
'SERVER_NAME' => 'host.tld',
|
||||||
|
'SERVER_PORT' => '80',
|
||||||
|
'SCRIPT_NAME' => '/admin/index.php',
|
||||||
|
'REQUEST_URI' => '/admin/picture-wall',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class PageCacheManagerTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
$this->cacheManager = new PageCacheManager(static::$testCacheDir);
|
$this->cacheManager = new PageCacheManager(static::$testCacheDir, true);
|
||||||
|
|
||||||
if (!is_dir(self::$testCacheDir)) {
|
if (!is_dir(self::$testCacheDir)) {
|
||||||
mkdir(self::$testCacheDir);
|
mkdir(self::$testCacheDir);
|
||||||
|
@ -73,7 +73,7 @@ public function testPurgeCachedPages()
|
||||||
*/
|
*/
|
||||||
public function testPurgeCachedPagesMissingDir()
|
public function testPurgeCachedPagesMissingDir()
|
||||||
{
|
{
|
||||||
$this->cacheManager = new PageCacheManager(self::$testCacheDir . '_missing');
|
$this->cacheManager = new PageCacheManager(self::$testCacheDir . '_missing', true);
|
||||||
|
|
||||||
$oldlog = ini_get('error_log');
|
$oldlog = ini_get('error_log');
|
||||||
ini_set('error_log', '/dev/null');
|
ini_set('error_log', '/dev/null');
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<div class="pure-u-lg-2-3 pure-u-22-24 page-form page-visitor" id="daily">
|
<div class="pure-u-lg-2-3 pure-u-22-24 page-form page-visitor" id="daily">
|
||||||
<h2 class="window-title">
|
<h2 class="window-title">
|
||||||
{'The Daily Shaarli'|t}
|
{'The Daily Shaarli'|t}
|
||||||
<a href="./?do=dailyrss" title="{'1 RSS entry per day'|t}"><i class="fa fa-rss"></i></a>
|
<a href="./daily-rss" title="{'1 RSS entry per day'|t}"><i class="fa fa-rss"></i></a>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div id="plugin_zone_start_daily" class="plugin_zone">
|
<div id="plugin_zone_start_daily" class="plugin_zone">
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
<item>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<title>{$title} - {function="strftime('%A %e %B %Y', $daydate)"}</title>
|
<rss version="2.0">
|
||||||
<guid>{$absurl}</guid>
|
<channel>
|
||||||
<link>{$absurl}</link>
|
<title>Daily - {$title}</title>
|
||||||
<pubDate>{$rssdate}</pubDate>
|
<link>{$index_url}</link>
|
||||||
<description><![CDATA[
|
<description>Daily shaared bookmarks</description>
|
||||||
{loop="links"}
|
<language>{$language}</language>
|
||||||
<h3><a href="{$value.url}">{$value.title}</a></h3>
|
<copyright>{$index_url}</copyright>
|
||||||
<small>{if="!$hide_timestamps"}{function="strftime('%c', $value.timestamp)"} - {/if}{if="$value.tags"}{$value.tags}{/if}<br>
|
<generator>Shaarli</generator>
|
||||||
{$value.url}</small><br>
|
|
||||||
{if="$value.thumbnail"}<img src="{$index_url}{$value.thumbnail}#" alt="thumbnail" />{/if}<br>
|
{loop="$days"}
|
||||||
{if="$value.description"}{$value.formatedDescription}{/if}
|
<item>
|
||||||
<br><br><hr>
|
<title>{$value.date_human} - {$title}</title>
|
||||||
{/loop}
|
<guid>{$value.absolute_url}</guid>
|
||||||
]]></description>
|
<link>{$value.absolute_url}</link>
|
||||||
</item>
|
<pubDate>{$value.date_rss}</pubDate>
|
||||||
|
<description><![CDATA[
|
||||||
|
{loop="$value.links"}
|
||||||
|
<h3><a href="{$value.url}">{$value.title}</a></h3>
|
||||||
|
<small>
|
||||||
|
{if="!$hide_timestamps"}{$value.created|format_date} - {/if}{if="$value.tags"}{$value.tags}{/if}<br>
|
||||||
|
{$value.url}
|
||||||
|
</small><br>
|
||||||
|
{if="$value.thumbnail"}<img src="{$index_url}{$value.thumbnail}#" alt="thumbnail" />{/if}<br>
|
||||||
|
{if="$value.description"}{$value.description}{/if}
|
||||||
|
<br><br><hr>
|
||||||
|
{/loop}
|
||||||
|
]]></description>
|
||||||
|
</item>
|
||||||
|
{/loop}
|
||||||
|
</channel>
|
||||||
|
</rss><!-- Cached version of {$page_url} -->
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
{/loop}
|
{/loop}
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<a href="./?do=dailyrss" title="1 RSS entry per day"><img src="img/feed-icon-14x14.png" alt="rss_feed">Daily RSS Feed</a>
|
<a href="./daily-rss" title="1 RSS entry per day"><img src="img/feed-icon-14x14.png" alt="rss_feed">Daily RSS Feed</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dailyTitle">
|
<div class="dailyTitle">
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
<item>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<title>{$title} - {function="strftime('%A %e %B %Y', $daydate)"}</title>
|
<rss version="2.0">
|
||||||
<guid>{$absurl}</guid>
|
<channel>
|
||||||
<link>{$absurl}</link>
|
<title>Daily - {$title}</title>
|
||||||
<pubDate>{$rssdate}</pubDate>
|
<link>{$index_url}</link>
|
||||||
<description><![CDATA[
|
<description>Daily shaared bookmarks</description>
|
||||||
{loop="links"}
|
<language>{$language}</language>
|
||||||
<h3><a href="{$value.url}">{$value.title}</a></h3>
|
<copyright>{$index_url}</copyright>
|
||||||
<small>{if="!$hide_timestamps"}{function="strftime('%c', $value.timestamp)"} - {/if}{if="$value.tags"}{$value.tags}{/if}<br>
|
<generator>Shaarli</generator>
|
||||||
{$value.url}</small><br>
|
|
||||||
{if="$value.thumbnail"}<img src="{$index_url}{$value.thumbnail}#" alt="thumbnail" />{/if}<br>
|
{loop="$days"}
|
||||||
{if="$value.description"}{$value.formatedDescription}{/if}
|
<item>
|
||||||
<br><br><hr>
|
<title>{$value.date_human} - {$title}</title>
|
||||||
|
<guid>{$value.absolute_url}</guid>
|
||||||
|
<link>{$value.absolute_url}</link>
|
||||||
|
<pubDate>{$value.date_rss}</pubDate>
|
||||||
|
<description><![CDATA[
|
||||||
|
{loop="$value.links"}
|
||||||
|
<h3><a href="{$value.url}">{$value.title}</a></h3>
|
||||||
|
<small>
|
||||||
|
{if="!$hide_timestamps"}{$value.created|format_date} - {/if}{if="$value.tags"}{$value.tags}{/if}<br>
|
||||||
|
{$value.url}
|
||||||
|
</small><br>
|
||||||
|
{if="$value.thumbnail"}<img src="{$index_url}{$value.thumbnail}#" alt="thumbnail" />{/if}<br>
|
||||||
|
{if="$value.description"}{$value.description}{/if}
|
||||||
|
<br><br><hr>
|
||||||
{/loop}
|
{/loop}
|
||||||
]]></description>
|
]]></description>
|
||||||
</item>
|
</item>
|
||||||
|
{/loop}
|
||||||
|
</channel>
|
||||||
|
</rss><!-- Cached version of {$page_url} -->
|
||||||
|
|
Loading…
Reference in a new issue