diff options
27 files changed, 1211 insertions, 333 deletions
diff --git a/application/History.php b/application/History.php index 4fd2f294..bd5c1bf7 100644 --- a/application/History.php +++ b/application/History.php | |||
@@ -4,6 +4,7 @@ namespace Shaarli; | |||
4 | use DateTime; | 4 | use DateTime; |
5 | use Exception; | 5 | use Exception; |
6 | use Shaarli\Bookmark\Bookmark; | 6 | use Shaarli\Bookmark\Bookmark; |
7 | use Shaarli\Helper\FileUtils; | ||
7 | 8 | ||
8 | /** | 9 | /** |
9 | * Class History | 10 | * Class History |
diff --git a/application/Utils.php b/application/Utils.php index bc1c9f5d..db046893 100644 --- a/application/Utils.php +++ b/application/Utils.php | |||
@@ -327,6 +327,23 @@ function format_date($date, $time = true, $intl = true) | |||
327 | } | 327 | } |
328 | 328 | ||
329 | /** | 329 | /** |
330 | * Format the date month according to the locale. | ||
331 | * | ||
332 | * @param DateTimeInterface $date to format. | ||
333 | * | ||
334 | * @return bool|string Formatted date, or false if the input is invalid. | ||
335 | */ | ||
336 | function format_month(DateTimeInterface $date) | ||
337 | { | ||
338 | if (! $date instanceof DateTimeInterface) { | ||
339 | return false; | ||
340 | } | ||
341 | |||
342 | return strftime('%B', $date->getTimestamp()); | ||
343 | } | ||
344 | |||
345 | |||
346 | /** | ||
330 | * Check if the input is an integer, no matter its real type. | 347 | * Check if the input is an integer, no matter its real type. |
331 | * | 348 | * |
332 | * PHP is a bit messy regarding this: | 349 | * PHP is a bit messy regarding this: |
@@ -454,16 +471,20 @@ function alphabetical_sort(&$data, $reverse = false, $byKeys = false) | |||
454 | * Wrapper function for translation which match the API | 471 | * Wrapper function for translation which match the API |
455 | * of gettext()/_() and ngettext(). | 472 | * of gettext()/_() and ngettext(). |
456 | * | 473 | * |
457 | * @param string $text Text to translate. | 474 | * @param string $text Text to translate. |
458 | * @param string $nText The plural message ID. | 475 | * @param string $nText The plural message ID. |
459 | * @param int $nb The number of items for plural forms. | 476 | * @param int $nb The number of items for plural forms. |
460 | * @param string $domain The domain where the translation is stored (default: shaarli). | 477 | * @param string $domain The domain where the translation is stored (default: shaarli). |
478 | * @param array $variables Associative array of variables to replace in translated text. | ||
479 | * @param bool $fixCase Apply `ucfirst` on the translated string, might be useful for strings with variables. | ||
461 | * | 480 | * |
462 | * @return string Text translated. | 481 | * @return string Text translated. |
463 | */ | 482 | */ |
464 | function t($text, $nText = '', $nb = 1, $domain = 'shaarli') | 483 | function t($text, $nText = '', $nb = 1, $domain = 'shaarli', $variables = [], $fixCase = false) |
465 | { | 484 | { |
466 | return dn__($domain, $text, $nText, $nb); | 485 | $postFunction = $fixCase ? 'ucfirst' : function ($input) { return $input; }; |
486 | |||
487 | return $postFunction(dn__($domain, $text, $nText, $nb, $variables)); | ||
467 | } | 488 | } |
468 | 489 | ||
469 | /** | 490 | /** |
diff --git a/application/bookmark/BookmarkFileService.php b/application/bookmark/BookmarkFileService.php index 14b3d620..0df2f47f 100644 --- a/application/bookmark/BookmarkFileService.php +++ b/application/bookmark/BookmarkFileService.php | |||
@@ -343,26 +343,42 @@ class BookmarkFileService implements BookmarkServiceInterface | |||
343 | /** | 343 | /** |
344 | * @inheritDoc | 344 | * @inheritDoc |
345 | */ | 345 | */ |
346 | public function days(): array | 346 | public function findByDate( |
347 | { | 347 | \DateTimeInterface $from, |
348 | $bookmarkDays = []; | 348 | \DateTimeInterface $to, |
349 | foreach ($this->search() as $bookmark) { | 349 | ?\DateTimeInterface &$previous, |
350 | $bookmarkDays[$bookmark->getCreated()->format('Ymd')] = 0; | 350 | ?\DateTimeInterface &$next |
351 | ): array { | ||
352 | $out = []; | ||
353 | $previous = null; | ||
354 | $next = null; | ||
355 | |||
356 | foreach ($this->search([], null, false, false, true) as $bookmark) { | ||
357 | if ($to < $bookmark->getCreated()) { | ||
358 | $next = $bookmark->getCreated(); | ||
359 | } else if ($from < $bookmark->getCreated() && $to > $bookmark->getCreated()) { | ||
360 | $out[] = $bookmark; | ||
361 | } else { | ||
362 | if ($previous !== null) { | ||
363 | break; | ||
364 | } | ||
365 | $previous = $bookmark->getCreated(); | ||
366 | } | ||
351 | } | 367 | } |
352 | $bookmarkDays = array_keys($bookmarkDays); | ||
353 | sort($bookmarkDays); | ||
354 | 368 | ||
355 | return array_map('strval', $bookmarkDays); | 369 | return $out; |
356 | } | 370 | } |
357 | 371 | ||
358 | /** | 372 | /** |
359 | * @inheritDoc | 373 | * @inheritDoc |
360 | */ | 374 | */ |
361 | public function filterDay(string $request) | 375 | public function getLatest(): ?Bookmark |
362 | { | 376 | { |
363 | $visibility = $this->isLoggedIn ? BookmarkFilter::$ALL : BookmarkFilter::$PUBLIC; | 377 | foreach ($this->search([], null, false, false, true) as $bookmark) { |
378 | return $bookmark; | ||
379 | } | ||
364 | 380 | ||
365 | return $this->bookmarkFilter->filter(BookmarkFilter::$FILTER_DAY, $request, false, $visibility); | 381 | return null; |
366 | } | 382 | } |
367 | 383 | ||
368 | /** | 384 | /** |
diff --git a/application/bookmark/BookmarkServiceInterface.php b/application/bookmark/BookmarkServiceInterface.php index 9fa61533..08cdbb4e 100644 --- a/application/bookmark/BookmarkServiceInterface.php +++ b/application/bookmark/BookmarkServiceInterface.php | |||
@@ -156,22 +156,29 @@ interface BookmarkServiceInterface | |||
156 | public function bookmarksCountPerTag(array $filteringTags = [], ?string $visibility = null): array; | 156 | public function bookmarksCountPerTag(array $filteringTags = [], ?string $visibility = null): array; |
157 | 157 | ||
158 | /** | 158 | /** |
159 | * Returns the list of days containing articles (oldest first) | 159 | * Return a list of bookmark matching provided period of time. |
160 | * It also update directly previous and next date outside of given period found in the datastore. | ||
160 | * | 161 | * |
161 | * @return array containing days (in format YYYYMMDD). | 162 | * @param \DateTimeInterface $from Starting date. |
163 | * @param \DateTimeInterface $to Ending date. | ||
164 | * @param \DateTimeInterface|null $previous (by reference) updated with first created date found before $from. | ||
165 | * @param \DateTimeInterface|null $next (by reference) updated with first created date found after $to. | ||
166 | * | ||
167 | * @return array List of bookmarks matching provided period of time. | ||
162 | */ | 168 | */ |
163 | public function days(): array; | 169 | public function findByDate( |
170 | \DateTimeInterface $from, | ||
171 | \DateTimeInterface $to, | ||
172 | ?\DateTimeInterface &$previous, | ||
173 | ?\DateTimeInterface &$next | ||
174 | ): array; | ||
164 | 175 | ||
165 | /** | 176 | /** |
166 | * Returns the list of articles for a given day. | 177 | * Returns the latest bookmark by creation date. |
167 | * | ||
168 | * @param string $request day to filter. Format: YYYYMMDD. | ||
169 | * | 178 | * |
170 | * @return Bookmark[] list of shaare found. | 179 | * @return Bookmark|null Found Bookmark or null if the datastore is empty. |
171 | * | ||
172 | * @throws BookmarkNotFoundException | ||
173 | */ | 180 | */ |
174 | public function filterDay(string $request); | 181 | public function getLatest(): ?Bookmark; |
175 | 182 | ||
176 | /** | 183 | /** |
177 | * Creates the default database after a fresh install. | 184 | * Creates the default database after a fresh install. |
diff --git a/application/front/controller/admin/ServerController.php b/application/front/controller/admin/ServerController.php index 85654a43..bfc99422 100644 --- a/application/front/controller/admin/ServerController.php +++ b/application/front/controller/admin/ServerController.php | |||
@@ -4,8 +4,8 @@ declare(strict_types=1); | |||
4 | 4 | ||
5 | namespace Shaarli\Front\Controller\Admin; | 5 | namespace Shaarli\Front\Controller\Admin; |
6 | 6 | ||
7 | use Shaarli\ApplicationUtils; | 7 | use Shaarli\Helper\ApplicationUtils; |
8 | use Shaarli\FileUtils; | 8 | use Shaarli\Helper\FileUtils; |
9 | use Slim\Http\Request; | 9 | use Slim\Http\Request; |
10 | use Slim\Http\Response; | 10 | use Slim\Http\Response; |
11 | 11 | ||
diff --git a/application/front/controller/visitor/DailyController.php b/application/front/controller/visitor/DailyController.php index 07617cf1..728bc2d8 100644 --- a/application/front/controller/visitor/DailyController.php +++ b/application/front/controller/visitor/DailyController.php | |||
@@ -5,8 +5,8 @@ declare(strict_types=1); | |||
5 | namespace Shaarli\Front\Controller\Visitor; | 5 | namespace Shaarli\Front\Controller\Visitor; |
6 | 6 | ||
7 | use DateTime; | 7 | use DateTime; |
8 | use DateTimeImmutable; | ||
9 | use Shaarli\Bookmark\Bookmark; | 8 | use Shaarli\Bookmark\Bookmark; |
9 | use Shaarli\Helper\DailyPageHelper; | ||
10 | use Shaarli\Render\TemplatePage; | 10 | use Shaarli\Render\TemplatePage; |
11 | use Slim\Http\Request; | 11 | use Slim\Http\Request; |
12 | use Slim\Http\Response; | 12 | use Slim\Http\Response; |
@@ -26,32 +26,20 @@ class DailyController extends ShaarliVisitorController | |||
26 | */ | 26 | */ |
27 | public function index(Request $request, Response $response): Response | 27 | public function index(Request $request, Response $response): Response |
28 | { | 28 | { |
29 | $day = $request->getQueryParam('day') ?? date('Ymd'); | 29 | $type = DailyPageHelper::extractRequestedType($request); |
30 | 30 | $format = DailyPageHelper::getFormatByType($type); | |
31 | $availableDates = $this->container->bookmarkService->days(); | 31 | $latestBookmark = $this->container->bookmarkService->getLatest(); |
32 | $nbAvailableDates = count($availableDates); | 32 | $dateTime = DailyPageHelper::extractRequestedDateTime($type, $request->getQueryParam($type), $latestBookmark); |
33 | $index = array_search($day, $availableDates); | 33 | $start = DailyPageHelper::getStartDateTimeByType($type, $dateTime); |
34 | 34 | $end = DailyPageHelper::getEndDateTimeByType($type, $dateTime); | |
35 | if ($index === false) { | 35 | $dailyDesc = DailyPageHelper::getDescriptionByType($type, $dateTime); |
36 | // no bookmarks for day, but at least one day with bookmarks | 36 | |
37 | $day = $availableDates[$nbAvailableDates - 1] ?? $day; | 37 | $linksToDisplay = $this->container->bookmarkService->findByDate( |
38 | $previousDay = $availableDates[$nbAvailableDates - 2] ?? ''; | 38 | $start, |
39 | } else { | 39 | $end, |
40 | $previousDay = $availableDates[$index - 1] ?? ''; | 40 | $previousDay, |
41 | $nextDay = $availableDates[$index + 1] ?? ''; | 41 | $nextDay |
42 | } | 42 | ); |
43 | |||
44 | if ($day === date('Ymd')) { | ||
45 | $this->assignView('dayDesc', t('Today')); | ||
46 | } elseif ($day === date('Ymd', strtotime('-1 days'))) { | ||
47 | $this->assignView('dayDesc', t('Yesterday')); | ||
48 | } | ||
49 | |||
50 | try { | ||
51 | $linksToDisplay = $this->container->bookmarkService->filterDay($day); | ||
52 | } catch (\Exception $exc) { | ||
53 | $linksToDisplay = []; | ||
54 | } | ||
55 | 43 | ||
56 | $formatter = $this->container->formatterFactory->getFormatter(); | 44 | $formatter = $this->container->formatterFactory->getFormatter(); |
57 | $formatter->addContextData('base_path', $this->container->basePath); | 45 | $formatter->addContextData('base_path', $this->container->basePath); |
@@ -63,13 +51,15 @@ class DailyController extends ShaarliVisitorController | |||
63 | $linksToDisplay[$key]['description'] = $bookmark->getDescription(); | 51 | $linksToDisplay[$key]['description'] = $bookmark->getDescription(); |
64 | } | 52 | } |
65 | 53 | ||
66 | $dayDate = DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, $day.'_000000'); | ||
67 | $data = [ | 54 | $data = [ |
68 | 'linksToDisplay' => $linksToDisplay, | 55 | 'linksToDisplay' => $linksToDisplay, |
69 | 'day' => $dayDate->getTimestamp(), | 56 | 'dayDate' => $start, |
70 | 'dayDate' => $dayDate, | 57 | 'day' => $start->getTimestamp(), |
71 | 'previousday' => $previousDay ?? '', | 58 | 'previousday' => $previousDay ? $previousDay->format($format) : '', |
72 | 'nextday' => $nextDay ?? '', | 59 | 'nextday' => $nextDay ? $nextDay->format($format) : '', |
60 | 'dayDesc' => $dailyDesc, | ||
61 | 'type' => $type, | ||
62 | 'localizedType' => $this->translateType($type), | ||
73 | ]; | 63 | ]; |
74 | 64 | ||
75 | // Hooks are called before column construction so that plugins don't have to deal with columns. | 65 | // Hooks are called before column construction so that plugins don't have to deal with columns. |
@@ -82,7 +72,7 @@ class DailyController extends ShaarliVisitorController | |||
82 | $mainTitle = $this->container->conf->get('general.title', 'Shaarli'); | 72 | $mainTitle = $this->container->conf->get('general.title', 'Shaarli'); |
83 | $this->assignView( | 73 | $this->assignView( |
84 | 'pagetitle', | 74 | 'pagetitle', |
85 | t('Daily') .' - '. format_date($dayDate, false) . ' - ' . $mainTitle | 75 | $data['localizedType'] . ' - ' . $data['dayDesc'] . ' - ' . $mainTitle |
86 | ); | 76 | ); |
87 | 77 | ||
88 | return $response->write($this->render(TemplatePage::DAILY)); | 78 | return $response->write($this->render(TemplatePage::DAILY)); |
@@ -106,11 +96,14 @@ class DailyController extends ShaarliVisitorController | |||
106 | } | 96 | } |
107 | 97 | ||
108 | $days = []; | 98 | $days = []; |
99 | $type = DailyPageHelper::extractRequestedType($request); | ||
100 | $format = DailyPageHelper::getFormatByType($type); | ||
101 | $length = DailyPageHelper::getRssLengthByType($type); | ||
109 | foreach ($this->container->bookmarkService->search() as $bookmark) { | 102 | foreach ($this->container->bookmarkService->search() as $bookmark) { |
110 | $day = $bookmark->getCreated()->format('Ymd'); | 103 | $day = $bookmark->getCreated()->format($format); |
111 | 104 | ||
112 | // Stop iterating after DAILY_RSS_NB_DAYS entries | 105 | // Stop iterating after DAILY_RSS_NB_DAYS entries |
113 | if (count($days) === static::$DAILY_RSS_NB_DAYS && !isset($days[$day])) { | 106 | if (count($days) === $length && !isset($days[$day])) { |
114 | break; | 107 | break; |
115 | } | 108 | } |
116 | 109 | ||
@@ -127,12 +120,19 @@ class DailyController extends ShaarliVisitorController | |||
127 | 120 | ||
128 | /** @var Bookmark[] $bookmarks */ | 121 | /** @var Bookmark[] $bookmarks */ |
129 | foreach ($days as $day => $bookmarks) { | 122 | foreach ($days as $day => $bookmarks) { |
130 | $dayDatetime = DateTimeImmutable::createFromFormat(Bookmark::LINK_DATE_FORMAT, $day.'_000000'); | 123 | $dayDateTime = DailyPageHelper::extractRequestedDateTime($type, (string) $day); |
124 | $endDateTime = DailyPageHelper::getEndDateTimeByType($type, $dayDateTime); | ||
125 | |||
126 | // We only want the RSS entry to be published when the period is over. | ||
127 | if (new DateTime() < $endDateTime) { | ||
128 | continue; | ||
129 | } | ||
130 | |||
131 | $dataPerDay[$day] = [ | 131 | $dataPerDay[$day] = [ |
132 | 'date' => $dayDatetime, | 132 | 'date' => $endDateTime, |
133 | 'date_rss' => $dayDatetime->format(DateTime::RSS), | 133 | 'date_rss' => $endDateTime->format(DateTime::RSS), |
134 | 'date_human' => format_date($dayDatetime, false, true), | 134 | 'date_human' => DailyPageHelper::getDescriptionByType($type, $dayDateTime), |
135 | 'absolute_url' => $indexUrl . 'daily?day=' . $day, | 135 | 'absolute_url' => $indexUrl . 'daily?'. $type .'=' . $day, |
136 | 'links' => [], | 136 | 'links' => [], |
137 | ]; | 137 | ]; |
138 | 138 | ||
@@ -141,16 +141,20 @@ class DailyController extends ShaarliVisitorController | |||
141 | 141 | ||
142 | // Make permalink URL absolute | 142 | // Make permalink URL absolute |
143 | if ($bookmark->isNote()) { | 143 | if ($bookmark->isNote()) { |
144 | $dataPerDay[$day]['links'][$key]['url'] = $indexUrl . $bookmark->getUrl(); | 144 | $dataPerDay[$day]['links'][$key]['url'] = rtrim($indexUrl, '/') . $bookmark->getUrl(); |
145 | } | 145 | } |
146 | } | 146 | } |
147 | } | 147 | } |
148 | 148 | ||
149 | $this->assignView('title', $this->container->conf->get('general.title', 'Shaarli')); | 149 | $this->assignAllView([ |
150 | $this->assignView('index_url', $indexUrl); | 150 | 'title' => $this->container->conf->get('general.title', 'Shaarli'), |
151 | $this->assignView('page_url', $pageUrl); | 151 | 'index_url' => $indexUrl, |
152 | $this->assignView('hide_timestamps', $this->container->conf->get('privacy.hide_timestamps', false)); | 152 | 'page_url' => $pageUrl, |
153 | $this->assignView('days', $dataPerDay); | 153 | 'hide_timestamps' => $this->container->conf->get('privacy.hide_timestamps', false), |
154 | 'days' => $dataPerDay, | ||
155 | 'type' => $type, | ||
156 | 'localizedType' => $this->translateType($type), | ||
157 | ]); | ||
154 | 158 | ||
155 | $rssContent = $this->render(TemplatePage::DAILY_RSS); | 159 | $rssContent = $this->render(TemplatePage::DAILY_RSS); |
156 | 160 | ||
@@ -189,4 +193,13 @@ class DailyController extends ShaarliVisitorController | |||
189 | 193 | ||
190 | return $columns; | 194 | return $columns; |
191 | } | 195 | } |
196 | |||
197 | protected function translateType($type): string | ||
198 | { | ||
199 | return [ | ||
200 | t('day') => t('Daily'), | ||
201 | t('week') => t('Weekly'), | ||
202 | t('month') => t('Monthly'), | ||
203 | ][t($type)] ?? t('Daily'); | ||
204 | } | ||
192 | } | 205 | } |
diff --git a/application/front/controller/visitor/InstallController.php b/application/front/controller/visitor/InstallController.php index 564a5777..22329294 100644 --- a/application/front/controller/visitor/InstallController.php +++ b/application/front/controller/visitor/InstallController.php | |||
@@ -4,10 +4,10 @@ declare(strict_types=1); | |||
4 | 4 | ||
5 | namespace Shaarli\Front\Controller\Visitor; | 5 | namespace Shaarli\Front\Controller\Visitor; |
6 | 6 | ||
7 | use Shaarli\ApplicationUtils; | ||
8 | use Shaarli\Container\ShaarliContainer; | 7 | use Shaarli\Container\ShaarliContainer; |
9 | use Shaarli\Front\Exception\AlreadyInstalledException; | 8 | use Shaarli\Front\Exception\AlreadyInstalledException; |
10 | use Shaarli\Front\Exception\ResourcePermissionException; | 9 | use Shaarli\Front\Exception\ResourcePermissionException; |
10 | use Shaarli\Helper\ApplicationUtils; | ||
11 | use Shaarli\Languages; | 11 | use Shaarli\Languages; |
12 | use Shaarli\Security\SessionManager; | 12 | use Shaarli\Security\SessionManager; |
13 | use Slim\Http\Request; | 13 | use Slim\Http\Request; |
diff --git a/application/ApplicationUtils.php b/application/helper/ApplicationUtils.php index bd1c7cf3..4b34e114 100644 --- a/application/ApplicationUtils.php +++ b/application/helper/ApplicationUtils.php | |||
@@ -1,5 +1,5 @@ | |||
1 | <?php | 1 | <?php |
2 | namespace Shaarli; | 2 | namespace Shaarli\Helper; |
3 | 3 | ||
4 | use Exception; | 4 | use Exception; |
5 | use Shaarli\Config\ConfigManager; | 5 | use Shaarli\Config\ConfigManager; |
diff --git a/application/helper/DailyPageHelper.php b/application/helper/DailyPageHelper.php new file mode 100644 index 00000000..5fabc907 --- /dev/null +++ b/application/helper/DailyPageHelper.php | |||
@@ -0,0 +1,208 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Helper; | ||
6 | |||
7 | use Shaarli\Bookmark\Bookmark; | ||
8 | use Slim\Http\Request; | ||
9 | |||
10 | class DailyPageHelper | ||
11 | { | ||
12 | public const MONTH = 'month'; | ||
13 | public const WEEK = 'week'; | ||
14 | public const DAY = 'day'; | ||
15 | |||
16 | /** | ||
17 | * Extracts the type of the daily to display from the HTTP request parameters | ||
18 | * | ||
19 | * @param Request $request HTTP request | ||
20 | * | ||
21 | * @return string month/week/day | ||
22 | */ | ||
23 | public static function extractRequestedType(Request $request): string | ||
24 | { | ||
25 | if ($request->getQueryParam(static::MONTH) !== null) { | ||
26 | return static::MONTH; | ||
27 | } elseif ($request->getQueryParam(static::WEEK) !== null) { | ||
28 | return static::WEEK; | ||
29 | } | ||
30 | |||
31 | return static::DAY; | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * Extracts a DateTimeImmutable from provided HTTP request. | ||
36 | * If no parameter is provided, we rely on the creation date of the latest provided created bookmark. | ||
37 | * If the datastore is empty or no bookmark is provided, we use the current date. | ||
38 | * | ||
39 | * @param string $type month/week/day | ||
40 | * @param string|null $requestedDate Input string extracted from the request | ||
41 | * @param Bookmark|null $latestBookmark Latest bookmark found in the datastore (by date) | ||
42 | * | ||
43 | * @return \DateTimeImmutable from input or latest bookmark. | ||
44 | * | ||
45 | * @throws \Exception Type not supported. | ||
46 | */ | ||
47 | public static function extractRequestedDateTime( | ||
48 | string $type, | ||
49 | ?string $requestedDate, | ||
50 | Bookmark $latestBookmark = null | ||
51 | ): \DateTimeImmutable { | ||
52 | $format = static::getFormatByType($type); | ||
53 | if (empty($requestedDate)) { | ||
54 | return $latestBookmark instanceof Bookmark | ||
55 | ? new \DateTimeImmutable($latestBookmark->getCreated()->format(\DateTime::ATOM)) | ||
56 | : new \DateTimeImmutable() | ||
57 | ; | ||
58 | } | ||
59 | |||
60 | // W is not supported by createFromFormat... | ||
61 | if ($type === static::WEEK) { | ||
62 | return (new \DateTimeImmutable()) | ||
63 | ->setISODate((int) substr($requestedDate, 0, 4), (int) substr($requestedDate, 4, 2)) | ||
64 | ; | ||
65 | } | ||
66 | |||
67 | return \DateTimeImmutable::createFromFormat($format, $requestedDate); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * Get the DateTime format used by provided type | ||
72 | * Examples: | ||
73 | * - day: 20201016 (<year><month><day>) | ||
74 | * - week: 202041 (<year><week number>) | ||
75 | * - month: 202010 (<year><month>) | ||
76 | * | ||
77 | * @param string $type month/week/day | ||
78 | * | ||
79 | * @return string DateTime compatible format | ||
80 | * | ||
81 | * @see https://www.php.net/manual/en/datetime.format.php | ||
82 | * | ||
83 | * @throws \Exception Type not supported. | ||
84 | */ | ||
85 | public static function getFormatByType(string $type): string | ||
86 | { | ||
87 | switch ($type) { | ||
88 | case static::MONTH: | ||
89 | return 'Ym'; | ||
90 | case static::WEEK: | ||
91 | return 'YW'; | ||
92 | case static::DAY: | ||
93 | return 'Ymd'; | ||
94 | default: | ||
95 | throw new \Exception('Unsupported daily format type'); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Get the first DateTime of the time period depending on given datetime and type. | ||
101 | * Note: DateTimeImmutable is required because we rely heavily on DateTime->modify() syntax | ||
102 | * and we don't want to alter original datetime. | ||
103 | * | ||
104 | * @param string $type month/week/day | ||
105 | * @param \DateTimeImmutable $requested DateTime extracted from request input | ||
106 | * (should come from extractRequestedDateTime) | ||
107 | * | ||
108 | * @return \DateTimeInterface First DateTime of the time period | ||
109 | * | ||
110 | * @throws \Exception Type not supported. | ||
111 | */ | ||
112 | public static function getStartDateTimeByType(string $type, \DateTimeImmutable $requested): \DateTimeInterface | ||
113 | { | ||
114 | switch ($type) { | ||
115 | case static::MONTH: | ||
116 | return $requested->modify('first day of this month midnight'); | ||
117 | case static::WEEK: | ||
118 | return $requested->modify('Monday this week midnight'); | ||
119 | case static::DAY: | ||
120 | return $requested->modify('Today midnight'); | ||
121 | default: | ||
122 | throw new \Exception('Unsupported daily format type'); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Get the last DateTime of the time period depending on given datetime and type. | ||
128 | * Note: DateTimeImmutable is required because we rely heavily on DateTime->modify() syntax | ||
129 | * and we don't want to alter original datetime. | ||
130 | * | ||
131 | * @param string $type month/week/day | ||
132 | * @param \DateTimeImmutable $requested DateTime extracted from request input | ||
133 | * (should come from extractRequestedDateTime) | ||
134 | * | ||
135 | * @return \DateTimeInterface Last DateTime of the time period | ||
136 | * | ||
137 | * @throws \Exception Type not supported. | ||
138 | */ | ||
139 | public static function getEndDateTimeByType(string $type, \DateTimeImmutable $requested): \DateTimeInterface | ||
140 | { | ||
141 | switch ($type) { | ||
142 | case static::MONTH: | ||
143 | return $requested->modify('last day of this month 23:59:59'); | ||
144 | case static::WEEK: | ||
145 | return $requested->modify('Sunday this week 23:59:59'); | ||
146 | case static::DAY: | ||
147 | return $requested->modify('Today 23:59:59'); | ||
148 | default: | ||
149 | throw new \Exception('Unsupported daily format type'); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Get localized description of the time period depending on given datetime and type. | ||
155 | * Example: for a month period, it returns `October, 2020`. | ||
156 | * | ||
157 | * @param string $type month/week/day | ||
158 | * @param \DateTimeImmutable $requested DateTime extracted from request input | ||
159 | * (should come from extractRequestedDateTime) | ||
160 | * | ||
161 | * @return string Localized time period description | ||
162 | * | ||
163 | * @throws \Exception Type not supported. | ||
164 | */ | ||
165 | public static function getDescriptionByType(string $type, \DateTimeImmutable $requested): string | ||
166 | { | ||
167 | switch ($type) { | ||
168 | case static::MONTH: | ||
169 | return $requested->format('F') . ', ' . $requested->format('Y'); | ||
170 | case static::WEEK: | ||
171 | $requested = $requested->modify('Monday this week'); | ||
172 | return t('Week') . ' ' . $requested->format('W') . ' (' . format_date($requested, false) . ')'; | ||
173 | case static::DAY: | ||
174 | $out = ''; | ||
175 | if ($requested->format('Ymd') === date('Ymd')) { | ||
176 | $out = t('Today') . ' - '; | ||
177 | } elseif ($requested->format('Ymd') === date('Ymd', strtotime('-1 days'))) { | ||
178 | $out = t('Yesterday') . ' - '; | ||
179 | } | ||
180 | return $out . format_date($requested, false); | ||
181 | default: | ||
182 | throw new \Exception('Unsupported daily format type'); | ||
183 | } | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Get the number of items to display in the RSS feed depending on the given type. | ||
188 | * | ||
189 | * @param string $type month/week/day | ||
190 | * | ||
191 | * @return int number of elements | ||
192 | * | ||
193 | * @throws \Exception Type not supported. | ||
194 | */ | ||
195 | public static function getRssLengthByType(string $type): int | ||
196 | { | ||
197 | switch ($type) { | ||
198 | case static::MONTH: | ||
199 | return 12; // 1 year | ||
200 | case static::WEEK: | ||
201 | return 26; // ~6 months | ||
202 | case static::DAY: | ||
203 | return 30; // ~1 month | ||
204 | default: | ||
205 | throw new \Exception('Unsupported daily format type'); | ||
206 | } | ||
207 | } | ||
208 | } | ||
diff --git a/application/FileUtils.php b/application/helper/FileUtils.php index 3f940751..2eac0793 100644 --- a/application/FileUtils.php +++ b/application/helper/FileUtils.php | |||
@@ -1,6 +1,6 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Shaarli; | 3 | namespace Shaarli\Helper; |
4 | 4 | ||
5 | use Shaarli\Exceptions\IOException; | 5 | use Shaarli\Exceptions\IOException; |
6 | 6 | ||
@@ -133,7 +133,7 @@ class FileUtils | |||
133 | */ | 133 | */ |
134 | public static function isPathInShaarliFolder(string $path): bool | 134 | public static function isPathInShaarliFolder(string $path): bool |
135 | { | 135 | { |
136 | $rootDirectory = dirname(dirname(__FILE__)); | 136 | $rootDirectory = dirname(dirname(dirname(__FILE__))); |
137 | 137 | ||
138 | return strpos(realpath($path), $rootDirectory) !== false; | 138 | return strpos(realpath($path), $rootDirectory) !== false; |
139 | } | 139 | } |
diff --git a/application/legacy/LegacyLinkDB.php b/application/legacy/LegacyLinkDB.php index 7bf76fd4..5c02a21b 100644 --- a/application/legacy/LegacyLinkDB.php +++ b/application/legacy/LegacyLinkDB.php | |||
@@ -8,7 +8,7 @@ use DateTime; | |||
8 | use Iterator; | 8 | use Iterator; |
9 | use Shaarli\Bookmark\Exception\BookmarkNotFoundException; | 9 | use Shaarli\Bookmark\Exception\BookmarkNotFoundException; |
10 | use Shaarli\Exceptions\IOException; | 10 | use Shaarli\Exceptions\IOException; |
11 | use Shaarli\FileUtils; | 11 | use Shaarli\Helper\FileUtils; |
12 | use Shaarli\Render\PageCacheManager; | 12 | use Shaarli\Render\PageCacheManager; |
13 | 13 | ||
14 | /** | 14 | /** |
diff --git a/application/legacy/LegacyUpdater.php b/application/legacy/LegacyUpdater.php index 0ab3a55b..fe1a286f 100644 --- a/application/legacy/LegacyUpdater.php +++ b/application/legacy/LegacyUpdater.php | |||
@@ -7,7 +7,6 @@ use RainTPL; | |||
7 | use ReflectionClass; | 7 | use ReflectionClass; |
8 | use ReflectionException; | 8 | use ReflectionException; |
9 | use ReflectionMethod; | 9 | use ReflectionMethod; |
10 | use Shaarli\ApplicationUtils; | ||
11 | use Shaarli\Bookmark\Bookmark; | 10 | use Shaarli\Bookmark\Bookmark; |
12 | use Shaarli\Bookmark\BookmarkArray; | 11 | use Shaarli\Bookmark\BookmarkArray; |
13 | use Shaarli\Bookmark\BookmarkFilter; | 12 | use Shaarli\Bookmark\BookmarkFilter; |
@@ -17,6 +16,7 @@ use Shaarli\Config\ConfigJson; | |||
17 | use Shaarli\Config\ConfigManager; | 16 | use Shaarli\Config\ConfigManager; |
18 | use Shaarli\Config\ConfigPhp; | 17 | use Shaarli\Config\ConfigPhp; |
19 | use Shaarli\Exceptions\IOException; | 18 | use Shaarli\Exceptions\IOException; |
19 | use Shaarli\Helper\ApplicationUtils; | ||
20 | use Shaarli\Thumbnailer; | 20 | use Shaarli\Thumbnailer; |
21 | use Shaarli\Updater\Exception\UpdaterException; | 21 | use Shaarli\Updater\Exception\UpdaterException; |
22 | 22 | ||
diff --git a/application/render/PageBuilder.php b/application/render/PageBuilder.php index 512bb79e..25e0e284 100644 --- a/application/render/PageBuilder.php +++ b/application/render/PageBuilder.php | |||
@@ -5,9 +5,9 @@ namespace Shaarli\Render; | |||
5 | use Exception; | 5 | use Exception; |
6 | use Psr\Log\LoggerInterface; | 6 | use Psr\Log\LoggerInterface; |
7 | use RainTPL; | 7 | use RainTPL; |
8 | use Shaarli\ApplicationUtils; | ||
9 | use Shaarli\Bookmark\BookmarkServiceInterface; | 8 | use Shaarli\Bookmark\BookmarkServiceInterface; |
10 | use Shaarli\Config\ConfigManager; | 9 | use Shaarli\Config\ConfigManager; |
10 | use Shaarli\Helper\ApplicationUtils; | ||
11 | use Shaarli\Security\SessionManager; | 11 | use Shaarli\Security\SessionManager; |
12 | use Shaarli\Thumbnailer; | 12 | use Shaarli\Thumbnailer; |
13 | 13 | ||
diff --git a/application/security/BanManager.php b/application/security/BanManager.php index f72c8b7b..288cbde0 100644 --- a/application/security/BanManager.php +++ b/application/security/BanManager.php | |||
@@ -4,7 +4,7 @@ | |||
4 | namespace Shaarli\Security; | 4 | namespace Shaarli\Security; |
5 | 5 | ||
6 | use Psr\Log\LoggerInterface; | 6 | use Psr\Log\LoggerInterface; |
7 | use Shaarli\FileUtils; | 7 | use Shaarli\Helper\FileUtils; |
8 | 8 | ||
9 | /** | 9 | /** |
10 | * Class BanManager | 10 | * Class BanManager |
diff --git a/composer.json b/composer.json index 64f0025e..94492586 100644 --- a/composer.json +++ b/composer.json | |||
@@ -59,6 +59,7 @@ | |||
59 | "Shaarli\\Front\\Controller\\Admin\\": "application/front/controller/admin", | 59 | "Shaarli\\Front\\Controller\\Admin\\": "application/front/controller/admin", |
60 | "Shaarli\\Front\\Controller\\Visitor\\": "application/front/controller/visitor", | 60 | "Shaarli\\Front\\Controller\\Visitor\\": "application/front/controller/visitor", |
61 | "Shaarli\\Front\\Exception\\": "application/front/exceptions", | 61 | "Shaarli\\Front\\Exception\\": "application/front/exceptions", |
62 | "Shaarli\\Helper\\": "application/helper", | ||
62 | "Shaarli\\Http\\": "application/http", | 63 | "Shaarli\\Http\\": "application/http", |
63 | "Shaarli\\Legacy\\": "application/legacy", | 64 | "Shaarli\\Legacy\\": "application/legacy", |
64 | "Shaarli\\Netscape\\": "application/netscape", | 65 | "Shaarli\\Netscape\\": "application/netscape", |
diff --git a/inc/languages/fr/LC_MESSAGES/shaarli.po b/inc/languages/fr/LC_MESSAGES/shaarli.po index 3f14d22c..6d4ff0bd 100644 --- a/inc/languages/fr/LC_MESSAGES/shaarli.po +++ b/inc/languages/fr/LC_MESSAGES/shaarli.po | |||
@@ -1,8 +1,8 @@ | |||
1 | msgid "" | 1 | msgid "" |
2 | msgstr "" | 2 | msgstr "" |
3 | "Project-Id-Version: Shaarli\n" | 3 | "Project-Id-Version: Shaarli\n" |
4 | "POT-Creation-Date: 2020-10-27 19:32+0100\n" | 4 | "POT-Creation-Date: 2020-10-27 19:44+0100\n" |
5 | "PO-Revision-Date: 2020-10-27 19:32+0100\n" | 5 | "PO-Revision-Date: 2020-10-27 19:44+0100\n" |
6 | "Last-Translator: \n" | 6 | "Last-Translator: \n" |
7 | "Language-Team: Shaarli\n" | 7 | "Language-Team: Shaarli\n" |
8 | "Language: fr_FR\n" | 8 | "Language: fr_FR\n" |
@@ -20,78 +20,11 @@ msgstr "" | |||
20 | "X-Poedit-SearchPath-3: init.php\n" | 20 | "X-Poedit-SearchPath-3: init.php\n" |
21 | "X-Poedit-SearchPath-4: plugins\n" | 21 | "X-Poedit-SearchPath-4: plugins\n" |
22 | 22 | ||
23 | #: application/ApplicationUtils.php:162 | 23 | #: application/History.php:180 |
24 | #, php-format | ||
25 | msgid "" | ||
26 | "Your PHP version is obsolete! Shaarli requires at least PHP %s, and thus " | ||
27 | "cannot run. Your PHP version has known security vulnerabilities and should " | ||
28 | "be updated as soon as possible." | ||
29 | msgstr "" | ||
30 | "Votre version de PHP est obsolète ! Shaarli nécessite au moins PHP %s, et ne " | ||
31 | "peut donc pas fonctionner. Votre version de PHP a des failles de sécurités " | ||
32 | "connues et devrait être mise à jour au plus tôt." | ||
33 | |||
34 | #: application/ApplicationUtils.php:195 application/ApplicationUtils.php:215 | ||
35 | msgid "directory is not readable" | ||
36 | msgstr "le répertoire n'est pas accessible en lecture" | ||
37 | |||
38 | #: application/ApplicationUtils.php:218 | ||
39 | msgid "directory is not writable" | ||
40 | msgstr "le répertoire n'est pas accessible en écriture" | ||
41 | |||
42 | #: application/ApplicationUtils.php:240 | ||
43 | msgid "file is not readable" | ||
44 | msgstr "le fichier n'est pas accessible en lecture" | ||
45 | |||
46 | #: application/ApplicationUtils.php:243 | ||
47 | msgid "file is not writable" | ||
48 | msgstr "le fichier n'est pas accessible en écriture" | ||
49 | |||
50 | #: application/ApplicationUtils.php:277 | ||
51 | msgid "Configuration parsing" | ||
52 | msgstr "Chargement de la configuration" | ||
53 | |||
54 | #: application/ApplicationUtils.php:278 | ||
55 | msgid "Slim Framework (routing, etc.)" | ||
56 | msgstr "Slim Framwork (routage, etc.)" | ||
57 | |||
58 | #: application/ApplicationUtils.php:279 | ||
59 | msgid "Multibyte (Unicode) string support" | ||
60 | msgstr "Support des chaînes de caractère multibytes (Unicode)" | ||
61 | |||
62 | #: application/ApplicationUtils.php:280 | ||
63 | msgid "Required to use thumbnails" | ||
64 | msgstr "Obligatoire pour utiliser les miniatures" | ||
65 | |||
66 | #: application/ApplicationUtils.php:281 | ||
67 | msgid "Localized text sorting (e.g. e->è->f)" | ||
68 | msgstr "Tri des textes traduits (ex : e->è->f)" | ||
69 | |||
70 | #: application/ApplicationUtils.php:282 | ||
71 | msgid "Better retrieval of bookmark metadata and thumbnail" | ||
72 | msgstr "Meilleure récupération des meta-données des marque-pages et minatures" | ||
73 | |||
74 | #: application/ApplicationUtils.php:283 | ||
75 | msgid "Use the translation system in gettext mode" | ||
76 | msgstr "Utiliser le système de traduction en mode gettext" | ||
77 | |||
78 | #: application/ApplicationUtils.php:284 | ||
79 | msgid "Login using LDAP server" | ||
80 | msgstr "Authentification via un serveur LDAP" | ||
81 | |||
82 | #: application/FileUtils.php:100 | ||
83 | msgid "Provided path is not a directory." | ||
84 | msgstr "Le chemin fourni n'est pas un dossier." | ||
85 | |||
86 | #: application/FileUtils.php:104 | ||
87 | msgid "Trying to delete a folder outside of Shaarli path." | ||
88 | msgstr "Tentative de supprimer un dossier en dehors du chemin de Shaarli." | ||
89 | |||
90 | #: application/History.php:179 | ||
91 | msgid "History file isn't readable or writable" | 24 | msgid "History file isn't readable or writable" |
92 | msgstr "Le fichier d'historique n'est pas accessible en lecture ou en écriture" | 25 | msgstr "Le fichier d'historique n'est pas accessible en lecture ou en écriture" |
93 | 26 | ||
94 | #: application/History.php:190 | 27 | #: application/History.php:191 |
95 | msgid "Could not parse history file" | 28 | msgid "Could not parse history file" |
96 | msgstr "Format incorrect pour le fichier d'historique" | 29 | msgstr "Format incorrect pour le fichier d'historique" |
97 | 30 | ||
@@ -123,27 +56,27 @@ msgstr "" | |||
123 | "l'extension php-gd doit être chargée pour utiliser les miniatures. Les " | 56 | "l'extension php-gd doit être chargée pour utiliser les miniatures. Les " |
124 | "miniatures sont désormais désactivées. Rechargez la page." | 57 | "miniatures sont désormais désactivées. Rechargez la page." |
125 | 58 | ||
126 | #: application/Utils.php:385 | 59 | #: application/Utils.php:402 |
127 | msgid "Setting not set" | 60 | msgid "Setting not set" |
128 | msgstr "Paramètre non défini" | 61 | msgstr "Paramètre non défini" |
129 | 62 | ||
130 | #: application/Utils.php:392 | 63 | #: application/Utils.php:409 |
131 | msgid "Unlimited" | 64 | msgid "Unlimited" |
132 | msgstr "Illimité" | 65 | msgstr "Illimité" |
133 | 66 | ||
134 | #: application/Utils.php:395 | 67 | #: application/Utils.php:412 |
135 | msgid "B" | 68 | msgid "B" |
136 | msgstr "o" | 69 | msgstr "o" |
137 | 70 | ||
138 | #: application/Utils.php:395 | 71 | #: application/Utils.php:412 |
139 | msgid "kiB" | 72 | msgid "kiB" |
140 | msgstr "ko" | 73 | msgstr "ko" |
141 | 74 | ||
142 | #: application/Utils.php:395 | 75 | #: application/Utils.php:412 |
143 | msgid "MiB" | 76 | msgid "MiB" |
144 | msgstr "Mo" | 77 | msgstr "Mo" |
145 | 78 | ||
146 | #: application/Utils.php:395 | 79 | #: application/Utils.php:412 |
147 | msgid "GiB" | 80 | msgid "GiB" |
148 | msgstr "Go" | 81 | msgstr "Go" |
149 | 82 | ||
@@ -156,7 +89,7 @@ msgstr "Vous n'êtes pas autorisé à modifier les données" | |||
156 | 89 | ||
157 | #: application/bookmark/BookmarkFileService.php:208 | 90 | #: application/bookmark/BookmarkFileService.php:208 |
158 | msgid "This bookmarks already exists" | 91 | msgid "This bookmarks already exists" |
159 | msgstr "Ce marque-page existe déjà ." | 92 | msgstr "Ce marque-page existe déjà " |
160 | 93 | ||
161 | #: application/bookmark/BookmarkInitializer.php:39 | 94 | #: application/bookmark/BookmarkInitializer.php:39 |
162 | msgid "(private bookmark with thumbnail demo)" | 95 | msgid "(private bookmark with thumbnail demo)" |
@@ -354,7 +287,8 @@ msgid "Direct link" | |||
354 | msgstr "Liens directs" | 287 | msgstr "Liens directs" |
355 | 288 | ||
356 | #: application/feed/FeedBuilder.php:181 | 289 | #: application/feed/FeedBuilder.php:181 |
357 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:96 | 290 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:103 |
291 | #: tmp/dailyrss.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 | ||
358 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:179 | 292 | #: tmp/linklist.b91ef64efc3688266305ea9b42e5017e.rtpl.php:179 |
359 | msgid "Permalink" | 293 | msgid "Permalink" |
360 | msgstr "Permalien" | 294 | msgstr "Permalien" |
@@ -537,20 +471,36 @@ msgstr "Outils" | |||
537 | msgid "Search: " | 471 | msgid "Search: " |
538 | msgstr "Recherche : " | 472 | msgstr "Recherche : " |
539 | 473 | ||
540 | #: application/front/controller/visitor/DailyController.php:45 | 474 | #: application/front/controller/visitor/DailyController.php:200 |
541 | msgid "Today" | 475 | msgid "day" |
542 | msgstr "Aujourd'hui" | 476 | msgstr "jour" |
543 | |||
544 | #: application/front/controller/visitor/DailyController.php:47 | ||
545 | msgid "Yesterday" | ||
546 | msgstr "Hier" | ||
547 | 477 | ||
548 | #: application/front/controller/visitor/DailyController.php:85 | 478 | #: application/front/controller/visitor/DailyController.php:200 |
479 | #: application/front/controller/visitor/DailyController.php:203 | ||
480 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:13 | ||
549 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 | 481 | #: tmp/page.header.b91ef64efc3688266305ea9b42e5017e.rtpl.php:48 |
550 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:48 | 482 | #: tmp/page.header.cedf684561d925457130839629000a81.rtpl.php:48 |
551 | msgid "Daily" | 483 | msgid "Daily" |
552 | msgstr "Quotidien" | 484 | msgstr "Quotidien" |
553 | 485 | ||
486 | #: application/front/controller/visitor/DailyController.php:201 | ||
487 | msgid "week" | ||
488 | msgstr "semaine" | ||
489 | |||
490 | #: application/front/controller/visitor/DailyController.php:201 | ||
491 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:14 | ||
492 | msgid "Weekly" | ||
493 | msgstr "Hebdomadaire" | ||
494 | |||
495 | #: application/front/controller/visitor/DailyController.php:202 | ||
496 | msgid "month" | ||
497 | msgstr "mois" | ||
498 | |||
499 | #: application/front/controller/visitor/DailyController.php:202 | ||
500 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | ||
501 | msgid "Monthly" | ||
502 | msgstr "Mensuel" | ||
503 | |||
554 | #: application/front/controller/visitor/ErrorController.php:33 | 504 | #: application/front/controller/visitor/ErrorController.php:33 |
555 | msgid "An unexpected error occurred." | 505 | msgid "An unexpected error occurred." |
556 | msgstr "Une erreur inattendue s'est produite." | 506 | msgstr "Une erreur inattendue s'est produite." |
@@ -616,7 +566,7 @@ msgstr "Mur d'images" | |||
616 | 566 | ||
617 | #: application/front/controller/visitor/TagCloudController.php:88 | 567 | #: application/front/controller/visitor/TagCloudController.php:88 |
618 | msgid "Tag " | 568 | msgid "Tag " |
619 | msgstr "Tag" | 569 | msgstr "Tag " |
620 | 570 | ||
621 | #: application/front/exceptions/AlreadyInstalledException.php:11 | 571 | #: application/front/exceptions/AlreadyInstalledException.php:11 |
622 | msgid "Shaarli has already been installed. Login to edit the configuration." | 572 | msgid "Shaarli has already been installed. Login to edit the configuration." |
@@ -644,6 +594,86 @@ msgstr "" | |||
644 | msgid "Wrong token." | 594 | msgid "Wrong token." |
645 | msgstr "Jeton invalide." | 595 | msgstr "Jeton invalide." |
646 | 596 | ||
597 | #: application/helper/ApplicationUtils.php:162 | ||
598 | #, php-format | ||
599 | msgid "" | ||
600 | "Your PHP version is obsolete! Shaarli requires at least PHP %s, and thus " | ||
601 | "cannot run. Your PHP version has known security vulnerabilities and should " | ||
602 | "be updated as soon as possible." | ||
603 | msgstr "" | ||
604 | "Votre version de PHP est obsolète ! Shaarli nécessite au moins PHP %s, et ne " | ||
605 | "peut donc pas fonctionner. Votre version de PHP a des failles de sécurités " | ||
606 | "connues et devrait être mise à jour au plus tôt." | ||
607 | |||
608 | #: application/helper/ApplicationUtils.php:195 | ||
609 | #: application/helper/ApplicationUtils.php:215 | ||
610 | msgid "directory is not readable" | ||
611 | msgstr "le répertoire n'est pas accessible en lecture" | ||
612 | |||
613 | #: application/helper/ApplicationUtils.php:218 | ||
614 | msgid "directory is not writable" | ||
615 | msgstr "le répertoire n'est pas accessible en écriture" | ||
616 | |||
617 | #: application/helper/ApplicationUtils.php:240 | ||
618 | msgid "file is not readable" | ||
619 | msgstr "le fichier n'est pas accessible en lecture" | ||
620 | |||
621 | #: application/helper/ApplicationUtils.php:243 | ||
622 | msgid "file is not writable" | ||
623 | msgstr "le fichier n'est pas accessible en écriture" | ||
624 | |||
625 | #: application/helper/ApplicationUtils.php:277 | ||
626 | msgid "Configuration parsing" | ||
627 | msgstr "Chargement de la configuration" | ||
628 | |||
629 | #: application/helper/ApplicationUtils.php:278 | ||
630 | msgid "Slim Framework (routing, etc.)" | ||
631 | msgstr "Slim Framwork (routage, etc.)" | ||
632 | |||
633 | #: application/helper/ApplicationUtils.php:279 | ||
634 | msgid "Multibyte (Unicode) string support" | ||
635 | msgstr "Support des chaînes de caractère multibytes (Unicode)" | ||
636 | |||
637 | #: application/helper/ApplicationUtils.php:280 | ||
638 | msgid "Required to use thumbnails" | ||
639 | msgstr "Obligatoire pour utiliser les miniatures" | ||
640 | |||
641 | #: application/helper/ApplicationUtils.php:281 | ||
642 | msgid "Localized text sorting (e.g. e->è->f)" | ||
643 | msgstr "Tri des textes traduits (ex : e->è->f)" | ||
644 | |||
645 | #: application/helper/ApplicationUtils.php:282 | ||
646 | msgid "Better retrieval of bookmark metadata and thumbnail" | ||
647 | msgstr "Meilleure récupération des meta-données des marque-pages et minatures" | ||
648 | |||
649 | #: application/helper/ApplicationUtils.php:283 | ||
650 | msgid "Use the translation system in gettext mode" | ||
651 | msgstr "Utiliser le système de traduction en mode gettext" | ||
652 | |||
653 | #: application/helper/ApplicationUtils.php:284 | ||
654 | msgid "Login using LDAP server" | ||
655 | msgstr "Authentification via un serveur LDAP" | ||
656 | |||
657 | #: application/helper/DailyPageHelper.php:172 | ||
658 | msgid "Week" | ||
659 | msgstr "Semaine" | ||
660 | |||
661 | #: application/helper/DailyPageHelper.php:176 | ||
662 | msgid "Today" | ||
663 | msgstr "Aujourd'hui" | ||
664 | |||
665 | #: application/helper/DailyPageHelper.php:178 | ||
666 | msgid "Yesterday" | ||
667 | msgstr "Hier" | ||
668 | |||
669 | #: application/helper/FileUtils.php:100 | ||
670 | msgid "Provided path is not a directory." | ||
671 | msgstr "Le chemin fourni n'est pas un dossier." | ||
672 | |||
673 | #: application/helper/FileUtils.php:104 | ||
674 | msgid "Trying to delete a folder outside of Shaarli path." | ||
675 | msgstr "Tentative de supprimer un dossier en dehors du chemin de Shaarli." | ||
676 | |||
647 | #: application/legacy/LegacyLinkDB.php:131 | 677 | #: application/legacy/LegacyLinkDB.php:131 |
648 | msgid "You are not authorized to add a link." | 678 | msgid "You are not authorized to add a link." |
649 | msgstr "Vous n'êtes pas autorisé à ajouter un lien." | 679 | msgstr "Vous n'êtes pas autorisé à ajouter un lien." |
@@ -1103,25 +1133,30 @@ msgstr "Aucune" | |||
1103 | msgid "Save" | 1133 | msgid "Save" |
1104 | msgstr "Enregistrer" | 1134 | msgstr "Enregistrer" |
1105 | 1135 | ||
1106 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:15 | 1136 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:26 |
1107 | msgid "The Daily Shaarli" | 1137 | msgid "1 RSS entry per :type" |
1108 | msgstr "Le Quotidien Shaarli" | 1138 | msgid_plural "" |
1109 | 1139 | msgstr[0] "1 entrée RSS par :type" | |
1110 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:17 | 1140 | msgstr[1] "" |
1111 | msgid "1 RSS entry per day" | 1141 | |
1112 | msgstr "1 entrée RSS par jour" | 1142 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:49 |
1113 | 1143 | msgid "Previous :type" | |
1114 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:37 | 1144 | msgid_plural "" |
1115 | msgid "Previous day" | 1145 | msgstr[0] ":type précédent" |
1116 | msgstr "Jour précédent" | 1146 | msgstr[1] "Jour précédent" |
1117 | 1147 | ||
1118 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:44 | 1148 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:56 |
1119 | msgid "All links of one day in a single page." | 1149 | #: tmp/dailyrss.b91ef64efc3688266305ea9b42e5017e.rtpl.php:7 |
1120 | msgstr "Tous les liens d'un jour sur une page." | 1150 | msgid "All links of one :type in a single page." |
1121 | 1151 | msgid_plural "" | |
1122 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:51 | 1152 | msgstr[0] "Tous les liens d'un :type sur une page." |
1123 | msgid "Next day" | 1153 | msgstr[1] "Tous les liens d'un jour sur une page." |
1124 | msgstr "Jour suivant" | 1154 | |
1155 | #: tmp/daily.b91ef64efc3688266305ea9b42e5017e.rtpl.php:63 | ||
1156 | msgid "Next :type" | ||
1157 | msgid_plural "" | ||
1158 | msgstr[0] ":type suivant" | ||
1159 | msgstr[1] "" | ||
1125 | 1160 | ||
1126 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 | 1161 | #: tmp/editlink.b91ef64efc3688266305ea9b42e5017e.rtpl.php:21 |
1127 | msgid "Edit Shaare" | 1162 | msgid "Edit Shaare" |
@@ -1821,8 +1856,11 @@ msgstr "" | |||
1821 | "Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " | 1856 | "Glisser ce lien dans votre barre de favoris ou cliquer droit dessus et « " |
1822 | "Ajouter aux favoris »" | 1857 | "Ajouter aux favoris »" |
1823 | 1858 | ||
1824 | #~ msgid "Rename" | 1859 | #~ msgid "Display:" |
1825 | #~ msgstr "Renommer" | 1860 | #~ msgstr "Afficher :" |
1861 | |||
1862 | #~ msgid "The Daily Shaarli" | ||
1863 | #~ msgstr "Le Quotidien Shaarli" | ||
1826 | 1864 | ||
1827 | #, fuzzy | 1865 | #, fuzzy |
1828 | #~| msgid "Selection" | 1866 | #~| msgid "Selection" |
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | require_once __DIR__ . '/vendor/autoload.php'; | 3 | require_once __DIR__ . '/vendor/autoload.php'; |
4 | 4 | ||
5 | use Shaarli\ApplicationUtils; | 5 | use Shaarli\Helper\ApplicationUtils; |
6 | use Shaarli\Security\SessionManager; | 6 | use Shaarli\Security\SessionManager; |
7 | 7 | ||
8 | // Set 'UTC' as the default timezone if it is not defined in php.ini | 8 | // Set 'UTC' as the default timezone if it is not defined in php.ini |
diff --git a/tests/bookmark/BookmarkFileServiceTest.php b/tests/bookmark/BookmarkFileServiceTest.php index 47970117..8e0ff8dd 100644 --- a/tests/bookmark/BookmarkFileServiceTest.php +++ b/tests/bookmark/BookmarkFileServiceTest.php | |||
@@ -686,22 +686,6 @@ class BookmarkFileServiceTest extends TestCase | |||
686 | } | 686 | } |
687 | 687 | ||
688 | /** | 688 | /** |
689 | * List the days for which bookmarks have been posted | ||
690 | */ | ||
691 | public function testDays() | ||
692 | { | ||
693 | $this->assertSame( | ||
694 | ['20100309', '20100310', '20121206', '20121207', '20130614', '20150310'], | ||
695 | $this->publicLinkDB->days() | ||
696 | ); | ||
697 | |||
698 | $this->assertSame( | ||
699 | ['20100309', '20100310', '20121206', '20121207', '20130614', '20141125', '20150310'], | ||
700 | $this->privateLinkDB->days() | ||
701 | ); | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * The URL corresponds to an existing entry in the DB | 689 | * The URL corresponds to an existing entry in the DB |
706 | */ | 690 | */ |
707 | public function testGetKnownLinkFromURL() | 691 | public function testGetKnownLinkFromURL() |
@@ -1074,33 +1058,105 @@ class BookmarkFileServiceTest extends TestCase | |||
1074 | } | 1058 | } |
1075 | 1059 | ||
1076 | /** | 1060 | /** |
1077 | * Test filterDay while logged in | 1061 | * Test find by dates in the middle of the datastore (sorted by dates) with a single bookmark as a result. |
1078 | */ | 1062 | */ |
1079 | public function testFilterDayLoggedIn(): void | 1063 | public function testFilterByDateMidTimePeriodSingleBookmark(): void |
1080 | { | 1064 | { |
1081 | $bookmarks = $this->privateLinkDB->filterDay('20121206'); | 1065 | $bookmarks = $this->privateLinkDB->findByDate( |
1082 | $expectedIds = [4, 9, 1, 0]; | 1066 | DateTime::createFromFormat('Ymd_His', '20121206_150000'), |
1067 | DateTime::createFromFormat('Ymd_His', '20121206_160000'), | ||
1068 | $before, | ||
1069 | $after | ||
1070 | ); | ||
1083 | 1071 | ||
1084 | static::assertCount(4, $bookmarks); | 1072 | static::assertCount(1, $bookmarks); |
1085 | foreach ($bookmarks as $bookmark) { | 1073 | |
1086 | $i = ($i ?? -1) + 1; | 1074 | static::assertSame(9, $bookmarks[0]->getId()); |
1087 | static::assertSame($expectedIds[$i], $bookmark->getId()); | 1075 | static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_142300'), $before); |
1088 | } | 1076 | static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_172539'), $after); |
1089 | } | 1077 | } |
1090 | 1078 | ||
1091 | /** | 1079 | /** |
1092 | * Test filterDay while logged out | 1080 | * Test find by dates in the middle of the datastore (sorted by dates) with a multiple bookmarks as a result. |
1093 | */ | 1081 | */ |
1094 | public function testFilterDayLoggedOut(): void | 1082 | public function testFilterByDateMidTimePeriodMultipleBookmarks(): void |
1095 | { | 1083 | { |
1096 | $bookmarks = $this->publicLinkDB->filterDay('20121206'); | 1084 | $bookmarks = $this->privateLinkDB->findByDate( |
1097 | $expectedIds = [4, 9, 1]; | 1085 | DateTime::createFromFormat('Ymd_His', '20121206_150000'), |
1086 | DateTime::createFromFormat('Ymd_His', '20121206_180000'), | ||
1087 | $before, | ||
1088 | $after | ||
1089 | ); | ||
1098 | 1090 | ||
1099 | static::assertCount(3, $bookmarks); | 1091 | static::assertCount(2, $bookmarks); |
1100 | foreach ($bookmarks as $bookmark) { | 1092 | |
1101 | $i = ($i ?? -1) + 1; | 1093 | static::assertSame(1, $bookmarks[0]->getId()); |
1102 | static::assertSame($expectedIds[$i], $bookmark->getId()); | 1094 | static::assertSame(9, $bookmarks[1]->getId()); |
1103 | } | 1095 | static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_142300'), $before); |
1096 | static::assertEquals(DateTime::createFromFormat('Ymd_His', '20121206_182539'), $after); | ||
1097 | } | ||
1098 | |||
1099 | /** | ||
1100 | * Test find by dates at the end of the datastore (sorted by dates). | ||
1101 | */ | ||
1102 | public function testFilterByDateLastTimePeriod(): void | ||
1103 | { | ||
1104 | $after = new DateTime(); | ||
1105 | $bookmarks = $this->privateLinkDB->findByDate( | ||
1106 | DateTime::createFromFormat('Ymd_His', '20150310_114640'), | ||
1107 | DateTime::createFromFormat('Ymd_His', '20450101_010101'), | ||
1108 | $before, | ||
1109 | $after | ||
1110 | ); | ||
1111 | |||
1112 | static::assertCount(1, $bookmarks); | ||
1113 | |||
1114 | static::assertSame(41, $bookmarks[0]->getId()); | ||
1115 | static::assertEquals(DateTime::createFromFormat('Ymd_His', '20150310_114633'), $before); | ||
1116 | static::assertNull($after); | ||
1117 | } | ||
1118 | |||
1119 | /** | ||
1120 | * Test find by dates at the beginning of the datastore (sorted by dates). | ||
1121 | */ | ||
1122 | public function testFilterByDateFirstTimePeriod(): void | ||
1123 | { | ||
1124 | $before = new DateTime(); | ||
1125 | $bookmarks = $this->privateLinkDB->findByDate( | ||
1126 | DateTime::createFromFormat('Ymd_His', '20000101_101010'), | ||
1127 | DateTime::createFromFormat('Ymd_His', '20100309_110000'), | ||
1128 | $before, | ||
1129 | $after | ||
1130 | ); | ||
1131 | |||
1132 | static::assertCount(1, $bookmarks); | ||
1133 | |||
1134 | static::assertSame(11, $bookmarks[0]->getId()); | ||
1135 | static::assertNull($before); | ||
1136 | static::assertEquals(DateTime::createFromFormat('Ymd_His', '20100310_101010'), $after); | ||
1137 | } | ||
1138 | |||
1139 | /** | ||
1140 | * Test getLatest with a sticky bookmark: it should be ignored and return the latest by creation date instead. | ||
1141 | */ | ||
1142 | public function testGetLatestWithSticky(): void | ||
1143 | { | ||
1144 | $bookmark = $this->publicLinkDB->getLatest(); | ||
1145 | |||
1146 | static::assertSame(41, $bookmark->getId()); | ||
1147 | } | ||
1148 | |||
1149 | /** | ||
1150 | * Test getLatest with a sticky bookmark: it should be ignored and return the latest by creation date instead. | ||
1151 | */ | ||
1152 | public function testGetLatestEmptyDatastore(): void | ||
1153 | { | ||
1154 | unlink($this->conf->get('resource.datastore')); | ||
1155 | $this->publicLinkDB = new BookmarkFileService($this->conf, $this->history, $this->mutex, false); | ||
1156 | |||
1157 | $bookmark = $this->publicLinkDB->getLatest(); | ||
1158 | |||
1159 | static::assertNull($bookmark); | ||
1104 | } | 1160 | } |
1105 | 1161 | ||
1106 | /** | 1162 | /** |
diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php index fc78bc13..758e7219 100644 --- a/tests/front/controller/visitor/DailyControllerTest.php +++ b/tests/front/controller/visitor/DailyControllerTest.php | |||
@@ -28,52 +28,49 @@ class DailyControllerTest extends TestCase | |||
28 | public function testValidIndexControllerInvokeDefault(): void | 28 | public function testValidIndexControllerInvokeDefault(): void |
29 | { | 29 | { |
30 | $currentDay = new \DateTimeImmutable('2020-05-13'); | 30 | $currentDay = new \DateTimeImmutable('2020-05-13'); |
31 | $previousDate = new \DateTime('2 days ago 00:00:00'); | ||
32 | $nextDate = new \DateTime('today 00:00:00'); | ||
31 | 33 | ||
32 | $request = $this->createMock(Request::class); | 34 | $request = $this->createMock(Request::class); |
33 | $request->method('getQueryParam')->willReturn($currentDay->format('Ymd')); | 35 | $request->method('getQueryParam')->willReturnCallback(function (string $key) use ($currentDay): ?string { |
36 | return $key === 'day' ? $currentDay->format('Ymd') : null; | ||
37 | }); | ||
34 | $response = new Response(); | 38 | $response = new Response(); |
35 | 39 | ||
36 | // Save RainTPL assigned variables | 40 | // Save RainTPL assigned variables |
37 | $assignedVariables = []; | 41 | $assignedVariables = []; |
38 | $this->assignTemplateVars($assignedVariables); | 42 | $this->assignTemplateVars($assignedVariables); |
39 | 43 | ||
40 | // Links dataset: 2 links with thumbnails | ||
41 | $this->container->bookmarkService | ||
42 | ->expects(static::once()) | ||
43 | ->method('days') | ||
44 | ->willReturnCallback(function () use ($currentDay): array { | ||
45 | return [ | ||
46 | '20200510', | ||
47 | $currentDay->format('Ymd'), | ||
48 | '20200516', | ||
49 | ]; | ||
50 | }) | ||
51 | ; | ||
52 | $this->container->bookmarkService | 44 | $this->container->bookmarkService |
53 | ->expects(static::once()) | 45 | ->expects(static::once()) |
54 | ->method('filterDay') | 46 | ->method('findByDate') |
55 | ->willReturnCallback(function (): array { | 47 | ->willReturnCallback( |
56 | return [ | 48 | function ($from, $to, &$previous, &$next) use ($currentDay, $previousDate, $nextDate): array { |
57 | (new Bookmark()) | 49 | $previous = $previousDate; |
58 | ->setId(1) | 50 | $next = $nextDate; |
59 | ->setUrl('http://url.tld') | 51 | |
60 | ->setTitle(static::generateString(50)) | 52 | return [ |
61 | ->setDescription(static::generateString(500)) | 53 | (new Bookmark()) |
62 | , | 54 | ->setId(1) |
63 | (new Bookmark()) | 55 | ->setUrl('http://url.tld') |
64 | ->setId(2) | 56 | ->setTitle(static::generateString(50)) |
65 | ->setUrl('http://url2.tld') | 57 | ->setDescription(static::generateString(500)) |
66 | ->setTitle(static::generateString(50)) | 58 | , |
67 | ->setDescription(static::generateString(500)) | 59 | (new Bookmark()) |
68 | , | 60 | ->setId(2) |
69 | (new Bookmark()) | 61 | ->setUrl('http://url2.tld') |
70 | ->setId(3) | 62 | ->setTitle(static::generateString(50)) |
71 | ->setUrl('http://url3.tld') | 63 | ->setDescription(static::generateString(500)) |
72 | ->setTitle(static::generateString(50)) | 64 | , |
73 | ->setDescription(static::generateString(500)) | 65 | (new Bookmark()) |
74 | , | 66 | ->setId(3) |
75 | ]; | 67 | ->setUrl('http://url3.tld') |
76 | }) | 68 | ->setTitle(static::generateString(50)) |
69 | ->setDescription(static::generateString(500)) | ||
70 | , | ||
71 | ]; | ||
72 | } | ||
73 | ) | ||
77 | ; | 74 | ; |
78 | 75 | ||
79 | // Make sure that PluginManager hook is triggered | 76 | // Make sure that PluginManager hook is triggered |
@@ -81,20 +78,22 @@ class DailyControllerTest extends TestCase | |||
81 | ->expects(static::atLeastOnce()) | 78 | ->expects(static::atLeastOnce()) |
82 | ->method('executeHooks') | 79 | ->method('executeHooks') |
83 | ->withConsecutive(['render_daily']) | 80 | ->withConsecutive(['render_daily']) |
84 | ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { | 81 | ->willReturnCallback( |
85 | if ('render_daily' === $hook) { | 82 | function (string $hook, array $data, array $param) use ($currentDay, $previousDate, $nextDate): array { |
86 | static::assertArrayHasKey('linksToDisplay', $data); | 83 | if ('render_daily' === $hook) { |
87 | static::assertCount(3, $data['linksToDisplay']); | 84 | static::assertArrayHasKey('linksToDisplay', $data); |
88 | static::assertSame(1, $data['linksToDisplay'][0]['id']); | 85 | static::assertCount(3, $data['linksToDisplay']); |
89 | static::assertSame($currentDay->getTimestamp(), $data['day']); | 86 | static::assertSame(1, $data['linksToDisplay'][0]['id']); |
90 | static::assertSame('20200510', $data['previousday']); | 87 | static::assertSame($currentDay->getTimestamp(), $data['day']); |
91 | static::assertSame('20200516', $data['nextday']); | 88 | static::assertSame($previousDate->format('Ymd'), $data['previousday']); |
92 | 89 | static::assertSame($nextDate->format('Ymd'), $data['nextday']); | |
93 | static::assertArrayHasKey('loggedin', $param); | 90 | |
91 | static::assertArrayHasKey('loggedin', $param); | ||
92 | } | ||
93 | |||
94 | return $data; | ||
94 | } | 95 | } |
95 | 96 | ) | |
96 | return $data; | ||
97 | }) | ||
98 | ; | 97 | ; |
99 | 98 | ||
100 | $result = $this->controller->index($request, $response); | 99 | $result = $this->controller->index($request, $response); |
@@ -107,6 +106,11 @@ class DailyControllerTest extends TestCase | |||
107 | ); | 106 | ); |
108 | static::assertEquals($currentDay, $assignedVariables['dayDate']); | 107 | static::assertEquals($currentDay, $assignedVariables['dayDate']); |
109 | static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']); | 108 | static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']); |
109 | static::assertSame($previousDate->format('Ymd'), $assignedVariables['previousday']); | ||
110 | static::assertSame($nextDate->format('Ymd'), $assignedVariables['nextday']); | ||
111 | static::assertSame('day', $assignedVariables['type']); | ||
112 | static::assertSame('May 13, 2020', $assignedVariables['dayDesc']); | ||
113 | static::assertSame('Daily', $assignedVariables['localizedType']); | ||
110 | static::assertCount(3, $assignedVariables['linksToDisplay']); | 114 | static::assertCount(3, $assignedVariables['linksToDisplay']); |
111 | 115 | ||
112 | $link = $assignedVariables['linksToDisplay'][0]; | 116 | $link = $assignedVariables['linksToDisplay'][0]; |
@@ -171,27 +175,20 @@ class DailyControllerTest extends TestCase | |||
171 | $currentDay = new \DateTimeImmutable('2020-05-13'); | 175 | $currentDay = new \DateTimeImmutable('2020-05-13'); |
172 | 176 | ||
173 | $request = $this->createMock(Request::class); | 177 | $request = $this->createMock(Request::class); |
178 | $request->method('getQueryParam')->willReturnCallback(function (string $key) use ($currentDay): ?string { | ||
179 | return $key === 'day' ? $currentDay->format('Ymd') : null; | ||
180 | }); | ||
174 | $response = new Response(); | 181 | $response = new Response(); |
175 | 182 | ||
176 | // Save RainTPL assigned variables | 183 | // Save RainTPL assigned variables |
177 | $assignedVariables = []; | 184 | $assignedVariables = []; |
178 | $this->assignTemplateVars($assignedVariables); | 185 | $this->assignTemplateVars($assignedVariables); |
179 | 186 | ||
180 | // Links dataset: 2 links with thumbnails | ||
181 | $this->container->bookmarkService | 187 | $this->container->bookmarkService |
182 | ->expects(static::once()) | 188 | ->expects(static::once()) |
183 | ->method('days') | 189 | ->method('findByDate') |
184 | ->willReturnCallback(function () use ($currentDay): array { | 190 | ->willReturnCallback(function () use ($currentDay): array { |
185 | return [ | 191 | return [ |
186 | $currentDay->format($currentDay->format('Ymd')), | ||
187 | ]; | ||
188 | }) | ||
189 | ; | ||
190 | $this->container->bookmarkService | ||
191 | ->expects(static::once()) | ||
192 | ->method('filterDay') | ||
193 | ->willReturnCallback(function (): array { | ||
194 | return [ | ||
195 | (new Bookmark()) | 192 | (new Bookmark()) |
196 | ->setId(1) | 193 | ->setId(1) |
197 | ->setUrl('http://url.tld') | 194 | ->setUrl('http://url.tld') |
@@ -250,21 +247,11 @@ class DailyControllerTest extends TestCase | |||
250 | $assignedVariables = []; | 247 | $assignedVariables = []; |
251 | $this->assignTemplateVars($assignedVariables); | 248 | $this->assignTemplateVars($assignedVariables); |
252 | 249 | ||
253 | // Links dataset: 2 links with thumbnails | ||
254 | $this->container->bookmarkService | 250 | $this->container->bookmarkService |
255 | ->expects(static::once()) | 251 | ->expects(static::once()) |
256 | ->method('days') | 252 | ->method('findByDate') |
257 | ->willReturnCallback(function () use ($currentDay): array { | 253 | ->willReturnCallback(function () use ($currentDay): array { |
258 | return [ | 254 | return [ |
259 | $currentDay->format($currentDay->format('Ymd')), | ||
260 | ]; | ||
261 | }) | ||
262 | ; | ||
263 | $this->container->bookmarkService | ||
264 | ->expects(static::once()) | ||
265 | ->method('filterDay') | ||
266 | ->willReturnCallback(function (): array { | ||
267 | return [ | ||
268 | (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'), | 255 | (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'), |
269 | (new Bookmark()) | 256 | (new Bookmark()) |
270 | ->setId(2) | 257 | ->setId(2) |
@@ -320,14 +307,7 @@ class DailyControllerTest extends TestCase | |||
320 | // Links dataset: 2 links with thumbnails | 307 | // Links dataset: 2 links with thumbnails |
321 | $this->container->bookmarkService | 308 | $this->container->bookmarkService |
322 | ->expects(static::once()) | 309 | ->expects(static::once()) |
323 | ->method('days') | 310 | ->method('findByDate') |
324 | ->willReturnCallback(function (): array { | ||
325 | return []; | ||
326 | }) | ||
327 | ; | ||
328 | $this->container->bookmarkService | ||
329 | ->expects(static::once()) | ||
330 | ->method('filterDay') | ||
331 | ->willReturnCallback(function (): array { | 311 | ->willReturnCallback(function (): array { |
332 | return []; | 312 | return []; |
333 | }) | 313 | }) |
@@ -347,7 +327,7 @@ class DailyControllerTest extends TestCase | |||
347 | static::assertSame(200, $result->getStatusCode()); | 327 | static::assertSame(200, $result->getStatusCode()); |
348 | static::assertSame('daily', (string) $result->getBody()); | 328 | static::assertSame('daily', (string) $result->getBody()); |
349 | static::assertCount(0, $assignedVariables['linksToDisplay']); | 329 | static::assertCount(0, $assignedVariables['linksToDisplay']); |
350 | static::assertSame('Today', $assignedVariables['dayDesc']); | 330 | static::assertSame('Today - ' . (new \DateTime())->format('F d, Y'), $assignedVariables['dayDesc']); |
351 | static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); | 331 | static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); |
352 | static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); | 332 | static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); |
353 | } | 333 | } |
@@ -361,6 +341,7 @@ class DailyControllerTest extends TestCase | |||
361 | new \DateTimeImmutable('2020-05-17'), | 341 | new \DateTimeImmutable('2020-05-17'), |
362 | new \DateTimeImmutable('2020-05-15'), | 342 | new \DateTimeImmutable('2020-05-15'), |
363 | new \DateTimeImmutable('2020-05-13'), | 343 | new \DateTimeImmutable('2020-05-13'), |
344 | new \DateTimeImmutable('+1 month'), | ||
364 | ]; | 345 | ]; |
365 | 346 | ||
366 | $request = $this->createMock(Request::class); | 347 | $request = $this->createMock(Request::class); |
@@ -371,6 +352,7 @@ class DailyControllerTest extends TestCase | |||
371 | (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), | 352 | (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), |
372 | (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), | 353 | (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), |
373 | (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), | 354 | (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), |
355 | (new Bookmark())->setId(5)->setCreated($dates[3])->setUrl('http://domain.tld/5'), | ||
374 | ]); | 356 | ]); |
375 | 357 | ||
376 | $this->container->pageCacheManager | 358 | $this->container->pageCacheManager |
@@ -397,13 +379,14 @@ class DailyControllerTest extends TestCase | |||
397 | static::assertSame('http://shaarli/subfolder/', $assignedVariables['index_url']); | 379 | static::assertSame('http://shaarli/subfolder/', $assignedVariables['index_url']); |
398 | static::assertSame('http://shaarli/subfolder/daily-rss', $assignedVariables['page_url']); | 380 | static::assertSame('http://shaarli/subfolder/daily-rss', $assignedVariables['page_url']); |
399 | static::assertFalse($assignedVariables['hide_timestamps']); | 381 | static::assertFalse($assignedVariables['hide_timestamps']); |
400 | static::assertCount(2, $assignedVariables['days']); | 382 | static::assertCount(3, $assignedVariables['days']); |
401 | 383 | ||
402 | $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; | 384 | $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; |
385 | $date = $dates[0]->setTime(23, 59, 59); | ||
403 | 386 | ||
404 | static::assertEquals($dates[0], $day['date']); | 387 | static::assertEquals($date, $day['date']); |
405 | static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']); | 388 | static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); |
406 | static::assertSame(format_date($dates[0], false), $day['date_human']); | 389 | static::assertSame(format_date($date, false), $day['date_human']); |
407 | static::assertSame('http://shaarli/subfolder/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); | 390 | static::assertSame('http://shaarli/subfolder/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); |
408 | static::assertCount(1, $day['links']); | 391 | static::assertCount(1, $day['links']); |
409 | static::assertSame(1, $day['links'][0]['id']); | 392 | static::assertSame(1, $day['links'][0]['id']); |
@@ -411,10 +394,11 @@ class DailyControllerTest extends TestCase | |||
411 | static::assertEquals($dates[0], $day['links'][0]['created']); | 394 | static::assertEquals($dates[0], $day['links'][0]['created']); |
412 | 395 | ||
413 | $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; | 396 | $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; |
397 | $date = $dates[1]->setTime(23, 59, 59); | ||
414 | 398 | ||
415 | static::assertEquals($dates[1], $day['date']); | 399 | static::assertEquals($date, $day['date']); |
416 | static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']); | 400 | static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); |
417 | static::assertSame(format_date($dates[1], false), $day['date_human']); | 401 | static::assertSame(format_date($date, false), $day['date_human']); |
418 | static::assertSame('http://shaarli/subfolder/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); | 402 | static::assertSame('http://shaarli/subfolder/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); |
419 | static::assertCount(2, $day['links']); | 403 | static::assertCount(2, $day['links']); |
420 | 404 | ||
@@ -424,6 +408,18 @@ class DailyControllerTest extends TestCase | |||
424 | static::assertSame(3, $day['links'][1]['id']); | 408 | static::assertSame(3, $day['links'][1]['id']); |
425 | static::assertSame('http://domain.tld/3', $day['links'][1]['url']); | 409 | static::assertSame('http://domain.tld/3', $day['links'][1]['url']); |
426 | static::assertEquals($dates[1], $day['links'][1]['created']); | 410 | static::assertEquals($dates[1], $day['links'][1]['created']); |
411 | |||
412 | $day = $assignedVariables['days'][$dates[2]->format('Ymd')]; | ||
413 | $date = $dates[2]->setTime(23, 59, 59); | ||
414 | |||
415 | static::assertEquals($date, $day['date']); | ||
416 | static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); | ||
417 | static::assertSame(format_date($date, false), $day['date_human']); | ||
418 | static::assertSame('http://shaarli/subfolder/daily?day='. $dates[2]->format('Ymd'), $day['absolute_url']); | ||
419 | static::assertCount(1, $day['links']); | ||
420 | static::assertSame(4, $day['links'][0]['id']); | ||
421 | static::assertSame('http://domain.tld/4', $day['links'][0]['url']); | ||
422 | static::assertEquals($dates[2], $day['links'][0]['created']); | ||
427 | } | 423 | } |
428 | 424 | ||
429 | /** | 425 | /** |
@@ -475,4 +471,246 @@ class DailyControllerTest extends TestCase | |||
475 | static::assertFalse($assignedVariables['hide_timestamps']); | 471 | static::assertFalse($assignedVariables['hide_timestamps']); |
476 | static::assertCount(0, $assignedVariables['days']); | 472 | static::assertCount(0, $assignedVariables['days']); |
477 | } | 473 | } |
474 | |||
475 | /** | ||
476 | * Test simple display index with week parameter | ||
477 | */ | ||
478 | public function testSimpleIndexWeekly(): void | ||
479 | { | ||
480 | $currentDay = new \DateTimeImmutable('2020-05-13'); | ||
481 | $expectedDay = new \DateTimeImmutable('2020-05-11'); | ||
482 | |||
483 | $request = $this->createMock(Request::class); | ||
484 | $request->method('getQueryParam')->willReturnCallback(function (string $key) use ($currentDay): ?string { | ||
485 | return $key === 'week' ? $currentDay->format('YW') : null; | ||
486 | }); | ||
487 | $response = new Response(); | ||
488 | |||
489 | // Save RainTPL assigned variables | ||
490 | $assignedVariables = []; | ||
491 | $this->assignTemplateVars($assignedVariables); | ||
492 | |||
493 | $this->container->bookmarkService | ||
494 | ->expects(static::once()) | ||
495 | ->method('findByDate') | ||
496 | ->willReturnCallback( | ||
497 | function (): array { | ||
498 | return [ | ||
499 | (new Bookmark()) | ||
500 | ->setId(1) | ||
501 | ->setUrl('http://url.tld') | ||
502 | ->setTitle(static::generateString(50)) | ||
503 | ->setDescription(static::generateString(500)) | ||
504 | , | ||
505 | (new Bookmark()) | ||
506 | ->setId(2) | ||
507 | ->setUrl('http://url2.tld') | ||
508 | ->setTitle(static::generateString(50)) | ||
509 | ->setDescription(static::generateString(500)) | ||
510 | , | ||
511 | ]; | ||
512 | } | ||
513 | ) | ||
514 | ; | ||
515 | |||
516 | $result = $this->controller->index($request, $response); | ||
517 | |||
518 | static::assertSame(200, $result->getStatusCode()); | ||
519 | static::assertSame('daily', (string) $result->getBody()); | ||
520 | static::assertSame( | ||
521 | 'Weekly - Week 20 (May 11, 2020) - Shaarli', | ||
522 | $assignedVariables['pagetitle'] | ||
523 | ); | ||
524 | |||
525 | static::assertCount(2, $assignedVariables['linksToDisplay']); | ||
526 | static::assertEquals($expectedDay->setTime(0, 0), $assignedVariables['dayDate']); | ||
527 | static::assertSame($expectedDay->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); | ||
528 | static::assertSame('', $assignedVariables['previousday']); | ||
529 | static::assertSame('', $assignedVariables['nextday']); | ||
530 | static::assertSame('Week 20 (May 11, 2020)', $assignedVariables['dayDesc']); | ||
531 | static::assertSame('week', $assignedVariables['type']); | ||
532 | static::assertSame('Weekly', $assignedVariables['localizedType']); | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * Test simple display index with month parameter | ||
537 | */ | ||
538 | public function testSimpleIndexMonthly(): void | ||
539 | { | ||
540 | $currentDay = new \DateTimeImmutable('2020-05-13'); | ||
541 | $expectedDay = new \DateTimeImmutable('2020-05-01'); | ||
542 | |||
543 | $request = $this->createMock(Request::class); | ||
544 | $request->method('getQueryParam')->willReturnCallback(function (string $key) use ($currentDay): ?string { | ||
545 | return $key === 'month' ? $currentDay->format('Ym') : null; | ||
546 | }); | ||
547 | $response = new Response(); | ||
548 | |||
549 | // Save RainTPL assigned variables | ||
550 | $assignedVariables = []; | ||
551 | $this->assignTemplateVars($assignedVariables); | ||
552 | |||
553 | $this->container->bookmarkService | ||
554 | ->expects(static::once()) | ||
555 | ->method('findByDate') | ||
556 | ->willReturnCallback( | ||
557 | function (): array { | ||
558 | return [ | ||
559 | (new Bookmark()) | ||
560 | ->setId(1) | ||
561 | ->setUrl('http://url.tld') | ||
562 | ->setTitle(static::generateString(50)) | ||
563 | ->setDescription(static::generateString(500)) | ||
564 | , | ||
565 | (new Bookmark()) | ||
566 | ->setId(2) | ||
567 | ->setUrl('http://url2.tld') | ||
568 | ->setTitle(static::generateString(50)) | ||
569 | ->setDescription(static::generateString(500)) | ||
570 | , | ||
571 | ]; | ||
572 | } | ||
573 | ) | ||
574 | ; | ||
575 | |||
576 | $result = $this->controller->index($request, $response); | ||
577 | |||
578 | static::assertSame(200, $result->getStatusCode()); | ||
579 | static::assertSame('daily', (string) $result->getBody()); | ||
580 | static::assertSame( | ||
581 | 'Monthly - May, 2020 - Shaarli', | ||
582 | $assignedVariables['pagetitle'] | ||
583 | ); | ||
584 | |||
585 | static::assertCount(2, $assignedVariables['linksToDisplay']); | ||
586 | static::assertEquals($expectedDay->setTime(0, 0), $assignedVariables['dayDate']); | ||
587 | static::assertSame($expectedDay->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); | ||
588 | static::assertSame('', $assignedVariables['previousday']); | ||
589 | static::assertSame('', $assignedVariables['nextday']); | ||
590 | static::assertSame('May, 2020', $assignedVariables['dayDesc']); | ||
591 | static::assertSame('month', $assignedVariables['type']); | ||
592 | static::assertSame('Monthly', $assignedVariables['localizedType']); | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * Test simple display RSS with week parameter | ||
597 | */ | ||
598 | public function testSimpleRssWeekly(): void | ||
599 | { | ||
600 | $dates = [ | ||
601 | new \DateTimeImmutable('2020-05-19'), | ||
602 | new \DateTimeImmutable('2020-05-13'), | ||
603 | ]; | ||
604 | $expectedDates = [ | ||
605 | new \DateTimeImmutable('2020-05-24 23:59:59'), | ||
606 | new \DateTimeImmutable('2020-05-17 23:59:59'), | ||
607 | ]; | ||
608 | |||
609 | $this->container->environment['QUERY_STRING'] = 'week'; | ||
610 | $request = $this->createMock(Request::class); | ||
611 | $request->method('getQueryParam')->willReturnCallback(function (string $key): ?string { | ||
612 | return $key === 'week' ? '' : null; | ||
613 | }); | ||
614 | $response = new Response(); | ||
615 | |||
616 | $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ | ||
617 | (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), | ||
618 | (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), | ||
619 | (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), | ||
620 | ]); | ||
621 | |||
622 | // Save RainTPL assigned variables | ||
623 | $assignedVariables = []; | ||
624 | $this->assignTemplateVars($assignedVariables); | ||
625 | |||
626 | $result = $this->controller->rss($request, $response); | ||
627 | |||
628 | static::assertSame(200, $result->getStatusCode()); | ||
629 | static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); | ||
630 | static::assertSame('dailyrss', (string) $result->getBody()); | ||
631 | static::assertSame('Shaarli', $assignedVariables['title']); | ||
632 | static::assertSame('http://shaarli/subfolder/', $assignedVariables['index_url']); | ||
633 | static::assertSame('http://shaarli/subfolder/daily-rss?week', $assignedVariables['page_url']); | ||
634 | static::assertFalse($assignedVariables['hide_timestamps']); | ||
635 | static::assertCount(2, $assignedVariables['days']); | ||
636 | |||
637 | $day = $assignedVariables['days'][$dates[0]->format('YW')]; | ||
638 | $date = $expectedDates[0]; | ||
639 | |||
640 | static::assertEquals($date, $day['date']); | ||
641 | static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); | ||
642 | static::assertSame('Week 21 (May 18, 2020)', $day['date_human']); | ||
643 | static::assertSame('http://shaarli/subfolder/daily?week='. $dates[0]->format('YW'), $day['absolute_url']); | ||
644 | static::assertCount(1, $day['links']); | ||
645 | |||
646 | $day = $assignedVariables['days'][$dates[1]->format('YW')]; | ||
647 | $date = $expectedDates[1]; | ||
648 | |||
649 | static::assertEquals($date, $day['date']); | ||
650 | static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); | ||
651 | static::assertSame('Week 20 (May 11, 2020)', $day['date_human']); | ||
652 | static::assertSame('http://shaarli/subfolder/daily?week='. $dates[1]->format('YW'), $day['absolute_url']); | ||
653 | static::assertCount(2, $day['links']); | ||
654 | } | ||
655 | |||
656 | /** | ||
657 | * Test simple display RSS with month parameter | ||
658 | */ | ||
659 | public function testSimpleRssMonthly(): void | ||
660 | { | ||
661 | $dates = [ | ||
662 | new \DateTimeImmutable('2020-05-19'), | ||
663 | new \DateTimeImmutable('2020-04-13'), | ||
664 | ]; | ||
665 | $expectedDates = [ | ||
666 | new \DateTimeImmutable('2020-05-31 23:59:59'), | ||
667 | new \DateTimeImmutable('2020-04-30 23:59:59'), | ||
668 | ]; | ||
669 | |||
670 | $this->container->environment['QUERY_STRING'] = 'month'; | ||
671 | $request = $this->createMock(Request::class); | ||
672 | $request->method('getQueryParam')->willReturnCallback(function (string $key): ?string { | ||
673 | return $key === 'month' ? '' : null; | ||
674 | }); | ||
675 | $response = new Response(); | ||
676 | |||
677 | $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ | ||
678 | (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), | ||
679 | (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), | ||
680 | (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), | ||
681 | ]); | ||
682 | |||
683 | // Save RainTPL assigned variables | ||
684 | $assignedVariables = []; | ||
685 | $this->assignTemplateVars($assignedVariables); | ||
686 | |||
687 | $result = $this->controller->rss($request, $response); | ||
688 | |||
689 | static::assertSame(200, $result->getStatusCode()); | ||
690 | static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); | ||
691 | static::assertSame('dailyrss', (string) $result->getBody()); | ||
692 | static::assertSame('Shaarli', $assignedVariables['title']); | ||
693 | static::assertSame('http://shaarli/subfolder/', $assignedVariables['index_url']); | ||
694 | static::assertSame('http://shaarli/subfolder/daily-rss?month', $assignedVariables['page_url']); | ||
695 | static::assertFalse($assignedVariables['hide_timestamps']); | ||
696 | static::assertCount(2, $assignedVariables['days']); | ||
697 | |||
698 | $day = $assignedVariables['days'][$dates[0]->format('Ym')]; | ||
699 | $date = $expectedDates[0]; | ||
700 | |||
701 | static::assertEquals($date, $day['date']); | ||
702 | static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); | ||
703 | static::assertSame('May, 2020', $day['date_human']); | ||
704 | static::assertSame('http://shaarli/subfolder/daily?month='. $dates[0]->format('Ym'), $day['absolute_url']); | ||
705 | static::assertCount(1, $day['links']); | ||
706 | |||
707 | $day = $assignedVariables['days'][$dates[1]->format('Ym')]; | ||
708 | $date = $expectedDates[1]; | ||
709 | |||
710 | static::assertEquals($date, $day['date']); | ||
711 | static::assertSame($date->format(\DateTime::RSS), $day['date_rss']); | ||
712 | static::assertSame('April, 2020', $day['date_human']); | ||
713 | static::assertSame('http://shaarli/subfolder/daily?month='. $dates[1]->format('Ym'), $day['absolute_url']); | ||
714 | static::assertCount(2, $day['links']); | ||
715 | } | ||
478 | } | 716 | } |
diff --git a/tests/ApplicationUtilsTest.php b/tests/helper/ApplicationUtilsTest.php index ac46cbf1..654857b9 100644 --- a/tests/ApplicationUtilsTest.php +++ b/tests/helper/ApplicationUtilsTest.php | |||
@@ -1,7 +1,8 @@ | |||
1 | <?php | 1 | <?php |
2 | namespace Shaarli; | 2 | namespace Shaarli\Helper; |
3 | 3 | ||
4 | use Shaarli\Config\ConfigManager; | 4 | use Shaarli\Config\ConfigManager; |
5 | use Shaarli\FakeApplicationUtils; | ||
5 | 6 | ||
6 | require_once 'tests/utils/FakeApplicationUtils.php'; | 7 | require_once 'tests/utils/FakeApplicationUtils.php'; |
7 | 8 | ||
diff --git a/tests/helper/DailyPageHelperTest.php b/tests/helper/DailyPageHelperTest.php new file mode 100644 index 00000000..e0378491 --- /dev/null +++ b/tests/helper/DailyPageHelperTest.php | |||
@@ -0,0 +1,262 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Helper; | ||
6 | |||
7 | use Shaarli\Bookmark\Bookmark; | ||
8 | use Shaarli\TestCase; | ||
9 | use Slim\Http\Request; | ||
10 | |||
11 | class DailyPageHelperTest extends TestCase | ||
12 | { | ||
13 | /** | ||
14 | * @dataProvider getRequestedTypes | ||
15 | */ | ||
16 | public function testExtractRequestedType(array $queryParams, string $expectedType): void | ||
17 | { | ||
18 | $request = $this->createMock(Request::class); | ||
19 | $request->method('getQueryParam')->willReturnCallback(function ($key) use ($queryParams): ?string { | ||
20 | return $queryParams[$key] ?? null; | ||
21 | }); | ||
22 | |||
23 | $type = DailyPageHelper::extractRequestedType($request); | ||
24 | |||
25 | static::assertSame($type, $expectedType); | ||
26 | } | ||
27 | |||
28 | /** | ||
29 | * @dataProvider getRequestedDateTimes | ||
30 | */ | ||
31 | public function testExtractRequestedDateTime( | ||
32 | string $type, | ||
33 | string $input, | ||
34 | ?Bookmark $bookmark, | ||
35 | \DateTimeInterface $expectedDateTime, | ||
36 | string $compareFormat = 'Ymd' | ||
37 | ): void { | ||
38 | $dateTime = DailyPageHelper::extractRequestedDateTime($type, $input, $bookmark); | ||
39 | |||
40 | static::assertSame($dateTime->format($compareFormat), $expectedDateTime->format($compareFormat)); | ||
41 | } | ||
42 | |||
43 | public function testExtractRequestedDateTimeExceptionUnknownType(): void | ||
44 | { | ||
45 | $this->expectException(\Exception::class); | ||
46 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
47 | |||
48 | DailyPageHelper::extractRequestedDateTime('nope', null, null); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * @dataProvider getFormatsByType | ||
53 | */ | ||
54 | public function testGetFormatByType(string $type, string $expectedFormat): void | ||
55 | { | ||
56 | $format = DailyPageHelper::getFormatByType($type); | ||
57 | |||
58 | static::assertSame($expectedFormat, $format); | ||
59 | } | ||
60 | |||
61 | public function testGetFormatByTypeExceptionUnknownType(): void | ||
62 | { | ||
63 | $this->expectException(\Exception::class); | ||
64 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
65 | |||
66 | DailyPageHelper::getFormatByType('nope'); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * @dataProvider getStartDatesByType | ||
71 | */ | ||
72 | public function testGetStartDatesByType( | ||
73 | string $type, | ||
74 | \DateTimeImmutable $dateTime, | ||
75 | \DateTimeInterface $expectedDateTime | ||
76 | ): void { | ||
77 | $startDateTime = DailyPageHelper::getStartDateTimeByType($type, $dateTime); | ||
78 | |||
79 | static::assertEquals($expectedDateTime, $startDateTime); | ||
80 | } | ||
81 | |||
82 | public function testGetStartDatesByTypeExceptionUnknownType(): void | ||
83 | { | ||
84 | $this->expectException(\Exception::class); | ||
85 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
86 | |||
87 | DailyPageHelper::getStartDateTimeByType('nope', new \DateTimeImmutable()); | ||
88 | } | ||
89 | |||
90 | /** | ||
91 | * @dataProvider getEndDatesByType | ||
92 | */ | ||
93 | public function testGetEndDatesByType( | ||
94 | string $type, | ||
95 | \DateTimeImmutable $dateTime, | ||
96 | \DateTimeInterface $expectedDateTime | ||
97 | ): void { | ||
98 | $endDateTime = DailyPageHelper::getEndDateTimeByType($type, $dateTime); | ||
99 | |||
100 | static::assertEquals($expectedDateTime, $endDateTime); | ||
101 | } | ||
102 | |||
103 | public function testGetEndDatesByTypeExceptionUnknownType(): void | ||
104 | { | ||
105 | $this->expectException(\Exception::class); | ||
106 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
107 | |||
108 | DailyPageHelper::getEndDateTimeByType('nope', new \DateTimeImmutable()); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * @dataProvider getDescriptionsByType | ||
113 | */ | ||
114 | public function testGeDescriptionsByType( | ||
115 | string $type, | ||
116 | \DateTimeImmutable $dateTime, | ||
117 | string $expectedDescription | ||
118 | ): void { | ||
119 | $description = DailyPageHelper::getDescriptionByType($type, $dateTime); | ||
120 | |||
121 | static::assertEquals($expectedDescription, $description); | ||
122 | } | ||
123 | |||
124 | public function getDescriptionByTypeExceptionUnknownType(): void | ||
125 | { | ||
126 | $this->expectException(\Exception::class); | ||
127 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
128 | |||
129 | DailyPageHelper::getDescriptionByType('nope', new \DateTimeImmutable()); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * @dataProvider getRssLengthsByType | ||
134 | */ | ||
135 | public function testGeRssLengthsByType(string $type): void { | ||
136 | $length = DailyPageHelper::getRssLengthByType($type); | ||
137 | |||
138 | static::assertIsInt($length); | ||
139 | } | ||
140 | |||
141 | public function testGeRssLengthsByTypeExceptionUnknownType(): void | ||
142 | { | ||
143 | $this->expectException(\Exception::class); | ||
144 | $this->expectExceptionMessage('Unsupported daily format type'); | ||
145 | |||
146 | DailyPageHelper::getRssLengthByType('nope'); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * Data provider for testExtractRequestedType() test method. | ||
151 | */ | ||
152 | public function getRequestedTypes(): array | ||
153 | { | ||
154 | return [ | ||
155 | [['month' => null], DailyPageHelper::DAY], | ||
156 | [['month' => ''], DailyPageHelper::MONTH], | ||
157 | [['month' => 'content'], DailyPageHelper::MONTH], | ||
158 | [['week' => null], DailyPageHelper::DAY], | ||
159 | [['week' => ''], DailyPageHelper::WEEK], | ||
160 | [['week' => 'content'], DailyPageHelper::WEEK], | ||
161 | [['day' => null], DailyPageHelper::DAY], | ||
162 | [['day' => ''], DailyPageHelper::DAY], | ||
163 | [['day' => 'content'], DailyPageHelper::DAY], | ||
164 | ]; | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * Data provider for testExtractRequestedDateTime() test method. | ||
169 | */ | ||
170 | public function getRequestedDateTimes(): array | ||
171 | { | ||
172 | return [ | ||
173 | [DailyPageHelper::DAY, '20201013', null, new \DateTime('2020-10-13')], | ||
174 | [ | ||
175 | DailyPageHelper::DAY, | ||
176 | '', | ||
177 | (new Bookmark())->setCreated($date = new \DateTime('2020-10-13 12:05:31')), | ||
178 | $date, | ||
179 | ], | ||
180 | [DailyPageHelper::DAY, '', null, new \DateTime()], | ||
181 | [DailyPageHelper::WEEK, '202030', null, new \DateTime('2020-07-20')], | ||
182 | [ | ||
183 | DailyPageHelper::WEEK, | ||
184 | '', | ||
185 | (new Bookmark())->setCreated($date = new \DateTime('2020-10-13 12:05:31')), | ||
186 | new \DateTime('2020-10-13'), | ||
187 | ], | ||
188 | [DailyPageHelper::WEEK, '', null, new \DateTime(), 'Ym'], | ||
189 | [DailyPageHelper::MONTH, '202008', null, new \DateTime('2020-08-01'), 'Ym'], | ||
190 | [ | ||
191 | DailyPageHelper::MONTH, | ||
192 | '', | ||
193 | (new Bookmark())->setCreated($date = new \DateTime('2020-10-13 12:05:31')), | ||
194 | new \DateTime('2020-10-13'), | ||
195 | 'Ym' | ||
196 | ], | ||
197 | [DailyPageHelper::MONTH, '', null, new \DateTime(), 'Ym'], | ||
198 | ]; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * Data provider for testGetFormatByType() test method. | ||
203 | */ | ||
204 | public function getFormatsByType(): array | ||
205 | { | ||
206 | return [ | ||
207 | [DailyPageHelper::DAY, 'Ymd'], | ||
208 | [DailyPageHelper::WEEK, 'YW'], | ||
209 | [DailyPageHelper::MONTH, 'Ym'], | ||
210 | ]; | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * Data provider for testGetStartDatesByType() test method. | ||
215 | */ | ||
216 | public function getStartDatesByType(): array | ||
217 | { | ||
218 | return [ | ||
219 | [DailyPageHelper::DAY, new \DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-09 00:00:00')], | ||
220 | [DailyPageHelper::WEEK, new \DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-05 00:00:00')], | ||
221 | [DailyPageHelper::MONTH, new \DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-01 00:00:00')], | ||
222 | ]; | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * Data provider for testGetEndDatesByType() test method. | ||
227 | */ | ||
228 | public function getEndDatesByType(): array | ||
229 | { | ||
230 | return [ | ||
231 | [DailyPageHelper::DAY, new \DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-09 23:59:59')], | ||
232 | [DailyPageHelper::WEEK, new \DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-11 23:59:59')], | ||
233 | [DailyPageHelper::MONTH, new \DateTimeImmutable('2020-10-09 04:05:06'), new \DateTime('2020-10-31 23:59:59')], | ||
234 | ]; | ||
235 | } | ||
236 | |||
237 | /** | ||
238 | * Data provider for testGetDescriptionsByType() test method. | ||
239 | */ | ||
240 | public function getDescriptionsByType(): array | ||
241 | { | ||
242 | return [ | ||
243 | [DailyPageHelper::DAY, $date = new \DateTimeImmutable(), 'Today - ' . $date->format('F d, Y')], | ||
244 | [DailyPageHelper::DAY, $date = new \DateTimeImmutable('-1 day'), 'Yesterday - ' . $date->format('F d, Y')], | ||
245 | [DailyPageHelper::DAY, new \DateTimeImmutable('2020-10-09 04:05:06'), 'October 9, 2020'], | ||
246 | [DailyPageHelper::WEEK, new \DateTimeImmutable('2020-10-09 04:05:06'), 'Week 41 (October 5, 2020)'], | ||
247 | [DailyPageHelper::MONTH, new \DateTimeImmutable('2020-10-09 04:05:06'), 'October, 2020'], | ||
248 | ]; | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * Data provider for testGetDescriptionsByType() test method. | ||
253 | */ | ||
254 | public function getRssLengthsByType(): array | ||
255 | { | ||
256 | return [ | ||
257 | [DailyPageHelper::DAY], | ||
258 | [DailyPageHelper::WEEK], | ||
259 | [DailyPageHelper::MONTH], | ||
260 | ]; | ||
261 | } | ||
262 | } | ||
diff --git a/tests/FileUtilsTest.php b/tests/helper/FileUtilsTest.php index 3384504a..8035f79c 100644 --- a/tests/FileUtilsTest.php +++ b/tests/helper/FileUtilsTest.php | |||
@@ -1,9 +1,10 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | namespace Shaarli; | 3 | namespace Shaarli\Helper; |
4 | 4 | ||
5 | use Exception; | 5 | use Exception; |
6 | use Shaarli\Exceptions\IOException; | 6 | use Shaarli\Exceptions\IOException; |
7 | use Shaarli\TestCase; | ||
7 | 8 | ||
8 | /** | 9 | /** |
9 | * Class FileUtilsTest | 10 | * Class FileUtilsTest |
diff --git a/tests/security/BanManagerTest.php b/tests/security/BanManagerTest.php index 22aa8666..29d2791b 100644 --- a/tests/security/BanManagerTest.php +++ b/tests/security/BanManagerTest.php | |||
@@ -4,7 +4,7 @@ | |||
4 | namespace Shaarli\Security; | 4 | namespace Shaarli\Security; |
5 | 5 | ||
6 | use Psr\Log\LoggerInterface; | 6 | use Psr\Log\LoggerInterface; |
7 | use Shaarli\FileUtils; | 7 | use Shaarli\Helper\FileUtils; |
8 | use Shaarli\TestCase; | 8 | use Shaarli\TestCase; |
9 | 9 | ||
10 | /** | 10 | /** |
diff --git a/tests/utils/FakeApplicationUtils.php b/tests/utils/FakeApplicationUtils.php index de83d598..d5289ede 100644 --- a/tests/utils/FakeApplicationUtils.php +++ b/tests/utils/FakeApplicationUtils.php | |||
@@ -2,6 +2,8 @@ | |||
2 | 2 | ||
3 | namespace Shaarli; | 3 | namespace Shaarli; |
4 | 4 | ||
5 | use Shaarli\Helper\ApplicationUtils; | ||
6 | |||
5 | /** | 7 | /** |
6 | * Fake ApplicationUtils class to avoid HTTP requests | 8 | * Fake ApplicationUtils class to avoid HTTP requests |
7 | */ | 9 | */ |
diff --git a/tests/utils/ReferenceHistory.php b/tests/utils/ReferenceHistory.php index 516c9f51..aed5d2cf 100644 --- a/tests/utils/ReferenceHistory.php +++ b/tests/utils/ReferenceHistory.php | |||
@@ -1,6 +1,6 @@ | |||
1 | <?php | 1 | <?php |
2 | 2 | ||
3 | use Shaarli\FileUtils; | 3 | use Shaarli\Helper\FileUtils; |
4 | use Shaarli\History; | 4 | use Shaarli\History; |
5 | 5 | ||
6 | /** | 6 | /** |
diff --git a/tpl/default/daily.html b/tpl/default/daily.html index 3749bffb..5e038c39 100644 --- a/tpl/default/daily.html +++ b/tpl/default/daily.html | |||
@@ -7,11 +7,24 @@ | |||
7 | {include="page.header"} | 7 | {include="page.header"} |
8 | 8 | ||
9 | <div class="pure-g"> | 9 | <div class="pure-g"> |
10 | <div class="pure-u-1 pure-alert pure-alert-success tag-sort"> | ||
11 | <a href="{$base_path}/daily?day">{'Daily'|t}</a> | ||
12 | <a href="{$base_path}/daily?week">{'Weekly'|t}</a> | ||
13 | <a href="{$base_path}/daily?month">{'Monthly'|t}</a> | ||
14 | </div> | ||
15 | </div> | ||
16 | |||
17 | |||
18 | <div class="pure-g"> | ||
10 | <div class="pure-u-lg-1-6 pure-u-1-24"></div> | 19 | <div class="pure-u-lg-1-6 pure-u-1-24"></div> |
11 | <div class="pure-u-lg-2-3 pure-u-22-24 page-form page-visitor" id="daily"> | 20 | <div class="pure-u-lg-2-3 pure-u-22-24 page-form page-visitor" id="daily"> |
12 | <h2 class="window-title"> | 21 | <h2 class="window-title"> |
13 | {'The Daily Shaarli'|t} | 22 | {$localizedType} Shaarli |
14 | <a href="{$base_path}/daily-rss" title="{'1 RSS entry per day'|t}"><i class="fa fa-rss"></i></a> | 23 | <a href="{$base_path}/daily-rss?{$type}" |
24 | title="{function="t('1 RSS entry per :type', '', 1, 'shaarli', [':type' => t($type)])"}" | ||
25 | > | ||
26 | <i class="fa fa-rss"></i> | ||
27 | </a> | ||
15 | </h2> | 28 | </h2> |
16 | 29 | ||
17 | <div id="plugin_zone_start_daily" class="plugin_zone"> | 30 | <div id="plugin_zone_start_daily" class="plugin_zone"> |
@@ -25,19 +38,19 @@ | |||
25 | <div class="pure-g"> | 38 | <div class="pure-g"> |
26 | <div class="pure-u-lg-1-3 pure-u-1 center"> | 39 | <div class="pure-u-lg-1-3 pure-u-1 center"> |
27 | {if="$previousday"} | 40 | {if="$previousday"} |
28 | <a href="{$base_path}/daily?day={$previousday}"> | 41 | <a href="{$base_path}/daily?{$type}={$previousday}"> |
29 | <i class="fa fa-arrow-left"></i> | 42 | <i class="fa fa-arrow-left"></i> |
30 | {'Previous day'|t} | 43 | {function="t('Previous :type', '', 1, 'shaarli', [':type' => t($type)], true)"} |
31 | </a> | 44 | </a> |
32 | {/if} | 45 | {/if} |
33 | </div> | 46 | </div> |
34 | <div class="daily-desc pure-u-lg-1-3 pure-u-1 center"> | 47 | <div class="daily-desc pure-u-lg-1-3 pure-u-1 center"> |
35 | {'All links of one day in a single page.'|t} | 48 | {function="t('All links of one :type in a single page.', '', 1, 'shaarli', [':type' => t($type)])"} |
36 | </div> | 49 | </div> |
37 | <div class="pure-u-lg-1-3 pure-u-1 center"> | 50 | <div class="pure-u-lg-1-3 pure-u-1 center"> |
38 | {if="$nextday"} | 51 | {if="$nextday"} |
39 | <a href="{$base_path}/daily?day={$nextday}"> | 52 | <a href="{$base_path}/daily?{$type}={$nextday}"> |
40 | {'Next day'|t} | 53 | {function="t('Next :type', '', 1, 'shaarli', [':type' => t($type)], true)"} |
41 | <i class="fa fa-arrow-right"></i> | 54 | <i class="fa fa-arrow-right"></i> |
42 | </a> | 55 | </a> |
43 | {/if} | 56 | {/if} |
@@ -45,10 +58,7 @@ | |||
45 | </div> | 58 | </div> |
46 | <div> | 59 | <div> |
47 | <h3 class="window-subtitle"> | 60 | <h3 class="window-subtitle"> |
48 | {if="!empty($dayDesc)"} | 61 | {$dayDesc} |
49 | {$dayDesc} - | ||
50 | {/if} | ||
51 | {function="format_date($dayDate, false)"} | ||
52 | </h3> | 62 | </h3> |
53 | 63 | ||
54 | <div id="plugin_zone_about_daily" class="plugin_zone"> | 64 | <div id="plugin_zone_about_daily" class="plugin_zone"> |
diff --git a/tpl/default/dailyrss.html b/tpl/default/dailyrss.html index d40d9496..871a3ba7 100644 --- a/tpl/default/dailyrss.html +++ b/tpl/default/dailyrss.html | |||
@@ -1,9 +1,9 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <rss version="2.0"> | 2 | <rss version="2.0"> |
3 | <channel> | 3 | <channel> |
4 | <title>Daily - {$title}</title> | 4 | <title>{$localizedType} - {$title}</title> |
5 | <link>{$index_url}</link> | 5 | <link>{$index_url}</link> |
6 | <description>Daily shaared bookmarks</description> | 6 | <description>{function="t('All links of one :type in a single page.', '', 1, 'shaarli', [':type' => t($type)])"}</description> |
7 | <language>{$language}</language> | 7 | <language>{$language}</language> |
8 | <copyright>{$index_url}</copyright> | 8 | <copyright>{$index_url}</copyright> |
9 | <generator>Shaarli</generator> | 9 | <generator>Shaarli</generator> |
@@ -18,12 +18,15 @@ | |||
18 | {loop="$value.links"} | 18 | {loop="$value.links"} |
19 | <h3><a href="{$value.url}">{$value.title}</a></h3> | 19 | <h3><a href="{$value.url}">{$value.title}</a></h3> |
20 | <small> | 20 | <small> |
21 | {if="!$hide_timestamps"}{$value.created|format_date} - {/if}{if="$value.tags"}{$value.tags}{/if}<br> | 21 | {if="!$hide_timestamps"}{$value.created|format_date} — {/if} |
22 | <a href="{$index_url}shaare/{$value.shorturl}">{'Permalink'|t}</a> | ||
23 | {if="$value.tags"} — {$value.tags}{/if} | ||
24 | <br> | ||
22 | {$value.url} | 25 | {$value.url} |
23 | </small><br> | 26 | </small><br> |
24 | {if="$value.thumbnail"}<img src="{$index_url}{$value.thumbnail}#" alt="thumbnail" />{/if}<br> | 27 | {if="$value.thumbnail"}<img src="{$index_url}{$value.thumbnail}#" alt="thumbnail" />{/if}<br> |
25 | {if="$value.description"}{$value.description}{/if} | 28 | {if="$value.description"}{$value.description}{/if} |
26 | <br><br><hr> | 29 | <br><hr> |
27 | {/loop} | 30 | {/loop} |
28 | ]]></description> | 31 | ]]></description> |
29 | </item> | 32 | </item> |