From b3bd8c3e8d367975980043e772f7cd78b7f96bc6 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Thu, 22 Oct 2020 16:21:03 +0200 Subject: Feature: support any tag separator So it allows to have multiple words tags. Breaking change: commas ',' are no longer a default separator. Fixes #594 --- .../front/controller/admin/ManageTagController.php | 33 ++++++++++++++++++++++ .../controller/admin/ShaareManageController.php | 4 +-- .../controller/admin/ShaarePublishController.php | 12 ++++++-- .../controller/visitor/BookmarkListController.php | 11 ++++++-- .../controller/visitor/TagCloudController.php | 10 ++++--- .../front/controller/visitor/TagController.php | 10 ++++--- 6 files changed, 65 insertions(+), 15 deletions(-) (limited to 'application/front') diff --git a/application/front/controller/admin/ManageTagController.php b/application/front/controller/admin/ManageTagController.php index 2065c3e2..22fb461c 100644 --- a/application/front/controller/admin/ManageTagController.php +++ b/application/front/controller/admin/ManageTagController.php @@ -24,6 +24,12 @@ class ManageTagController extends ShaarliAdminController $fromTag = $request->getParam('fromtag') ?? ''; $this->assignView('fromtag', escape($fromTag)); + $separator = escape($this->container->conf->get('general.tags_separator', ' ')); + if ($separator === ' ') { + $separator = ' '; + $this->assignView('tags_separator_desc', t('whitespace')); + } + $this->assignView('tags_separator', $separator); $this->assignView( 'pagetitle', t('Manage tags') .' - '. $this->container->conf->get('general.title', 'Shaarli') @@ -85,4 +91,31 @@ class ManageTagController extends ShaarliAdminController return $this->redirect($response, $redirect); } + + /** + * POST /admin/tags/change-separator - Change tag separator + */ + public function changeSeparator(Request $request, Response $response): Response + { + $this->checkToken($request); + + $reservedCharacters = ['-', '.', '*']; + $newSeparator = $request->getParam('separator'); + if ($newSeparator === null || mb_strlen($newSeparator) !== 1) { + $this->saveErrorMessage(t('Tags separator must be a single character.')); + } elseif (in_array($newSeparator, $reservedCharacters, true)) { + $reservedCharacters = implode(' ', array_map(function (string $character) { + return '' . $character . ''; + }, $reservedCharacters)); + $this->saveErrorMessage( + t('These characters are reserved and can\'t be used as tags separator: ') . $reservedCharacters + ); + } else { + $this->container->conf->set('general.tags_separator', $newSeparator, true, true); + + $this->saveSuccessMessage('Your tags separator setting has been updated!'); + } + + return $this->redirect($response, '/admin/tags'); + } } diff --git a/application/front/controller/admin/ShaareManageController.php b/application/front/controller/admin/ShaareManageController.php index 2ed298f5..0b143172 100644 --- a/application/front/controller/admin/ShaareManageController.php +++ b/application/front/controller/admin/ShaareManageController.php @@ -125,7 +125,7 @@ class ShaareManageController extends ShaarliAdminController // To preserve backward compatibility with 3rd parties, plugins still use arrays $data = $formatter->format($bookmark); $this->executePageHooks('save_link', $data); - $bookmark->fromArray($data); + $bookmark->fromArray($data, $this->container->conf->get('general.tags_separator', ' ')); $this->container->bookmarkService->set($bookmark, false); ++$count; @@ -167,7 +167,7 @@ class ShaareManageController extends ShaarliAdminController // To preserve backward compatibility with 3rd parties, plugins still use arrays $data = $formatter->format($bookmark); $this->executePageHooks('save_link', $data); - $bookmark->fromArray($data); + $bookmark->fromArray($data, $this->container->conf->get('general.tags_separator', ' ')); $this->container->bookmarkService->set($bookmark); diff --git a/application/front/controller/admin/ShaarePublishController.php b/application/front/controller/admin/ShaarePublishController.php index 18afc2d1..625a5680 100644 --- a/application/front/controller/admin/ShaarePublishController.php +++ b/application/front/controller/admin/ShaarePublishController.php @@ -113,7 +113,10 @@ class ShaarePublishController extends ShaarliAdminController $bookmark->setDescription($request->getParam('lf_description')); $bookmark->setUrl($request->getParam('lf_url'), $this->container->conf->get('security.allowed_protocols', [])); $bookmark->setPrivate(filter_var($request->getParam('lf_private'), FILTER_VALIDATE_BOOLEAN)); - $bookmark->setTagsString($request->getParam('lf_tags')); + $bookmark->setTagsString( + $request->getParam('lf_tags'), + $this->container->conf->get('general.tags_separator', ' ') + ); if ($this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE) !== Thumbnailer::MODE_NONE && true !== $this->container->conf->get('general.enable_async_metadata', true) @@ -128,7 +131,7 @@ class ShaarePublishController extends ShaarliAdminController $data = $formatter->format($bookmark); $this->executePageHooks('save_link', $data); - $bookmark->fromArray($data); + $bookmark->fromArray($data, $this->container->conf->get('general.tags_separator', ' ')); $this->container->bookmarkService->set($bookmark); // If we are called from the bookmarklet, we must close the popup: @@ -221,6 +224,11 @@ class ShaarePublishController extends ShaarliAdminController protected function buildFormData(array $link, bool $isNew, Request $request): array { + $link['tags'] = strlen($link['tags']) > 0 + ? $link['tags'] . $this->container->conf->get('general.tags_separator', ' ') + : $link['tags'] + ; + return escape([ 'link' => $link, 'link_is_new' => $isNew, diff --git a/application/front/controller/visitor/BookmarkListController.php b/application/front/controller/visitor/BookmarkListController.php index 78c474c9..cc3837ce 100644 --- a/application/front/controller/visitor/BookmarkListController.php +++ b/application/front/controller/visitor/BookmarkListController.php @@ -95,6 +95,10 @@ class BookmarkListController extends ShaarliVisitorController $next_page_url = '?page=' . ($page - 1) . $searchtermUrl . $searchtagsUrl; } + $tagsSeparator = $this->container->conf->get('general.tags_separator', ' '); + $searchTagsUrlEncoded = array_map('urlencode', tags_str2array($searchTags, $tagsSeparator)); + $searchTags = !empty($searchTags) ? trim($searchTags, $tagsSeparator) . $tagsSeparator : ''; + // Fill all template fields. $data = array_merge( $this->initializeTemplateVars(), @@ -106,7 +110,7 @@ class BookmarkListController extends ShaarliVisitorController 'result_count' => count($linksToDisplay), 'search_term' => escape($searchTerm), 'search_tags' => escape($searchTags), - 'search_tags_url' => array_map('urlencode', explode(' ', $searchTags)), + 'search_tags_url' => $searchTagsUrlEncoded, 'visibility' => $visibility, 'links' => $linkDisp, ] @@ -119,8 +123,9 @@ class BookmarkListController extends ShaarliVisitorController return '[' . $tag . ']'; }; $data['pagetitle'] .= ! empty($searchTags) - ? implode(' ', array_map($bracketWrap, preg_split('/\s+/', $searchTags))) . ' ' - : ''; + ? implode(' ', array_map($bracketWrap, tags_str2array($searchTags, $tagsSeparator))) . ' ' + : '' + ; $data['pagetitle'] .= '- '; } diff --git a/application/front/controller/visitor/TagCloudController.php b/application/front/controller/visitor/TagCloudController.php index 76ed7690..560cad08 100644 --- a/application/front/controller/visitor/TagCloudController.php +++ b/application/front/controller/visitor/TagCloudController.php @@ -47,13 +47,14 @@ class TagCloudController extends ShaarliVisitorController */ protected function processRequest(string $type, Request $request, Response $response): Response { + $tagsSeparator = $this->container->conf->get('general.tags_separator', ' '); if ($this->container->loginManager->isLoggedIn() === true) { $visibility = $this->container->sessionManager->getSessionParameter('visibility'); } $sort = $request->getQueryParam('sort'); $searchTags = $request->getQueryParam('searchtags'); - $filteringTags = $searchTags !== null ? explode(' ', $searchTags) : []; + $filteringTags = $searchTags !== null ? explode($tagsSeparator, $searchTags) : []; $tags = $this->container->bookmarkService->bookmarksCountPerTag($filteringTags, $visibility ?? null); @@ -71,8 +72,9 @@ class TagCloudController extends ShaarliVisitorController $tagsUrl[escape($tag)] = urlencode((string) $tag); } - $searchTags = implode(' ', escape($filteringTags)); - $searchTagsUrl = urlencode(implode(' ', $filteringTags)); + $searchTags = tags_array2str($filteringTags, $tagsSeparator); + $searchTags = !empty($searchTags) ? trim($searchTags, $tagsSeparator) . $tagsSeparator : ''; + $searchTagsUrl = urlencode($searchTags); $data = [ 'search_tags' => escape($searchTags), 'search_tags_url' => $searchTagsUrl, @@ -82,7 +84,7 @@ class TagCloudController extends ShaarliVisitorController $this->executePageHooks('render_tag' . $type, $data, 'tag.' . $type); $this->assignAllView($data); - $searchTags = !empty($searchTags) ? $searchTags .' - ' : ''; + $searchTags = !empty($searchTags) ? trim(str_replace($tagsSeparator, ' ', $searchTags)) .' - ' : ''; $this->assignView( 'pagetitle', $searchTags . t('Tag '. $type) .' - '. $this->container->conf->get('general.title', 'Shaarli') diff --git a/application/front/controller/visitor/TagController.php b/application/front/controller/visitor/TagController.php index de4e7ea2..7a3377a7 100644 --- a/application/front/controller/visitor/TagController.php +++ b/application/front/controller/visitor/TagController.php @@ -45,9 +45,10 @@ class TagController extends ShaarliVisitorController unset($params['addtag']); } + $tagsSeparator = $this->container->conf->get('general.tags_separator', ' '); // Check if this tag is already in the search query and ignore it if it is. // Each tag is always separated by a space - $currentTags = isset($params['searchtags']) ? explode(' ', $params['searchtags']) : []; + $currentTags = tags_str2array($params['searchtags'] ?? '', $tagsSeparator); $addtag = true; foreach ($currentTags as $value) { @@ -62,7 +63,7 @@ class TagController extends ShaarliVisitorController $currentTags[] = trim($newTag); } - $params['searchtags'] = trim(implode(' ', $currentTags)); + $params['searchtags'] = tags_array2str($currentTags, $tagsSeparator); // We also remove page (keeping the same page has no sense, since the results are different) unset($params['page']); @@ -98,10 +99,11 @@ class TagController extends ShaarliVisitorController } if (isset($params['searchtags'])) { - $tags = explode(' ', $params['searchtags']); + $tagsSeparator = $this->container->conf->get('general.tags_separator', ' '); + $tags = tags_str2array($params['searchtags'] ?? '', $tagsSeparator); // Remove value from array $tags. $tags = array_diff($tags, [$tagToRemove]); - $params['searchtags'] = implode(' ', $tags); + $params['searchtags'] = tags_array2str($tags, $tagsSeparator); if (empty($params['searchtags'])) { unset($params['searchtags']); -- cgit v1.2.3