]> git.immae.eu Git - github/shaarli/Shaarli.git/commitdiff
Process daily page through Slim controller
authorArthurHoaro <arthur@hoa.ro>
Sun, 17 May 2020 09:06:39 +0000 (11:06 +0200)
committerArthurHoaro <arthur@hoa.ro>
Thu, 23 Jul 2020 19:19:21 +0000 (21:19 +0200)
application/Utils.php
application/bookmark/BookmarkFilter.php
application/front/controllers/DailyController.php [new file with mode: 0644]
index.php
tests/front/controller/DailyControllerTest.php [new file with mode: 0644]
tpl/default/daily.html

index 4e97cddae26267f6e3c9b4e8a472c7a56aaf597b..72c90049b9b41c3e7926bede39c4caf6facc2a6a 100644 (file)
@@ -294,15 +294,15 @@ function normalize_spaces($string)
  * Requires php-intl to display international datetimes,
  * otherwise default format '%c' will be returned.
  *
- * @param DateTime $date to format.
- * @param bool     $time Displays time if true.
- * @param bool     $intl Use international format if true.
+ * @param DateTimeInterface $date to format.
+ * @param bool              $time Displays time if true.
+ * @param bool              $intl Use international format if true.
  *
  * @return bool|string Formatted date, or false if the input is invalid.
  */
 function format_date($date, $time = true, $intl = true)
 {
-    if (! $date instanceof DateTime) {
+    if (! $date instanceof DateTimeInterface) {
         return false;
     }
 
index fd5566790447838e0b7566e09f12695ffe680b0f..797a36b8ecd54c34a7aaea1ac63d3db0c2496bc8 100644 (file)
@@ -436,7 +436,7 @@ class BookmarkFilter
             throw new Exception('Invalid date format');
         }
 
-        $filtered = array();
+        $filtered = [];
         foreach ($this->bookmarks as $key => $l) {
             if ($l->getCreated()->format('Ymd') == $day) {
                 $filtered[$key] = $l;
diff --git a/application/front/controllers/DailyController.php b/application/front/controllers/DailyController.php
new file mode 100644 (file)
index 0000000..c2fdaa5
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shaarli\Front\Controller;
+
+use DateTime;
+use Shaarli\Bookmark\Bookmark;
+use Slim\Http\Request;
+use Slim\Http\Response;
+
+/**
+ * Class DailyController
+ *
+ * Slim controller used to render the daily page.
+ *
+ * @package Front\Controller
+ */
+class DailyController extends ShaarliController
+{
+    /**
+     * Controller displaying all bookmarks published in a single day.
+     * It take a `day` date query parameter (format YYYYMMDD).
+     */
+    public function index(Request $request, Response $response): Response
+    {
+        $day = $request->getQueryParam('day') ?? date('Ymd');
+
+        $availableDates = $this->container->bookmarkService->days();
+        $nbAvailableDates = count($availableDates);
+        $index = array_search($day, $availableDates);
+
+        if ($index === false && $nbAvailableDates > 0) {
+            // no bookmarks for day, but at least one day with bookmarks
+            $index = $nbAvailableDates - 1;
+            $day = $availableDates[$index];
+        }
+
+        if ($day === date('Ymd')) {
+            $this->assignView('dayDesc', t('Today'));
+        } elseif ($day === date('Ymd', strtotime('-1 days'))) {
+            $this->assignView('dayDesc', t('Yesterday'));
+        }
+
+        if ($index !== false) {
+            if ($index >= 1) {
+                $previousDay = $availableDates[$index - 1];
+            }
+            if ($index < $nbAvailableDates - 1) {
+                $nextDay = $availableDates[$index + 1];
+            }
+        }
+
+        try {
+            $linksToDisplay = $this->container->bookmarkService->filterDay($day);
+        } catch (\Exception $exc) {
+            $linksToDisplay = [];
+        }
+
+        $formatter = $this->container->formatterFactory->getFormatter();
+        // We pre-format some fields for proper output.
+        foreach ($linksToDisplay as $key => $bookmark) {
+            $linksToDisplay[$key] = $formatter->format($bookmark);
+            // This page is a bit specific, we need raw description to calculate the length
+            $linksToDisplay[$key]['formatedDescription'] = $linksToDisplay[$key]['description'];
+            $linksToDisplay[$key]['description'] = $bookmark->getDescription();
+        }
+
+        $dayDate = DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, $day.'_000000');
+        $data = [
+            'linksToDisplay' => $linksToDisplay,
+            'day' => $dayDate->getTimestamp(),
+            'dayDate' => $dayDate,
+            'previousday' => $previousDay ?? '',
+            'nextday' => $nextDay ?? '',
+        ];
+
+        // Hooks are called before column construction so that plugins don't have to deal with columns.
+        $this->executeHooks($data);
+
+        $data['cols'] = $this->calculateColumns($data['linksToDisplay']);
+
+        foreach ($data as $key => $value) {
+            $this->assignView($key, $value);
+        }
+
+        $mainTitle = $this->container->conf->get('general.title', 'Shaarli');
+        $this->assignView(
+            'pagetitle',
+            t('Daily') .' - '. format_date($dayDate, false) . ' - ' . $mainTitle
+        );
+
+        return $response->write($this->render('daily'));
+    }
+
+    /**
+     * We need to spread the articles on 3 columns.
+     * did not want to use a JavaScript lib like http://masonry.desandro.com/
+     * so I manually spread entries with a simple method: I roughly evaluate the
+     * height of a div according to title and description length.
+     */
+    protected function calculateColumns(array $links): array
+    {
+        // Entries to display, for each column.
+        $columns = [[], [], []];
+        // Rough estimate of columns fill.
+        $fill = [0, 0, 0];
+        foreach ($links as $link) {
+            // Roughly estimate length of entry (by counting characters)
+            // Title: 30 chars = 1 line. 1 line is 30 pixels height.
+            // Description: 836 characters gives roughly 342 pixel height.
+            // This is not perfect, but it's usually OK.
+            $length = strlen($link['title'] ?? '') + (342 * strlen($link['description'] ?? '')) / 836;
+            if (! empty($link['thumbnail'])) {
+                $length += 100; // 1 thumbnails roughly takes 100 pixels height.
+            }
+            // Then put in column which is the less filled:
+            $smallest = min($fill); // find smallest value in array.
+            $index = array_search($smallest, $fill); // find index of this smallest value.
+            array_push($columns[$index], $link); // Put entry in this column.
+            $fill[$index] += $length;
+        }
+
+        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;
+    }
+}
index 89a1e5814c81ff82677b61f78d642bae34e8b18e..f8337d79a6bc6f700ee1bd63afcf2014c0188ce4 100644 (file)
--- a/index.php
+++ b/index.php
@@ -398,112 +398,6 @@ function showDailyRSS($bookmarkService, $conf, $loginManager)
     exit;
 }
 
-/**
- * Show the 'Daily' page.
- *
- * @param PageBuilder              $pageBuilder     Template engine wrapper.
- * @param BookmarkServiceInterface $bookmarkService instance.
- * @param ConfigManager            $conf            Configuration Manager instance.
- * @param PluginManager            $pluginManager   Plugin Manager instance.
- * @param LoginManager             $loginManager    Login Manager instance
- */
-function showDaily($pageBuilder, $bookmarkService, $conf, $pluginManager, $loginManager)
-{
-    if (isset($_GET['day'])) {
-        $day = $_GET['day'];
-        if ($day === date('Ymd', strtotime('now'))) {
-            $pageBuilder->assign('dayDesc', t('Today'));
-        } elseif ($day === date('Ymd', strtotime('-1 days'))) {
-            $pageBuilder->assign('dayDesc', t('Yesterday'));
-        }
-    } else {
-        $day = date('Ymd', strtotime('now')); // Today, in format YYYYMMDD.
-        $pageBuilder->assign('dayDesc', t('Today'));
-    }
-
-    $days = $bookmarkService->days();
-    $i = array_search($day, $days);
-    if ($i === false && count($days)) {
-        // no bookmarks for day, but at least one day with bookmarks
-        $i = count($days) - 1;
-        $day = $days[$i];
-    }
-    $previousday = '';
-    $nextday = '';
-
-    if ($i !== false) {
-        if ($i >= 1) {
-             $previousday = $days[$i - 1];
-        }
-        if ($i < count($days) - 1) {
-            $nextday = $days[$i + 1];
-        }
-    }
-    try {
-        $linksToDisplay = $bookmarkService->filterDay($day);
-    } catch (Exception $exc) {
-        error_log($exc);
-        $linksToDisplay = [];
-    }
-
-    $factory = new FormatterFactory($conf, $loginManager->isLoggedIn());
-    $formatter = $factory->getFormatter();
-    // We pre-format some fields for proper output.
-    foreach ($linksToDisplay as $key => $bookmark) {
-        $linksToDisplay[$key] = $formatter->format($bookmark);
-        // This page is a bit specific, we need raw description to calculate the length
-        $linksToDisplay[$key]['formatedDescription'] = $linksToDisplay[$key]['description'];
-        $linksToDisplay[$key]['description'] = $bookmark->getDescription();
-    }
-
-    $dayDate = DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, $day.'_000000');
-    $data = array(
-        'pagetitle' => $conf->get('general.title') .' - '. format_date($dayDate, false),
-        'linksToDisplay' => $linksToDisplay,
-        'day' => $dayDate->getTimestamp(),
-        'dayDate' => $dayDate,
-        'previousday' => $previousday,
-        'nextday' => $nextday,
-    );
-
-    /* Hook is called before column construction so that plugins don't have
-       to deal with columns. */
-    $pluginManager->executeHooks('render_daily', $data, array('loggedin' => $loginManager->isLoggedIn()));
-
-    /* We need to spread the articles on 3 columns.
-       I did not want to use a JavaScript lib like http://masonry.desandro.com/
-       so I manually spread entries with a simple method: I roughly evaluate the
-       height of a div according to title and description length.
-    */
-    $columns = array(array(), array(), array()); // Entries to display, for each column.
-    $fill = array(0, 0, 0);  // Rough estimate of columns fill.
-    foreach ($data['linksToDisplay'] as $key => $bookmark) {
-        // Roughly estimate length of entry (by counting characters)
-        // Title: 30 chars = 1 line. 1 line is 30 pixels height.
-        // Description: 836 characters gives roughly 342 pixel height.
-        // This is not perfect, but it's usually OK.
-        $length = strlen($bookmark['title']) + (342 * strlen($bookmark['description'])) / 836;
-        if (! empty($bookmark['thumbnail'])) {
-            $length += 100; // 1 thumbnails roughly takes 100 pixels height.
-        }
-        // Then put in column which is the less filled:
-        $smallest = min($fill); // find smallest value in array.
-        $index = array_search($smallest, $fill); // find index of this smallest value.
-        array_push($columns[$index], $bookmark); // Put entry in this column.
-        $fill[$index] += $length;
-    }
-
-    $data['cols'] = $columns;
-
-    foreach ($data as $key => $value) {
-        $pageBuilder->assign($key, $value);
-    }
-
-    $pageBuilder->assign('pagetitle', t('Daily') .' - '. $conf->get('general.title', 'Shaarli'));
-    $pageBuilder->renderPage('daily');
-    exit;
-}
-
 /**
  * Renders the linklist
  *
@@ -628,7 +522,8 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
 
     // Daily page.
     if ($targetPage == Router::$PAGE_DAILY) {
-        showDaily($PAGE, $bookmarkService, $conf, $pluginManager, $loginManager);
+        header('Location: ./daily');
+        exit;
     }
 
     // ATOM and RSS feed.
@@ -1850,6 +1745,8 @@ $app->group('', function () {
     $this->get('/picture-wall', '\Shaarli\Front\Controller\PictureWallController:index')->setName('picwall');
     $this->get('/tag-cloud', '\Shaarli\Front\Controller\TagCloudController:cloud')->setName('tagcloud');
     $this->get('/tag-list', '\Shaarli\Front\Controller\TagCloudController:list')->setName('taglist');
+    $this->get('/daily', '\Shaarli\Front\Controller\DailyController:index')->setName('daily');
+
     $this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\TagController:addTag')->setName('add-tag');
 })->add('\Shaarli\Front\ShaarliMiddleware');
 
diff --git a/tests/front/controller/DailyControllerTest.php b/tests/front/controller/DailyControllerTest.php
new file mode 100644 (file)
index 0000000..bb453d5
--- /dev/null
@@ -0,0 +1,423 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shaarli\Front\Controller;
+
+use PHPUnit\Framework\TestCase;
+use Shaarli\Bookmark\Bookmark;
+use Shaarli\Bookmark\BookmarkServiceInterface;
+use Shaarli\Config\ConfigManager;
+use Shaarli\Container\ShaarliContainer;
+use Shaarli\Formatter\BookmarkFormatter;
+use Shaarli\Formatter\BookmarkRawFormatter;
+use Shaarli\Formatter\FormatterFactory;
+use Shaarli\Plugin\PluginManager;
+use Shaarli\Render\PageBuilder;
+use Shaarli\Security\LoginManager;
+use Slim\Http\Request;
+use Slim\Http\Response;
+
+class DailyControllerTest extends TestCase
+{
+    /** @var ShaarliContainer */
+    protected $container;
+
+    /** @var DailyController */
+    protected $controller;
+
+    public function setUp(): void
+    {
+        $this->container = $this->createMock(ShaarliContainer::class);
+        $this->controller = new DailyController($this->container);
+    }
+
+    public function testValidControllerInvokeDefault(): void
+    {
+        $this->createValidContainerMockSet();
+
+        $currentDay = new \DateTimeImmutable('2020-05-13');
+
+        $request = $this->createMock(Request::class);
+        $request->method('getQueryParam')->willReturn($currentDay->format('Ymd'));
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        // Links dataset: 2 links with thumbnails
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('days')
+            ->willReturnCallback(function () use ($currentDay): array {
+               return [
+                   '20200510',
+                   $currentDay->format('Ymd'),
+                   '20200516',
+               ];
+            })
+        ;
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('filterDay')
+            ->willReturnCallback(function (): array {
+                return [
+                    (new Bookmark())
+                        ->setId(1)
+                        ->setUrl('http://url.tld')
+                        ->setTitle(static::generateContent(50))
+                        ->setDescription(static::generateContent(500))
+                    ,
+                    (new Bookmark())
+                        ->setId(2)
+                        ->setUrl('http://url2.tld')
+                        ->setTitle(static::generateContent(50))
+                        ->setDescription(static::generateContent(500))
+                    ,
+                    (new Bookmark())
+                        ->setId(3)
+                        ->setUrl('http://url3.tld')
+                        ->setTitle(static::generateContent(50))
+                        ->setDescription(static::generateContent(500))
+                    ,
+                ];
+            })
+        ;
+
+        // Make sure that PluginManager hook is triggered
+        $this->container->pluginManager
+            ->expects(static::at(0))
+            ->method('executeHooks')
+            ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array {
+                static::assertSame('render_daily', $hook);
+
+                static::assertArrayHasKey('linksToDisplay', $data);
+                static::assertCount(3, $data['linksToDisplay']);
+                static::assertSame(1, $data['linksToDisplay'][0]['id']);
+                static::assertSame($currentDay->getTimestamp(), $data['day']);
+                static::assertSame('20200510', $data['previousday']);
+                static::assertSame('20200516', $data['nextday']);
+
+                static::assertArrayHasKey('loggedin', $param);
+
+                return $data;
+            });
+
+        $result = $this->controller->index($request, $response);
+
+        static::assertSame(200, $result->getStatusCode());
+        static::assertSame('daily', (string) $result->getBody());
+        static::assertSame(
+            'Daily - '. format_date($currentDay, false, true) .' - Shaarli',
+            $assignedVariables['pagetitle']
+        );
+        static::assertCount(3, $assignedVariables['linksToDisplay']);
+
+        $link = $assignedVariables['linksToDisplay'][0];
+
+        static::assertSame(1, $link['id']);
+        static::assertSame('http://url.tld', $link['url']);
+        static::assertNotEmpty($link['title']);
+        static::assertNotEmpty($link['description']);
+        static::assertNotEmpty($link['formatedDescription']);
+
+        $link = $assignedVariables['linksToDisplay'][1];
+
+        static::assertSame(2, $link['id']);
+        static::assertSame('http://url2.tld', $link['url']);
+        static::assertNotEmpty($link['title']);
+        static::assertNotEmpty($link['description']);
+        static::assertNotEmpty($link['formatedDescription']);
+
+        $link = $assignedVariables['linksToDisplay'][2];
+
+        static::assertSame(3, $link['id']);
+        static::assertSame('http://url3.tld', $link['url']);
+        static::assertNotEmpty($link['title']);
+        static::assertNotEmpty($link['description']);
+        static::assertNotEmpty($link['formatedDescription']);
+
+        static::assertCount(3, $assignedVariables['cols']);
+        static::assertCount(1, $assignedVariables['cols'][0]);
+        static::assertCount(1, $assignedVariables['cols'][1]);
+        static::assertCount(1, $assignedVariables['cols'][2]);
+
+        $link = $assignedVariables['cols'][0][0];
+
+        static::assertSame(1, $link['id']);
+        static::assertSame('http://url.tld', $link['url']);
+        static::assertNotEmpty($link['title']);
+        static::assertNotEmpty($link['description']);
+        static::assertNotEmpty($link['formatedDescription']);
+
+        $link = $assignedVariables['cols'][1][0];
+
+        static::assertSame(2, $link['id']);
+        static::assertSame('http://url2.tld', $link['url']);
+        static::assertNotEmpty($link['title']);
+        static::assertNotEmpty($link['description']);
+        static::assertNotEmpty($link['formatedDescription']);
+
+        $link = $assignedVariables['cols'][2][0];
+
+        static::assertSame(3, $link['id']);
+        static::assertSame('http://url3.tld', $link['url']);
+        static::assertNotEmpty($link['title']);
+        static::assertNotEmpty($link['description']);
+        static::assertNotEmpty($link['formatedDescription']);
+    }
+
+    /**
+     * Daily page - test that everything goes fine with no future or past bookmarks
+     */
+    public function testValidControllerInvokeNoFutureOrPast(): void
+    {
+        $this->createValidContainerMockSet();
+
+        $currentDay = new \DateTimeImmutable('2020-05-13');
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        // Links dataset: 2 links with thumbnails
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('days')
+            ->willReturnCallback(function () use ($currentDay): array {
+                return [
+                    $currentDay->format($currentDay->format('Ymd')),
+                ];
+            })
+        ;
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('filterDay')
+            ->willReturnCallback(function (): array {
+                return [
+                    (new Bookmark())
+                        ->setId(1)
+                        ->setUrl('http://url.tld')
+                        ->setTitle(static::generateContent(50))
+                        ->setDescription(static::generateContent(500))
+                    ,
+                ];
+            })
+        ;
+
+        // Make sure that PluginManager hook is triggered
+        $this->container->pluginManager
+            ->expects(static::at(0))
+            ->method('executeHooks')
+            ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array {
+                static::assertSame('render_daily', $hook);
+
+                static::assertArrayHasKey('linksToDisplay', $data);
+                static::assertCount(1, $data['linksToDisplay']);
+                static::assertSame(1, $data['linksToDisplay'][0]['id']);
+                static::assertSame($currentDay->getTimestamp(), $data['day']);
+                static::assertEmpty($data['previousday']);
+                static::assertEmpty($data['nextday']);
+
+                static::assertArrayHasKey('loggedin', $param);
+
+                return $data;
+            });
+
+        $result = $this->controller->index($request, $response);
+
+        static::assertSame(200, $result->getStatusCode());
+        static::assertSame('daily', (string) $result->getBody());
+        static::assertSame(
+            'Daily - '. format_date($currentDay, false, true) .' - Shaarli',
+            $assignedVariables['pagetitle']
+        );
+        static::assertCount(1, $assignedVariables['linksToDisplay']);
+
+        $link = $assignedVariables['linksToDisplay'][0];
+        static::assertSame(1, $link['id']);
+    }
+
+    /**
+     * Daily page - test that height adjustment in columns is working
+     */
+    public function testValidControllerInvokeHeightAdjustment(): void
+    {
+        $this->createValidContainerMockSet();
+
+        $currentDay = new \DateTimeImmutable('2020-05-13');
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        // Links dataset: 2 links with thumbnails
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('days')
+            ->willReturnCallback(function () use ($currentDay): array {
+                return [
+                    $currentDay->format($currentDay->format('Ymd')),
+                ];
+            })
+        ;
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('filterDay')
+            ->willReturnCallback(function (): array {
+                return [
+                    (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'),
+                    (new Bookmark())
+                        ->setId(2)
+                        ->setUrl('http://url.tld')
+                        ->setTitle(static::generateContent(50))
+                        ->setDescription(static::generateContent(5000))
+                    ,
+                    (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'),
+                    (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'),
+                    (new Bookmark())->setId(5)->setUrl('http://url.tld')->setTitle('title'),
+                    (new Bookmark())->setId(6)->setUrl('http://url.tld')->setTitle('title'),
+                    (new Bookmark())->setId(7)->setUrl('http://url.tld')->setTitle('title'),
+                ];
+            })
+        ;
+
+        // Make sure that PluginManager hook is triggered
+        $this->container->pluginManager
+            ->expects(static::at(0))
+            ->method('executeHooks')
+            ->willReturnCallback(function (string $hook, array $data, array $param): array {
+                return $data;
+            })
+        ;
+
+        $result = $this->controller->index($request, $response);
+
+        static::assertSame(200, $result->getStatusCode());
+        static::assertSame('daily', (string) $result->getBody());
+        static::assertCount(7, $assignedVariables['linksToDisplay']);
+
+        $columnIds = function (array $column): array {
+            return array_map(function (array $item): int { return $item['id']; }, $column);
+        };
+
+        static::assertSame([1, 4, 6], $columnIds($assignedVariables['cols'][0]));
+        static::assertSame([2], $columnIds($assignedVariables['cols'][1]));
+        static::assertSame([3, 5, 7], $columnIds($assignedVariables['cols'][2]));
+    }
+
+    /**
+     * Daily page - no bookmark
+     */
+    public function testValidControllerInvokeNoBookmark(): void
+    {
+        $this->createValidContainerMockSet();
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        // Links dataset: 2 links with thumbnails
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('days')
+            ->willReturnCallback(function (): array {
+                return [];
+            })
+        ;
+        $this->container->bookmarkService
+            ->expects(static::once())
+            ->method('filterDay')
+            ->willReturnCallback(function (): array {
+                return [];
+            })
+        ;
+
+        // Make sure that PluginManager hook is triggered
+        $this->container->pluginManager
+            ->expects(static::at(0))
+            ->method('executeHooks')
+            ->willReturnCallback(function (string $hook, array $data, array $param): array {
+                return $data;
+            })
+        ;
+
+        $result = $this->controller->index($request, $response);
+
+        static::assertSame(200, $result->getStatusCode());
+        static::assertSame('daily', (string) $result->getBody());
+        static::assertCount(0, $assignedVariables['linksToDisplay']);
+        static::assertSame('Today', $assignedVariables['dayDesc']);
+    }
+
+    protected function createValidContainerMockSet(): void
+    {
+        $loginManager = $this->createMock(LoginManager::class);
+        $this->container->loginManager = $loginManager;
+
+        // Config
+        $conf = $this->createMock(ConfigManager::class);
+        $this->container->conf = $conf;
+        $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) {
+            return $default;
+        });
+
+        // PageBuilder
+        $pageBuilder = $this->createMock(PageBuilder::class);
+        $pageBuilder
+            ->method('render')
+            ->willReturnCallback(function (string $template): string {
+                return $template;
+            })
+        ;
+        $this->container->pageBuilder = $pageBuilder;
+
+        // Plugin Manager
+        $pluginManager = $this->createMock(PluginManager::class);
+        $this->container->pluginManager = $pluginManager;
+
+        // BookmarkService
+        $bookmarkService = $this->createMock(BookmarkServiceInterface::class);
+        $this->container->bookmarkService = $bookmarkService;
+
+        // Formatter
+        $formatterFactory = $this->createMock(FormatterFactory::class);
+        $formatterFactory
+            ->method('getFormatter')
+            ->willReturnCallback(function (): BookmarkFormatter {
+                return new BookmarkRawFormatter($this->container->conf, true);
+            })
+        ;
+        $this->container->formatterFactory = $formatterFactory;
+    }
+
+    protected function assignTemplateVars(array &$variables): void
+    {
+        $this->container->pageBuilder
+            ->expects(static::atLeastOnce())
+            ->method('assign')
+            ->willReturnCallback(function ($key, $value) use (&$variables) {
+                $variables[$key] = $value;
+
+                return $this;
+            })
+        ;
+    }
+
+    protected static function generateContent(int $length): string
+    {
+        // bin2hex(random_bytes) generates string twice as long as given parameter
+        $length = (int) ceil($length / 2);
+        return bin2hex(random_bytes($length));
+    }
+}
index e2e7b47bd2926c39df61f4123243d8e01791ef8c..f07c0a8b910cc1b1a84bcd1b4f55bd24d61bf736 100644 (file)
@@ -25,7 +25,7 @@
       <div class="pure-g">
         <div class="pure-u-lg-1-3 pure-u-1 center">
           {if="$previousday"}
-            <a href="./?do=daily&amp;day={$previousday}">
+            <a href="./daily?day={$previousday}">
               <i class="fa fa-arrow-left"></i>
               {'Previous day'|t}
             </a>
@@ -36,7 +36,7 @@
         </div>
         <div class="pure-u-lg-1-3 pure-u-1 center">
           {if="$nextday"}
-            <a href="./?do=daily&amp;day={$nextday}">
+            <a href="./daily?day={$nextday}">
               {'Next day'|t}
               <i class="fa fa-arrow-right"></i>
             </a>
@@ -69,7 +69,7 @@
                 {$link=$value}
                 <div class="daily-entry">
                   <div class="daily-entry-title center">
-                    <a href="?{$link.shorturl}" title="{'Permalink'|t}">
+                    <a href="./?{$link.shorturl}" title="{'Permalink'|t}">
                       <i class="fa fa-link"></i>
                     </a>
                     <a href="{$link.real_url}">{$link.title}</a>