From 1a8ac737e52cb25a5c346232ee398f5908cee7d7 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Mon, 6 Jul 2020 08:04:35 +0200 Subject: Process main page (linklist) through Slim controller Including a bunch of improvements on the container, and helper used across new controllers. --- .../front/controller/admin/ConfigureController.php | 3 +- .../front/controller/admin/ExportController.php | 5 +- .../front/controller/admin/ImportController.php | 3 +- .../controller/admin/ManageShaareController.php | 5 +- .../front/controller/admin/ManageTagController.php | 3 +- .../front/controller/admin/PasswordController.php | 9 +- .../front/controller/admin/PluginsController.php | 3 +- .../controller/admin/ThumbnailsController.php | 18 +- .../front/controller/admin/ToolsController.php | 3 +- .../controller/visitor/BookmarkListController.php | 248 +++++++++++++++++++++ .../front/controller/visitor/DailyController.php | 5 +- .../front/controller/visitor/LoginController.php | 3 +- .../controller/visitor/OpenSearchController.php | 3 +- .../controller/visitor/PictureWallController.php | 3 +- 14 files changed, 280 insertions(+), 34 deletions(-) create mode 100644 application/front/controller/visitor/BookmarkListController.php (limited to 'application/front/controller') 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); namespace Shaarli\Front\Controller\Admin; use Shaarli\Languages; +use Shaarli\Render\TemplatePage; use Shaarli\Render\ThemeUtils; use Shaarli\Thumbnailer; use Slim\Http\Request; @@ -52,7 +53,7 @@ class ConfigureController extends ShaarliAdminController $this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)); $this->assignView('pagetitle', t('Configure') .' - '. $this->container->conf->get('general.title', 'Shaarli')); - return $response->write($this->render('configure')); + return $response->write($this->render(TemplatePage::CONFIGURE)); } /** 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; use DateTime; use Shaarli\Bookmark\Bookmark; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -24,7 +25,7 @@ class ExportController extends ShaarliAdminController { $this->assignView('pagetitle', t('Export') .' - '. $this->container->conf->get('general.title', 'Shaarli')); - return $response->write($this->render('export')); + return $response->write($this->render(TemplatePage::EXPORT)); } /** @@ -74,6 +75,6 @@ class ExportController extends ShaarliAdminController $this->assignView('eol', PHP_EOL); $this->assignView('selection', $selection); - return $response->write($this->render('export.bookmarks')); + return $response->write($this->render(TemplatePage::NETSCAPE_EXPORT_BOOKMARKS)); } } 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); namespace Shaarli\Front\Controller\Admin; use Psr\Http\Message\UploadedFileInterface; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -39,7 +40,7 @@ class ImportController extends ShaarliAdminController ); $this->assignView('pagetitle', t('Import') .' - '. $this->container->conf->get('general.title', 'Shaarli')); - return $response->write($this->render('import')); + return $response->write($this->render(TemplatePage::IMPORT)); } /** 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; use Shaarli\Bookmark\Bookmark; use Shaarli\Bookmark\Exception\BookmarkNotFoundException; use Shaarli\Formatter\BookmarkMarkdownFormatter; +use Shaarli\Render\TemplatePage; use Shaarli\Thumbnailer; use Slim\Http\Request; use Slim\Http\Response; @@ -28,7 +29,7 @@ class ManageShaareController extends ShaarliAdminController t('Shaare a new link') .' - '. $this->container->conf->get('general.title', 'Shaarli') ); - return $response->write($this->render('addlink')); + return $response->write($this->render(TemplatePage::ADDLINK)); } /** @@ -365,7 +366,7 @@ class ManageShaareController extends ShaarliAdminController $editLabel . t('Shaare') .' - '. $this->container->conf->get('general.title', 'Shaarli') ); - return $response->write($this->render('editlink')); + return $response->write($this->render(TemplatePage::EDIT_LINK)); } /** 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); namespace Shaarli\Front\Controller\Admin; use Shaarli\Bookmark\BookmarkFilter; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -28,7 +29,7 @@ class ManageTagController extends ShaarliAdminController t('Manage tags') .' - '. $this->container->conf->get('general.title', 'Shaarli') ); - return $response->write($this->render('changetag')); + return $response->write($this->render(TemplatePage::CHANGE_TAG)); } /** 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; use Shaarli\Container\ShaarliContainer; use Shaarli\Front\Exception\OpenShaarliPasswordException; use Shaarli\Front\Exception\ShaarliFrontException; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; use Throwable; @@ -33,7 +34,7 @@ class PasswordController extends ShaarliAdminController */ public function index(Request $request, Response $response): Response { - return $response->write($this->render('changepassword')); + return $response->write($this->render(TemplatePage::CHANGE_PASSWORD)); } /** @@ -55,7 +56,7 @@ class PasswordController extends ShaarliAdminController return $response ->withStatus(400) - ->write($this->render('changepassword')) + ->write($this->render(TemplatePage::CHANGE_PASSWORD)) ; } @@ -71,7 +72,7 @@ class PasswordController extends ShaarliAdminController return $response ->withStatus(400) - ->write($this->render('changepassword')) + ->write($this->render(TemplatePage::CHANGE_PASSWORD)) ; } @@ -95,6 +96,6 @@ class PasswordController extends ShaarliAdminController $this->saveSuccessMessage(t('Your password has been changed')); - return $response->write($this->render('changepassword')); + return $response->write($this->render(TemplatePage::CHANGE_PASSWORD)); } } 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); namespace Shaarli\Front\Controller\Admin; use Exception; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -44,7 +45,7 @@ class PluginsController extends ShaarliAdminController t('Plugin Administration') .' - '. $this->container->conf->get('general.title', 'Shaarli') ); - return $response->write($this->render('pluginsadmin')); + return $response->write($this->render(TemplatePage::PLUGINS_ADMIN)); } /** 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); namespace Shaarli\Front\Controller\Admin; use Shaarli\Bookmark\Exception\BookmarkNotFoundException; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -36,7 +37,7 @@ class ThumbnailsController extends ShaarliAdminController t('Thumbnails update') .' - '. $this->container->conf->get('general.title', 'Shaarli') ); - return $response->write($this->render('thumbnails')); + return $response->write($this->render(TemplatePage::THUMBNAILS)); } /** @@ -61,19 +62,4 @@ class ThumbnailsController extends ShaarliAdminController return $response->withJson($this->container->formatterFactory->getFormatter('raw')->format($bookmark)); } - - /** - * @param mixed[] $data Variables passed to the template engine - * - * @return mixed[] Template data after active plugins render_picwall hook execution. - */ - protected function executeHooks(array $data): array - { - $this->container->pluginManager->executeHooks( - 'render_tools', - $data - ); - - return $data; - } } 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); namespace Shaarli\Front\Controller\Admin; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -29,7 +30,7 @@ class ToolsController extends ShaarliAdminController $this->assignView('pagetitle', t('Tools') .' - '. $this->container->conf->get('general.title', 'Shaarli')); - return $response->write($this->render('tools')); + return $response->write($this->render(TemplatePage::TOOLS)); } /** 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 @@ +processLegacyController($request, $response); + if (null !== $legacyResponse) { + return $legacyResponse; + } + + $formatter = $this->container->formatterFactory->getFormatter(); + + $searchTags = escape(normalize_spaces($request->getParam('searchtags') ?? '')); + $searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? ''));; + + // Filter bookmarks according search parameters. + $visibility = $this->container->sessionManager->getSessionParameter('visibility'); + $search = [ + 'searchtags' => $searchTags, + 'searchterm' => $searchTerm, + ]; + $linksToDisplay = $this->container->bookmarkService->search( + $search, + $visibility, + false, + !!$this->container->sessionManager->getSessionParameter('untaggedonly') + ) ?? []; + + // ---- Handle paging. + $keys = []; + foreach ($linksToDisplay as $key => $value) { + $keys[] = $key; + } + + $linksPerPage = $this->container->sessionManager->getSessionParameter('LINKS_PER_PAGE', 20) ?: 20; + + // Select articles according to paging. + $pageCount = (int) ceil(count($keys) / $linksPerPage) ?: 1; + $page = (int) $request->getParam('page') ?? 1; + $page = $page < 1 ? 1 : $page; + $page = $page > $pageCount ? $pageCount : $page; + + // Start index. + $i = ($page - 1) * $linksPerPage; + $end = $i + $linksPerPage; + + $linkDisp = []; + $save = false; + while ($i < $end && $i < count($keys)) { + $save = $this->updateThumbnail($linksToDisplay[$keys[$i]], false) || $save; + $link = $formatter->format($linksToDisplay[$keys[$i]]); + + $linkDisp[$keys[$i]] = $link; + $i++; + } + + if ($save) { + $this->container->bookmarkService->save(); + } + + // Compute paging navigation + $searchtagsUrl = $searchTags === '' ? '' : '&searchtags=' . urlencode($searchTags); + $searchtermUrl = $searchTerm === '' ? '' : '&searchterm=' . urlencode($searchTerm); + + $previous_page_url = ''; + if ($i !== count($keys)) { + $previous_page_url = '?page=' . ($page + 1) . $searchtermUrl . $searchtagsUrl; + } + $next_page_url = ''; + if ($page > 1) { + $next_page_url = '?page=' . ($page - 1) . $searchtermUrl . $searchtagsUrl; + } + + // Fill all template fields. + $data = array_merge( + $this->initializeTemplateVars(), + [ + 'previous_page_url' => $previous_page_url, + 'next_page_url' => $next_page_url, + 'page_current' => $page, + 'page_max' => $pageCount, + 'result_count' => count($linksToDisplay), + 'search_term' => $searchTerm, + 'search_tags' => $searchTags, + 'visibility' => $visibility, + 'links' => $linkDisp, + ] + ); + + if (!empty($searchTerm) || !empty($searchTags)) { + $data['pagetitle'] = t('Search: '); + $data['pagetitle'] .= ! empty($searchTerm) ? $searchTerm . ' ' : ''; + $bracketWrap = function ($tag) { + return '[' . $tag . ']'; + }; + $data['pagetitle'] .= ! empty($searchTags) + ? implode(' ', array_map($bracketWrap, preg_split('/\s+/', $searchTags))) . ' ' + : ''; + $data['pagetitle'] .= '- '; + } + + $data['pagetitle'] = ($data['pagetitle'] ?? '') . $this->container->conf->get('general.title', 'Shaarli'); + + $this->executeHooks($data); + $this->assignAllView($data); + + return $response->write($this->render(TemplatePage::LINKLIST)); + } + + /** + * GET /shaare/{hash} - Display a single shaare + */ + public function permalink(Request $request, Response $response, array $args): Response + { + try { + $bookmark = $this->container->bookmarkService->findByHash($args['hash']); + } catch (BookmarkNotFoundException $e) { + $this->assignView('error_message', $e->getMessage()); + + return $response->write($this->render(TemplatePage::ERROR_404)); + } + + $this->updateThumbnail($bookmark); + + $data = array_merge( + $this->initializeTemplateVars(), + [ + 'pagetitle' => $bookmark->getTitle() .' - '. $this->container->conf->get('general.title', 'Shaarli'), + 'links' => [$this->container->formatterFactory->getFormatter()->format($bookmark)], + ] + ); + + $this->executeHooks($data); + $this->assignAllView($data); + + return $response->write($this->render(TemplatePage::LINKLIST)); + } + + /** + * Update the thumbnail of a single bookmark if necessary. + */ + protected function updateThumbnail(Bookmark $bookmark, bool $writeDatastore = true): bool + { + // Logged in, thumbnails enabled, not a note, is HTTP + // and (never retrieved yet or no valid cache file) + if ($this->container->loginManager->isLoggedIn() + && $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE + && false !== $bookmark->getThumbnail() + && !$bookmark->isNote() + && (null === $bookmark->getThumbnail() || !is_file($bookmark->getThumbnail())) + && startsWith(strtolower($bookmark->getUrl()), 'http') + ) { + $bookmark->setThumbnail($this->container->thumbnailer->get($bookmark->getUrl())); + $this->container->bookmarkService->set($bookmark, $writeDatastore); + + return true; + } + + return false; + } + + /** + * @param mixed[] $data Template vars to process in plugins, passed as reference. + */ + protected function executeHooks(array &$data): void + { + $this->container->pluginManager->executeHooks( + 'render_linklist', + $data, + ['loggedin' => $this->container->loginManager->isLoggedIn()] + ); + } + + /** + * @return string[] Default template variables without values. + */ + protected function initializeTemplateVars(): array + { + return [ + 'previous_page_url' => '', + 'next_page_url' => '', + 'page_max' => '', + 'search_tags' => '', + 'result_count' => '', + ]; + } + + /** + * Process legacy routes if necessary. They used query parameters. + * If no legacy routes is passed, return null. + */ + protected function processLegacyController(Request $request, Response $response): ?Response + { + // Legacy smallhash filter + $queryString = $this->container->environment['QUERY_STRING'] ?? null; + if (null !== $queryString && 1 === preg_match('/^([a-zA-Z0-9-_@]{6})($|&|#)/', $queryString, $match)) { + return $this->redirect($response, '/shaare/' . $match[1]); + } + + // Legacy controllers (mostly used for redirections) + if (null !== $request->getQueryParam('do')) { + $legacyController = new LegacyController($this->container); + + try { + return $legacyController->process($request, $response, $request->getQueryParam('do')); + } catch (UnknowLegacyRouteException $e) { + // We ignore legacy 404 + return null; + } + } + + // Legacy GET admin routes + $legacyGetRoutes = array_intersect( + LegacyController::LEGACY_GET_ROUTES, + array_keys($request->getQueryParams() ?? []) + ); + if (1 === count($legacyGetRoutes)) { + $legacyController = new LegacyController($this->container); + + return $legacyController->process($request, $response, $legacyGetRoutes[0]); + } + + return null; + } +} 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; use DateTime; use DateTimeImmutable; use Shaarli\Bookmark\Bookmark; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -85,7 +86,7 @@ class DailyController extends ShaarliVisitorController t('Daily') .' - '. format_date($dayDate, false) . ' - ' . $mainTitle ); - return $response->write($this->render('daily')); + return $response->write($this->render(TemplatePage::DAILY)); } /** @@ -152,7 +153,7 @@ class DailyController extends ShaarliVisitorController $this->assignView('hide_timestamps', $this->container->conf->get('privacy.hide_timestamps', false)); $this->assignView('days', $dataPerDay); - $rssContent = $this->render('dailyrss'); + $rssContent = $this->render(TemplatePage::DAILY_RSS); $cache->cache($rssContent); 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); namespace Shaarli\Front\Controller\Visitor; use Shaarli\Front\Exception\LoginBannedException; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -41,6 +42,6 @@ class LoginController extends ShaarliVisitorController ->assignView('pagetitle', t('Login') .' - '. $this->container->conf->get('general.title', 'Shaarli')) ; - return $response->write($this->render('loginform')); + return $response->write($this->render(TemplatePage::LOGIN)); } } 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); namespace Shaarli\Front\Controller\Visitor; +use Shaarli\Render\TemplatePage; use Slim\Http\Request; use Slim\Http\Response; @@ -21,6 +22,6 @@ class OpenSearchController extends ShaarliVisitorController $this->assignView('serverurl', index_url($this->container->environment)); - return $response->write($this->render('opensearch')); + return $response->write($this->render(TemplatePage::OPEN_SEARCH)); } } 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); namespace Shaarli\Front\Controller\Visitor; use Shaarli\Front\Exception\ThumbnailsDisabledException; +use Shaarli\Render\TemplatePage; use Shaarli\Thumbnailer; use Slim\Http\Request; use Slim\Http\Response; @@ -46,7 +47,7 @@ class PictureWallController extends ShaarliVisitorController $this->assignView($key, $value); } - return $response->write($this->render('picwall')); + return $response->write($this->render(TemplatePage::PICTURE_WALL)); } /** -- cgit v1.2.3