aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/front
diff options
context:
space:
mode:
Diffstat (limited to 'application/front')
-rw-r--r--application/front/ShaarliMiddleware.php73
-rw-r--r--application/front/controller/admin/ConfigureController.php3
-rw-r--r--application/front/controller/admin/ExportController.php5
-rw-r--r--application/front/controller/admin/ImportController.php3
-rw-r--r--application/front/controller/admin/ManageShaareController.php5
-rw-r--r--application/front/controller/admin/ManageTagController.php3
-rw-r--r--application/front/controller/admin/PasswordController.php9
-rw-r--r--application/front/controller/admin/PluginsController.php3
-rw-r--r--application/front/controller/admin/ThumbnailsController.php18
-rw-r--r--application/front/controller/admin/ToolsController.php3
-rw-r--r--application/front/controller/visitor/BookmarkListController.php248
-rw-r--r--application/front/controller/visitor/DailyController.php5
-rw-r--r--application/front/controller/visitor/LoginController.php3
-rw-r--r--application/front/controller/visitor/OpenSearchController.php3
-rw-r--r--application/front/controller/visitor/PictureWallController.php3
15 files changed, 345 insertions, 42 deletions
diff --git a/application/front/ShaarliMiddleware.php b/application/front/ShaarliMiddleware.php
index 7ad610c7..baea6ef2 100644
--- a/application/front/ShaarliMiddleware.php
+++ b/application/front/ShaarliMiddleware.php
@@ -25,6 +25,8 @@ class ShaarliMiddleware
25 25
26 /** 26 /**
27 * Middleware execution: 27 * Middleware execution:
28 * - run updates
29 * - if not logged in open shaarli, redirect to login
28 * - execute the controller 30 * - execute the controller
29 * - return the response 31 * - return the response
30 * 32 *
@@ -36,27 +38,82 @@ class ShaarliMiddleware
36 * 38 *
37 * @return Response response. 39 * @return Response response.
38 */ 40 */
39 public function __invoke(Request $request, Response $response, callable $next) 41 public function __invoke(Request $request, Response $response, callable $next): Response
40 { 42 {
41 $this->container->basePath = rtrim($request->getUri()->getBasePath(), '/'); 43 $this->container->basePath = rtrim($request->getUri()->getBasePath(), '/');
42 44
43 try { 45 try {
44 $response = $next($request, $response); 46 $this->runUpdates();
47 $this->checkOpenShaarli($request, $response, $next);
48
49 return $next($request, $response);
45 } catch (ShaarliFrontException $e) { 50 } catch (ShaarliFrontException $e) {
51 // Possible functional error
52 $this->container->pageBuilder->reset();
46 $this->container->pageBuilder->assign('message', $e->getMessage()); 53 $this->container->pageBuilder->assign('message', $e->getMessage());
54
55 $response = $response->withStatus($e->getCode());
56
57 return $response->write($this->container->pageBuilder->render('error'));
58 } catch (UnauthorizedException $e) {
59 return $response->withRedirect($this->container->basePath . '/login');
60 } catch (\Throwable $e) {
61 // Unknown error encountered
62 $this->container->pageBuilder->reset();
47 if ($this->container->conf->get('dev.debug', false)) { 63 if ($this->container->conf->get('dev.debug', false)) {
64 $this->container->pageBuilder->assign('message', $e->getMessage());
48 $this->container->pageBuilder->assign( 65 $this->container->pageBuilder->assign(
49 'stacktrace', 66 'stacktrace',
50 nl2br(get_class($this) .': '. $e->getTraceAsString()) 67 nl2br(get_class($e) .': '. PHP_EOL . $e->getTraceAsString())
51 ); 68 );
69 } else {
70 $this->container->pageBuilder->assign('message', t('An unexpected error occurred.'));
52 } 71 }
53 72
54 $response = $response->withStatus($e->getCode()); 73 $response = $response->withStatus(500);
55 $response = $response->write($this->container->pageBuilder->render('error')); 74
56 } catch (UnauthorizedException $e) { 75 return $response->write($this->container->pageBuilder->render('error'));
57 return $response->withRedirect($this->container->basePath . '/login'); 76 }
77 }
78
79 /**
80 * Run the updater for every requests processed while logged in.
81 */
82 protected function runUpdates(): void
83 {
84 if ($this->container->loginManager->isLoggedIn() !== true) {
85 return;
86 }
87
88 $newUpdates = $this->container->updater->update();
89 if (!empty($newUpdates)) {
90 $this->container->updater->writeUpdates(
91 $this->container->conf->get('resource.updates'),
92 $this->container->updater->getDoneUpdates()
93 );
94
95 $this->container->pageCacheManager->invalidateCaches();
96 }
97 }
98
99 /**
100 * Access is denied to most pages with `hide_public_links` + `force_login` settings.
101 */
102 protected function checkOpenShaarli(Request $request, Response $response, callable $next): bool
103 {
104 if (// if the user isn't logged in
105 !$this->container->loginManager->isLoggedIn()
106 // and Shaarli doesn't have public content...
107 && $this->container->conf->get('privacy.hide_public_links')
108 // and is configured to enforce the login
109 && $this->container->conf->get('privacy.force_login')
110 // and the current page isn't already the login page
111 // and the user is not requesting a feed (which would lead to a different content-type as expected)
112 && !in_array($next->getName(), ['login', 'atom', 'rss'], true)
113 ) {
114 throw new UnauthorizedException();
58 } 115 }
59 116
60 return $response; 117 return true;
61 } 118 }
62} 119}
diff --git a/application/front/controller/admin/ConfigureController.php b/application/front/controller/admin/ConfigureController.php
index 201a859b..865fc2b0 100644
--- a/application/front/controller/admin/ConfigureController.php
+++ b/application/front/controller/admin/ConfigureController.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Admin; 5namespace Shaarli\Front\Controller\Admin;
6 6
7use Shaarli\Languages; 7use Shaarli\Languages;
8use Shaarli\Render\TemplatePage;
8use Shaarli\Render\ThemeUtils; 9use Shaarli\Render\ThemeUtils;
9use Shaarli\Thumbnailer; 10use Shaarli\Thumbnailer;
10use Slim\Http\Request; 11use Slim\Http\Request;
@@ -52,7 +53,7 @@ class ConfigureController extends ShaarliAdminController
52 $this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)); 53 $this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE));
53 $this->assignView('pagetitle', t('Configure') .' - '. $this->container->conf->get('general.title', 'Shaarli')); 54 $this->assignView('pagetitle', t('Configure') .' - '. $this->container->conf->get('general.title', 'Shaarli'));
54 55
55 return $response->write($this->render('configure')); 56 return $response->write($this->render(TemplatePage::CONFIGURE));
56 } 57 }
57 58
58 /** 59 /**
diff --git a/application/front/controller/admin/ExportController.php b/application/front/controller/admin/ExportController.php
index 7afbfc23..2be957fa 100644
--- a/application/front/controller/admin/ExportController.php
+++ b/application/front/controller/admin/ExportController.php
@@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller\Admin;
6 6
7use DateTime; 7use DateTime;
8use Shaarli\Bookmark\Bookmark; 8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Render\TemplatePage;
9use Slim\Http\Request; 10use Slim\Http\Request;
10use Slim\Http\Response; 11use Slim\Http\Response;
11 12
@@ -24,7 +25,7 @@ class ExportController extends ShaarliAdminController
24 { 25 {
25 $this->assignView('pagetitle', t('Export') .' - '. $this->container->conf->get('general.title', 'Shaarli')); 26 $this->assignView('pagetitle', t('Export') .' - '. $this->container->conf->get('general.title', 'Shaarli'));
26 27
27 return $response->write($this->render('export')); 28 return $response->write($this->render(TemplatePage::EXPORT));
28 } 29 }
29 30
30 /** 31 /**
@@ -74,6 +75,6 @@ class ExportController extends ShaarliAdminController
74 $this->assignView('eol', PHP_EOL); 75 $this->assignView('eol', PHP_EOL);
75 $this->assignView('selection', $selection); 76 $this->assignView('selection', $selection);
76 77
77 return $response->write($this->render('export.bookmarks')); 78 return $response->write($this->render(TemplatePage::NETSCAPE_EXPORT_BOOKMARKS));
78 } 79 }
79} 80}
diff --git a/application/front/controller/admin/ImportController.php b/application/front/controller/admin/ImportController.php
index 8c5305b9..758d5ef9 100644
--- a/application/front/controller/admin/ImportController.php
+++ b/application/front/controller/admin/ImportController.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Admin; 5namespace Shaarli\Front\Controller\Admin;
6 6
7use Psr\Http\Message\UploadedFileInterface; 7use Psr\Http\Message\UploadedFileInterface;
8use Shaarli\Render\TemplatePage;
8use Slim\Http\Request; 9use Slim\Http\Request;
9use Slim\Http\Response; 10use Slim\Http\Response;
10 11
@@ -39,7 +40,7 @@ class ImportController extends ShaarliAdminController
39 ); 40 );
40 $this->assignView('pagetitle', t('Import') .' - '. $this->container->conf->get('general.title', 'Shaarli')); 41 $this->assignView('pagetitle', t('Import') .' - '. $this->container->conf->get('general.title', 'Shaarli'));
41 42
42 return $response->write($this->render('import')); 43 return $response->write($this->render(TemplatePage::IMPORT));
43 } 44 }
44 45
45 /** 46 /**
diff --git a/application/front/controller/admin/ManageShaareController.php b/application/front/controller/admin/ManageShaareController.php
index bdfc5ca7..3aa48423 100644
--- a/application/front/controller/admin/ManageShaareController.php
+++ b/application/front/controller/admin/ManageShaareController.php
@@ -7,6 +7,7 @@ namespace Shaarli\Front\Controller\Admin;
7use Shaarli\Bookmark\Bookmark; 7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException; 8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Formatter\BookmarkMarkdownFormatter; 9use Shaarli\Formatter\BookmarkMarkdownFormatter;
10use Shaarli\Render\TemplatePage;
10use Shaarli\Thumbnailer; 11use Shaarli\Thumbnailer;
11use Slim\Http\Request; 12use Slim\Http\Request;
12use Slim\Http\Response; 13use Slim\Http\Response;
@@ -28,7 +29,7 @@ class ManageShaareController extends ShaarliAdminController
28 t('Shaare a new link') .' - '. $this->container->conf->get('general.title', 'Shaarli') 29 t('Shaare a new link') .' - '. $this->container->conf->get('general.title', 'Shaarli')
29 ); 30 );
30 31
31 return $response->write($this->render('addlink')); 32 return $response->write($this->render(TemplatePage::ADDLINK));
32 } 33 }
33 34
34 /** 35 /**
@@ -365,7 +366,7 @@ class ManageShaareController extends ShaarliAdminController
365 $editLabel . t('Shaare') .' - '. $this->container->conf->get('general.title', 'Shaarli') 366 $editLabel . t('Shaare') .' - '. $this->container->conf->get('general.title', 'Shaarli')
366 ); 367 );
367 368
368 return $response->write($this->render('editlink')); 369 return $response->write($this->render(TemplatePage::EDIT_LINK));
369 } 370 }
370 371
371 /** 372 /**
diff --git a/application/front/controller/admin/ManageTagController.php b/application/front/controller/admin/ManageTagController.php
index 7dab288a..0380ef1f 100644
--- a/application/front/controller/admin/ManageTagController.php
+++ b/application/front/controller/admin/ManageTagController.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Admin; 5namespace Shaarli\Front\Controller\Admin;
6 6
7use Shaarli\Bookmark\BookmarkFilter; 7use Shaarli\Bookmark\BookmarkFilter;
8use Shaarli\Render\TemplatePage;
8use Slim\Http\Request; 9use Slim\Http\Request;
9use Slim\Http\Response; 10use Slim\Http\Response;
10 11
@@ -28,7 +29,7 @@ class ManageTagController extends ShaarliAdminController
28 t('Manage tags') .' - '. $this->container->conf->get('general.title', 'Shaarli') 29 t('Manage tags') .' - '. $this->container->conf->get('general.title', 'Shaarli')
29 ); 30 );
30 31
31 return $response->write($this->render('changetag')); 32 return $response->write($this->render(TemplatePage::CHANGE_TAG));
32 } 33 }
33 34
34 /** 35 /**
diff --git a/application/front/controller/admin/PasswordController.php b/application/front/controller/admin/PasswordController.php
index bcce01a6..5ec0d24b 100644
--- a/application/front/controller/admin/PasswordController.php
+++ b/application/front/controller/admin/PasswordController.php
@@ -7,6 +7,7 @@ namespace Shaarli\Front\Controller\Admin;
7use Shaarli\Container\ShaarliContainer; 7use Shaarli\Container\ShaarliContainer;
8use Shaarli\Front\Exception\OpenShaarliPasswordException; 8use Shaarli\Front\Exception\OpenShaarliPasswordException;
9use Shaarli\Front\Exception\ShaarliFrontException; 9use Shaarli\Front\Exception\ShaarliFrontException;
10use Shaarli\Render\TemplatePage;
10use Slim\Http\Request; 11use Slim\Http\Request;
11use Slim\Http\Response; 12use Slim\Http\Response;
12use Throwable; 13use Throwable;
@@ -33,7 +34,7 @@ class PasswordController extends ShaarliAdminController
33 */ 34 */
34 public function index(Request $request, Response $response): Response 35 public function index(Request $request, Response $response): Response
35 { 36 {
36 return $response->write($this->render('changepassword')); 37 return $response->write($this->render(TemplatePage::CHANGE_PASSWORD));
37 } 38 }
38 39
39 /** 40 /**
@@ -55,7 +56,7 @@ class PasswordController extends ShaarliAdminController
55 56
56 return $response 57 return $response
57 ->withStatus(400) 58 ->withStatus(400)
58 ->write($this->render('changepassword')) 59 ->write($this->render(TemplatePage::CHANGE_PASSWORD))
59 ; 60 ;
60 } 61 }
61 62
@@ -71,7 +72,7 @@ class PasswordController extends ShaarliAdminController
71 72
72 return $response 73 return $response
73 ->withStatus(400) 74 ->withStatus(400)
74 ->write($this->render('changepassword')) 75 ->write($this->render(TemplatePage::CHANGE_PASSWORD))
75 ; 76 ;
76 } 77 }
77 78
@@ -95,6 +96,6 @@ class PasswordController extends ShaarliAdminController
95 96
96 $this->saveSuccessMessage(t('Your password has been changed')); 97 $this->saveSuccessMessage(t('Your password has been changed'));
97 98
98 return $response->write($this->render('changepassword')); 99 return $response->write($this->render(TemplatePage::CHANGE_PASSWORD));
99 } 100 }
100} 101}
diff --git a/application/front/controller/admin/PluginsController.php b/application/front/controller/admin/PluginsController.php
index d5ec91f0..44025395 100644
--- a/application/front/controller/admin/PluginsController.php
+++ b/application/front/controller/admin/PluginsController.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Admin; 5namespace Shaarli\Front\Controller\Admin;
6 6
7use Exception; 7use Exception;
8use Shaarli\Render\TemplatePage;
8use Slim\Http\Request; 9use Slim\Http\Request;
9use Slim\Http\Response; 10use Slim\Http\Response;
10 11
@@ -44,7 +45,7 @@ class PluginsController extends ShaarliAdminController
44 t('Plugin Administration') .' - '. $this->container->conf->get('general.title', 'Shaarli') 45 t('Plugin Administration') .' - '. $this->container->conf->get('general.title', 'Shaarli')
45 ); 46 );
46 47
47 return $response->write($this->render('pluginsadmin')); 48 return $response->write($this->render(TemplatePage::PLUGINS_ADMIN));
48 } 49 }
49 50
50 /** 51 /**
diff --git a/application/front/controller/admin/ThumbnailsController.php b/application/front/controller/admin/ThumbnailsController.php
index e5308510..81c87ed0 100644
--- a/application/front/controller/admin/ThumbnailsController.php
+++ b/application/front/controller/admin/ThumbnailsController.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Admin; 5namespace Shaarli\Front\Controller\Admin;
6 6
7use Shaarli\Bookmark\Exception\BookmarkNotFoundException; 7use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
8use Shaarli\Render\TemplatePage;
8use Slim\Http\Request; 9use Slim\Http\Request;
9use Slim\Http\Response; 10use Slim\Http\Response;
10 11
@@ -36,7 +37,7 @@ class ThumbnailsController extends ShaarliAdminController
36 t('Thumbnails update') .' - '. $this->container->conf->get('general.title', 'Shaarli') 37 t('Thumbnails update') .' - '. $this->container->conf->get('general.title', 'Shaarli')
37 ); 38 );
38 39
39 return $response->write($this->render('thumbnails')); 40 return $response->write($this->render(TemplatePage::THUMBNAILS));
40 } 41 }
41 42
42 /** 43 /**
@@ -61,19 +62,4 @@ class ThumbnailsController extends ShaarliAdminController
61 62
62 return $response->withJson($this->container->formatterFactory->getFormatter('raw')->format($bookmark)); 63 return $response->withJson($this->container->formatterFactory->getFormatter('raw')->format($bookmark));
63 } 64 }
64
65 /**
66 * @param mixed[] $data Variables passed to the template engine
67 *
68 * @return mixed[] Template data after active plugins render_picwall hook execution.
69 */
70 protected function executeHooks(array $data): array
71 {
72 $this->container->pluginManager->executeHooks(
73 'render_tools',
74 $data
75 );
76
77 return $data;
78 }
79} 65}
diff --git a/application/front/controller/admin/ToolsController.php b/application/front/controller/admin/ToolsController.php
index d087f2cd..a476e898 100644
--- a/application/front/controller/admin/ToolsController.php
+++ b/application/front/controller/admin/ToolsController.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
4 4
5namespace Shaarli\Front\Controller\Admin; 5namespace Shaarli\Front\Controller\Admin;
6 6
7use Shaarli\Render\TemplatePage;
7use Slim\Http\Request; 8use Slim\Http\Request;
8use Slim\Http\Response; 9use Slim\Http\Response;
9 10
@@ -29,7 +30,7 @@ class ToolsController extends ShaarliAdminController
29 30
30 $this->assignView('pagetitle', t('Tools') .' - '. $this->container->conf->get('general.title', 'Shaarli')); 31 $this->assignView('pagetitle', t('Tools') .' - '. $this->container->conf->get('general.title', 'Shaarli'));
31 32
32 return $response->write($this->render('tools')); 33 return $response->write($this->render(TemplatePage::TOOLS));
33 } 34 }
34 35
35 /** 36 /**
diff --git a/application/front/controller/visitor/BookmarkListController.php b/application/front/controller/visitor/BookmarkListController.php
new file mode 100644
index 00000000..a37a7f6b
--- /dev/null
+++ b/application/front/controller/visitor/BookmarkListController.php
@@ -0,0 +1,248 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Legacy\LegacyController;
10use Shaarli\Legacy\UnknowLegacyRouteException;
11use Shaarli\Render\TemplatePage;
12use Shaarli\Thumbnailer;
13use Slim\Http\Request;
14use Slim\Http\Response;
15
16/**
17 * Class BookmarkListController
18 *
19 * Slim controller used to render the bookmark list, the home page of Shaarli.
20 * It also displays permalinks, and process legacy routes based on GET parameters.
21 */
22class BookmarkListController extends ShaarliVisitorController
23{
24 /**
25 * GET / - Displays the bookmark list, with optional filter parameters.
26 */
27 public function index(Request $request, Response $response): Response
28 {
29 $legacyResponse = $this->processLegacyController($request, $response);
30 if (null !== $legacyResponse) {
31 return $legacyResponse;
32 }
33
34 $formatter = $this->container->formatterFactory->getFormatter();
35
36 $searchTags = escape(normalize_spaces($request->getParam('searchtags') ?? ''));
37 $searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? ''));;
38
39 // Filter bookmarks according search parameters.
40 $visibility = $this->container->sessionManager->getSessionParameter('visibility');
41 $search = [
42 'searchtags' => $searchTags,
43 'searchterm' => $searchTerm,
44 ];
45 $linksToDisplay = $this->container->bookmarkService->search(
46 $search,
47 $visibility,
48 false,
49 !!$this->container->sessionManager->getSessionParameter('untaggedonly')
50 ) ?? [];
51
52 // ---- Handle paging.
53 $keys = [];
54 foreach ($linksToDisplay as $key => $value) {
55 $keys[] = $key;
56 }
57
58 $linksPerPage = $this->container->sessionManager->getSessionParameter('LINKS_PER_PAGE', 20) ?: 20;
59
60 // Select articles according to paging.
61 $pageCount = (int) ceil(count($keys) / $linksPerPage) ?: 1;
62 $page = (int) $request->getParam('page') ?? 1;
63 $page = $page < 1 ? 1 : $page;
64 $page = $page > $pageCount ? $pageCount : $page;
65
66 // Start index.
67 $i = ($page - 1) * $linksPerPage;
68 $end = $i + $linksPerPage;
69
70 $linkDisp = [];
71 $save = false;
72 while ($i < $end && $i < count($keys)) {
73 $save = $this->updateThumbnail($linksToDisplay[$keys[$i]], false) || $save;
74 $link = $formatter->format($linksToDisplay[$keys[$i]]);
75
76 $linkDisp[$keys[$i]] = $link;
77 $i++;
78 }
79
80 if ($save) {
81 $this->container->bookmarkService->save();
82 }
83
84 // Compute paging navigation
85 $searchtagsUrl = $searchTags === '' ? '' : '&searchtags=' . urlencode($searchTags);
86 $searchtermUrl = $searchTerm === '' ? '' : '&searchterm=' . urlencode($searchTerm);
87
88 $previous_page_url = '';
89 if ($i !== count($keys)) {
90 $previous_page_url = '?page=' . ($page + 1) . $searchtermUrl . $searchtagsUrl;
91 }
92 $next_page_url = '';
93 if ($page > 1) {
94 $next_page_url = '?page=' . ($page - 1) . $searchtermUrl . $searchtagsUrl;
95 }
96
97 // Fill all template fields.
98 $data = array_merge(
99 $this->initializeTemplateVars(),
100 [
101 'previous_page_url' => $previous_page_url,
102 'next_page_url' => $next_page_url,
103 'page_current' => $page,
104 'page_max' => $pageCount,
105 'result_count' => count($linksToDisplay),
106 'search_term' => $searchTerm,
107 'search_tags' => $searchTags,
108 'visibility' => $visibility,
109 'links' => $linkDisp,
110 ]
111 );
112
113 if (!empty($searchTerm) || !empty($searchTags)) {
114 $data['pagetitle'] = t('Search: ');
115 $data['pagetitle'] .= ! empty($searchTerm) ? $searchTerm . ' ' : '';
116 $bracketWrap = function ($tag) {
117 return '[' . $tag . ']';
118 };
119 $data['pagetitle'] .= ! empty($searchTags)
120 ? implode(' ', array_map($bracketWrap, preg_split('/\s+/', $searchTags))) . ' '
121 : '';
122 $data['pagetitle'] .= '- ';
123 }
124
125 $data['pagetitle'] = ($data['pagetitle'] ?? '') . $this->container->conf->get('general.title', 'Shaarli');
126
127 $this->executeHooks($data);
128 $this->assignAllView($data);
129
130 return $response->write($this->render(TemplatePage::LINKLIST));
131 }
132
133 /**
134 * GET /shaare/{hash} - Display a single shaare
135 */
136 public function permalink(Request $request, Response $response, array $args): Response
137 {
138 try {
139 $bookmark = $this->container->bookmarkService->findByHash($args['hash']);
140 } catch (BookmarkNotFoundException $e) {
141 $this->assignView('error_message', $e->getMessage());
142
143 return $response->write($this->render(TemplatePage::ERROR_404));
144 }
145
146 $this->updateThumbnail($bookmark);
147
148 $data = array_merge(
149 $this->initializeTemplateVars(),
150 [
151 'pagetitle' => $bookmark->getTitle() .' - '. $this->container->conf->get('general.title', 'Shaarli'),
152 'links' => [$this->container->formatterFactory->getFormatter()->format($bookmark)],
153 ]
154 );
155
156 $this->executeHooks($data);
157 $this->assignAllView($data);
158
159 return $response->write($this->render(TemplatePage::LINKLIST));
160 }
161
162 /**
163 * Update the thumbnail of a single bookmark if necessary.
164 */
165 protected function updateThumbnail(Bookmark $bookmark, bool $writeDatastore = true): bool
166 {
167 // Logged in, thumbnails enabled, not a note, is HTTP
168 // and (never retrieved yet or no valid cache file)
169 if ($this->container->loginManager->isLoggedIn()
170 && $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE
171 && false !== $bookmark->getThumbnail()
172 && !$bookmark->isNote()
173 && (null === $bookmark->getThumbnail() || !is_file($bookmark->getThumbnail()))
174 && startsWith(strtolower($bookmark->getUrl()), 'http')
175 ) {
176 $bookmark->setThumbnail($this->container->thumbnailer->get($bookmark->getUrl()));
177 $this->container->bookmarkService->set($bookmark, $writeDatastore);
178
179 return true;
180 }
181
182 return false;
183 }
184
185 /**
186 * @param mixed[] $data Template vars to process in plugins, passed as reference.
187 */
188 protected function executeHooks(array &$data): void
189 {
190 $this->container->pluginManager->executeHooks(
191 'render_linklist',
192 $data,
193 ['loggedin' => $this->container->loginManager->isLoggedIn()]
194 );
195 }
196
197 /**
198 * @return string[] Default template variables without values.
199 */
200 protected function initializeTemplateVars(): array
201 {
202 return [
203 'previous_page_url' => '',
204 'next_page_url' => '',
205 'page_max' => '',
206 'search_tags' => '',
207 'result_count' => '',
208 ];
209 }
210
211 /**
212 * Process legacy routes if necessary. They used query parameters.
213 * If no legacy routes is passed, return null.
214 */
215 protected function processLegacyController(Request $request, Response $response): ?Response
216 {
217 // Legacy smallhash filter
218 $queryString = $this->container->environment['QUERY_STRING'] ?? null;
219 if (null !== $queryString && 1 === preg_match('/^([a-zA-Z0-9-_@]{6})($|&|#)/', $queryString, $match)) {
220 return $this->redirect($response, '/shaare/' . $match[1]);
221 }
222
223 // Legacy controllers (mostly used for redirections)
224 if (null !== $request->getQueryParam('do')) {
225 $legacyController = new LegacyController($this->container);
226
227 try {
228 return $legacyController->process($request, $response, $request->getQueryParam('do'));
229 } catch (UnknowLegacyRouteException $e) {
230 // We ignore legacy 404
231 return null;
232 }
233 }
234
235 // Legacy GET admin routes
236 $legacyGetRoutes = array_intersect(
237 LegacyController::LEGACY_GET_ROUTES,
238 array_keys($request->getQueryParams() ?? [])
239 );
240 if (1 === count($legacyGetRoutes)) {
241 $legacyController = new LegacyController($this->container);
242
243 return $legacyController->process($request, $response, $legacyGetRoutes[0]);
244 }
245
246 return null;
247 }
248}
diff --git a/application/front/controller/visitor/DailyController.php b/application/front/controller/visitor/DailyController.php
index e5c9ddac..05b4f095 100644
--- a/application/front/controller/visitor/DailyController.php
+++ b/application/front/controller/visitor/DailyController.php
@@ -7,6 +7,7 @@ namespace Shaarli\Front\Controller\Visitor;
7use DateTime; 7use DateTime;
8use DateTimeImmutable; 8use DateTimeImmutable;
9use Shaarli\Bookmark\Bookmark; 9use Shaarli\Bookmark\Bookmark;
10use Shaarli\Render\TemplatePage;
10use Slim\Http\Request; 11use Slim\Http\Request;
11use Slim\Http\Response; 12use Slim\Http\Response;
12 13
@@ -85,7 +86,7 @@ class DailyController extends ShaarliVisitorController
85 t('Daily') .' - '. format_date($dayDate, false) . ' - ' . $mainTitle 86 t('Daily') .' - '. format_date($dayDate, false) . ' - ' . $mainTitle
86 ); 87 );
87 88
88 return $response->write($this->render('daily')); 89 return $response->write($this->render(TemplatePage::DAILY));
89 } 90 }
90 91
91 /** 92 /**
@@ -152,7 +153,7 @@ class DailyController extends ShaarliVisitorController
152 $this->assignView('hide_timestamps', $this->container->conf->get('privacy.hide_timestamps', false)); 153 $this->assignView('hide_timestamps', $this->container->conf->get('privacy.hide_timestamps', false));
153 $this->assignView('days', $dataPerDay); 154 $this->assignView('days', $dataPerDay);
154 155
155 $rssContent = $this->render('dailyrss'); 156 $rssContent = $this->render(TemplatePage::DAILY_RSS);
156 157
157 $cache->cache($rssContent); 158 $cache->cache($rssContent);
158 159
diff --git a/application/front/controller/visitor/LoginController.php b/application/front/controller/visitor/LoginController.php
index 0db1f463..a257766f 100644
--- a/application/front/controller/visitor/LoginController.php
+++ b/application/front/controller/visitor/LoginController.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Visitor; 5namespace Shaarli\Front\Controller\Visitor;
6 6
7use Shaarli\Front\Exception\LoginBannedException; 7use Shaarli\Front\Exception\LoginBannedException;
8use Shaarli\Render\TemplatePage;
8use Slim\Http\Request; 9use Slim\Http\Request;
9use Slim\Http\Response; 10use Slim\Http\Response;
10 11
@@ -41,6 +42,6 @@ class LoginController extends ShaarliVisitorController
41 ->assignView('pagetitle', t('Login') .' - '. $this->container->conf->get('general.title', 'Shaarli')) 42 ->assignView('pagetitle', t('Login') .' - '. $this->container->conf->get('general.title', 'Shaarli'))
42 ; 43 ;
43 44
44 return $response->write($this->render('loginform')); 45 return $response->write($this->render(TemplatePage::LOGIN));
45 } 46 }
46} 47}
diff --git a/application/front/controller/visitor/OpenSearchController.php b/application/front/controller/visitor/OpenSearchController.php
index 0fd68db6..36d60acf 100644
--- a/application/front/controller/visitor/OpenSearchController.php
+++ b/application/front/controller/visitor/OpenSearchController.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
4 4
5namespace Shaarli\Front\Controller\Visitor; 5namespace Shaarli\Front\Controller\Visitor;
6 6
7use Shaarli\Render\TemplatePage;
7use Slim\Http\Request; 8use Slim\Http\Request;
8use Slim\Http\Response; 9use Slim\Http\Response;
9 10
@@ -21,6 +22,6 @@ class OpenSearchController extends ShaarliVisitorController
21 22
22 $this->assignView('serverurl', index_url($this->container->environment)); 23 $this->assignView('serverurl', index_url($this->container->environment));
23 24
24 return $response->write($this->render('opensearch')); 25 return $response->write($this->render(TemplatePage::OPEN_SEARCH));
25 } 26 }
26} 27}
diff --git a/application/front/controller/visitor/PictureWallController.php b/application/front/controller/visitor/PictureWallController.php
index 4e1dce8c..5ef2cb17 100644
--- a/application/front/controller/visitor/PictureWallController.php
+++ b/application/front/controller/visitor/PictureWallController.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Visitor; 5namespace Shaarli\Front\Controller\Visitor;
6 6
7use Shaarli\Front\Exception\ThumbnailsDisabledException; 7use Shaarli\Front\Exception\ThumbnailsDisabledException;
8use Shaarli\Render\TemplatePage;
8use Shaarli\Thumbnailer; 9use Shaarli\Thumbnailer;
9use Slim\Http\Request; 10use Slim\Http\Request;
10use Slim\Http\Response; 11use Slim\Http\Response;
@@ -46,7 +47,7 @@ class PictureWallController extends ShaarliVisitorController
46 $this->assignView($key, $value); 47 $this->assignView($key, $value);
47 } 48 }
48 49
49 return $response->write($this->render('picwall')); 50 return $response->write($this->render(TemplatePage::PICTURE_WALL));
50 } 51 }
51 52
52 /** 53 /**