3 declare(strict_types
=1);
5 namespace Shaarli\Front\Controller\Admin
;
7 use Shaarli\Bookmark\BookmarkFilter
;
8 use Shaarli\Render\TemplatePage
;
10 use Slim\Http\Response
;
13 * Class ManageTagController
15 * Slim controller used to handle Shaarli manage tags page (rename and delete tags).
17 class ManageTagController
extends ShaarliAdminController
20 * GET /admin/tags - Displays the manage tags page
22 public function index(Request
$request, Response
$response): Response
24 $fromTag = $request->getParam('fromtag') ?? '';
26 $this->assignView('fromtag', escape($fromTag));
27 $separator = escape($this->container
->conf
->get('general.tags_separator', ' '));
28 if ($separator === ' ') {
29 $separator = ' ';
30 $this->assignView('tags_separator_desc', t('whitespace'));
32 $this->assignView('tags_separator', $separator);
35 t('Manage tags') . ' - ' . $this->container
->conf
->get('general.title', 'Shaarli')
38 return $response->write($this->render(TemplatePage
::CHANGE_TAG
));
42 * POST /admin/tags - Update or delete provided tag
44 public function save(Request
$request, Response
$response): Response
46 $this->checkToken($request);
48 $isDelete = null !== $request->getParam('deletetag') && null === $request->getParam('renametag');
50 $fromTag = trim($request->getParam('fromtag') ?? '');
51 $toTag = trim($request->getParam('totag') ?? '');
53 if (0 === strlen($fromTag) || false === $isDelete && 0 === strlen($toTag)) {
54 $this->saveWarningMessage(t('Invalid tags provided.'));
56 return $this->redirect($response, '/admin/tags');
59 // TODO: move this to bookmark service
61 $bookmarks = $this->container
->bookmarkService
->search(['searchtags' => $fromTag], BookmarkFilter
::$ALL, true);
62 foreach ($bookmarks as $bookmark) {
63 if (false === $isDelete) {
64 $bookmark->renameTag($fromTag, $toTag);
66 $bookmark->deleteTag($fromTag);
69 $this->container
->bookmarkService
->set($bookmark, false);
70 $this->container
->history
->updateLink($bookmark);
74 $this->container
->bookmarkService
->save();
76 if (true === $isDelete) {
78 t('The tag was removed from %d bookmark.', 'The tag was removed from %d bookmarks.', $count),
83 t('The tag was renamed in %d bookmark.', 'The tag was renamed in %d bookmarks.', $count),
88 $this->saveSuccessMessage($alert);
90 $redirect = true === $isDelete ? '/admin/tags' : '/?searchtags=' . urlencode($toTag);
92 return $this->redirect($response, $redirect);
96 * POST /admin/tags/change-separator - Change tag separator
98 public function changeSeparator(Request
$request, Response
$response): Response
100 $this->checkToken($request);
102 $reservedCharacters = ['-', '.', '*'];
103 $newSeparator = $request->getParam('separator');
104 if ($newSeparator === null || mb_strlen($newSeparator) !== 1) {
105 $this->saveErrorMessage(t('Tags separator must be a single character.'));
106 } elseif (in_array($newSeparator, $reservedCharacters, true)) {
107 $reservedCharacters = implode(' ', array_map(function (string $character) {
108 return '<code>' . $character . '</code>';
109 }, $reservedCharacters));
110 $this->saveErrorMessage(
111 t('These characters are reserved and can\'t be used as tags separator: ') . $reservedCharacters
114 $this->container
->conf
->set('general.tags_separator', $newSeparator, true, true);
116 $this->saveSuccessMessage('Your tags separator setting has been updated!');
119 return $this->redirect($response, '/admin/tags');