From 03340c18ead651ef9e11f883745695f2edafbae3 Mon Sep 17 00:00:00 2001
From: ArthurHoaro
Date: Tue, 12 May 2020 12:44:48 +0200
Subject: [PATCH] Slim router: handle add tag route
---
application/bookmark/LinkUtils.php | 2 +-
application/container/ShaarliContainer.php | 1 +
.../formatter/BookmarkMarkdownFormatter.php | 4 +-
.../front/controllers/TagController.php | 74 +++++++
composer.lock | 207 +++++++++++-------
index.php | 1 +
tests/bookmark/LinkUtilsTest.php | 4 +-
tests/feed/FeedBuilderTest.php | 2 +-
.../BookmarkDefaultFormatterTest.php | 4 +-
.../BookmarkMarkdownFormatterTest.php | 4 +-
tests/front/controller/TagControllerTest.php | 191 ++++++++++++++++
tests/plugins/resources/hashtags.md | 10 -
tests/plugins/resources/hashtags.raw | 10 -
tests/plugins/resources/markdown.html | 33 ---
tests/plugins/resources/markdown.md | 34 ---
tpl/default/linklist.html | 2 +-
tpl/default/tag.cloud.html | 2 +-
tpl/default/tag.list.html | 2 +-
tpl/vintage/linklist.html | 2 +-
tpl/vintage/tag.cloud.html | 2 +-
20 files changed, 407 insertions(+), 184 deletions(-)
create mode 100644 application/front/controllers/TagController.php
create mode 100644 tests/front/controller/TagControllerTest.php
delete mode 100644 tests/plugins/resources/hashtags.md
delete mode 100644 tests/plugins/resources/hashtags.raw
delete mode 100644 tests/plugins/resources/markdown.html
delete mode 100644 tests/plugins/resources/markdown.md
diff --git a/application/bookmark/LinkUtils.php b/application/bookmark/LinkUtils.php
index 88379430..98d9038a 100644
--- a/application/bookmark/LinkUtils.php
+++ b/application/bookmark/LinkUtils.php
@@ -220,7 +220,7 @@ function hashtag_autolink($description, $indexUrl = '')
* \p{Mn} - any non marking space (accents, umlauts, etc)
*/
$regex = '/(^|\s)#([\p{Pc}\p{N}\p{L}\p{Mn}]+)/mui';
- $replacement = '$1#$2';
+ $replacement = '$1#$2';
return preg_replace($regex, $replacement, $description);
}
diff --git a/application/container/ShaarliContainer.php b/application/container/ShaarliContainer.php
index af62e574..3995f669 100644
--- a/application/container/ShaarliContainer.php
+++ b/application/container/ShaarliContainer.php
@@ -18,6 +18,7 @@ use Slim\Container;
/**
* Extension of Slim container to document the injected objects.
*
+ * @property mixed[] $environment $_SERVER automatically injected by Slim
* @property ConfigManager $conf
* @property SessionManager $sessionManager
* @property LoginManager $loginManager
diff --git a/application/formatter/BookmarkMarkdownFormatter.php b/application/formatter/BookmarkMarkdownFormatter.php
index 077e5312..5d244d4c 100644
--- a/application/formatter/BookmarkMarkdownFormatter.php
+++ b/application/formatter/BookmarkMarkdownFormatter.php
@@ -114,7 +114,7 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter
/**
* Replace hashtag in Markdown links format
- * E.g. `#hashtag` becomes `[#hashtag](?addtag=hashtag)`
+ * E.g. `#hashtag` becomes `[#hashtag](./add-tag/hashtag)`
* It includes the index URL if specified.
*
* @param string $description
@@ -133,7 +133,7 @@ class BookmarkMarkdownFormatter extends BookmarkDefaultFormatter
* \p{Mn} - any non marking space (accents, umlauts, etc)
*/
$regex = '/(^|\s)#([\p{Pc}\p{N}\p{L}\p{Mn}]+)/mui';
- $replacement = '$1[#$2]('. $indexUrl .'?addtag=$2)';
+ $replacement = '$1[#$2]('. $indexUrl .'./add-tag/$2)';
$descriptionLines = explode(PHP_EOL, $description);
$descriptionOut = '';
diff --git a/application/front/controllers/TagController.php b/application/front/controllers/TagController.php
new file mode 100644
index 00000000..598275b0
--- /dev/null
+++ b/application/front/controllers/TagController.php
@@ -0,0 +1,74 @@
+container->environment['HTTP_REFERER'] ?? null;
+
+ // In case browser does not send HTTP_REFERER, we search a single tag
+ if (null === $referer) {
+ if (null !== $newTag) {
+ return $response->withRedirect('./?searchtags='. urlencode($newTag));
+ }
+
+ return $response->withRedirect('./');
+ }
+
+ $currentUrl = parse_url($this->container->environment['HTTP_REFERER']);
+ parse_str($currentUrl['query'] ?? '', $params);
+
+ if (null === $newTag) {
+ return $response->withRedirect(($currentUrl['path'] ?? './') .'?'. http_build_query($params));
+ }
+
+ // Prevent redirection loop
+ if (isset($params['addtag'])) {
+ unset($params['addtag']);
+ }
+
+ // 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']) : [];
+
+ $addtag = true;
+ foreach ($currentTags as $value) {
+ if ($value === $newTag) {
+ $addtag = false;
+ break;
+ }
+ }
+
+ // Append the tag if necessary
+ if (true === $addtag) {
+ $currentTags[] = trim($newTag);
+ }
+
+ $params['searchtags'] = trim(implode(' ', $currentTags));
+
+ // We also remove page (keeping the same page has no sense, since the results are different)
+ unset($params['page']);
+
+ return $response->withRedirect(($currentUrl['path'] ?? './') .'?'. http_build_query($params));
+ }
+}
diff --git a/composer.lock b/composer.lock
index b3373a32..fccc741c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -508,16 +508,16 @@
},
{
"name": "psr/log",
- "version": "1.1.2",
+ "version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
+ "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
- "reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
+ "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc",
"shasum": ""
},
"require": {
@@ -551,7 +551,7 @@
"psr",
"psr-3"
],
- "time": "2019-11-01T11:05:21+00:00"
+ "time": "2020-03-23T09:12:05+00:00"
},
{
"name": "pubsubhubbub/publisher",
@@ -936,24 +936,21 @@
},
{
"name": "phpdocumentor/reflection-common",
- "version": "2.0.0",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
- "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
+ "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
- "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
+ "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
- "require-dev": {
- "phpunit/phpunit": "~6"
- },
"type": "library",
"extra": {
"branch-alias": {
@@ -984,7 +981,7 @@
"reflection",
"static analysis"
],
- "time": "2018-08-07T13:53:10+00:00"
+ "time": "2020-04-27T09:25:28+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
@@ -1087,24 +1084,24 @@
},
{
"name": "phpspec/prophecy",
- "version": "1.10.1",
+ "version": "v1.10.3",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc"
+ "reference": "451c3cd1418cf640de218914901e51b064abb093"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/cbe1df668b3fe136bcc909126a0f529a78d4cbbc",
- "reference": "cbe1df668b3fe136bcc909126a0f529a78d4cbbc",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093",
+ "reference": "451c3cd1418cf640de218914901e51b064abb093",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
- "sebastian/comparator": "^1.2.3|^2.0|^3.0",
- "sebastian/recursion-context": "^1.0|^2.0|^3.0"
+ "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0",
+ "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0"
},
"require-dev": {
"phpspec/phpspec": "^2.5 || ^3.2",
@@ -1146,7 +1143,7 @@
"spy",
"stub"
],
- "time": "2019-12-22T21:05:45+00:00"
+ "time": "2020-03-05T15:02:03+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -1501,12 +1498,12 @@
"source": {
"type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git",
- "reference": "67ac6ea8f4a078c3c9b7aec5d7ae70f098c37389"
+ "reference": "ec1a75b10126327b351fdea7c2b9bfb94e2f6f35"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/67ac6ea8f4a078c3c9b7aec5d7ae70f098c37389",
- "reference": "67ac6ea8f4a078c3c9b7aec5d7ae70f098c37389",
+ "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/ec1a75b10126327b351fdea7c2b9bfb94e2f6f35",
+ "reference": "ec1a75b10126327b351fdea7c2b9bfb94e2f6f35",
"shasum": ""
},
"conflict": {
@@ -1518,11 +1515,17 @@
"api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6",
"asymmetricrypt/asymmetricrypt": ">=0,<9.9.99",
"aws/aws-sdk-php": ">=3,<3.2.1",
+ "bagisto/bagisto": "<0.1.5",
+ "barrelstrength/sprout-base-email": "<3.9",
+ "bolt/bolt": "<3.6.10",
"brightlocal/phpwhois": "<=4.2.5",
+ "buddypress/buddypress": "<5.1.2",
"bugsnag/bugsnag-laravel": ">=2,<2.0.2",
"cakephp/cakephp": ">=1.3,<1.3.18|>=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.5.18|>=3.6,<3.6.15|>=3.7,<3.7.7",
"cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4",
"cartalyst/sentry": "<=2.1.6",
+ "centreon/centreon": "<18.10.8|>=19,<19.4.5",
+ "cesnet/simplesamlphp-module-proxystatistics": "<3.1",
"codeigniter/framework": "<=3.0.6",
"composer/composer": "<=1-alpha.11",
"contao-components/mediaelement": ">=2.14.2,<2.21.1",
@@ -1540,22 +1543,32 @@
"doctrine/mongodb-odm": ">=1,<1.0.2",
"doctrine/mongodb-odm-bundle": ">=2,<3.0.1",
"doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1",
+ "dolibarr/dolibarr": "<=10.0.6",
"dompdf/dompdf": ">=0.6,<0.6.2",
- "drupal/core": ">=7,<7.69|>=8,<8.7.11|>=8.8,<8.8.1",
- "drupal/drupal": ">=7,<7.69|>=8,<8.7.11|>=8.8,<8.8.1",
+ "drupal/core": ">=7,<7.69|>=8,<8.7.12|>=8.8,<8.8.4",
+ "drupal/drupal": ">=7,<7.69|>=8,<8.7.12|>=8.8,<8.8.4",
"endroid/qr-code-bundle": "<3.4.2",
+ "enshrined/svg-sanitize": "<0.13.1",
"erusev/parsedown": "<1.7.2",
- "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.4",
- "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.13.1|>=6,<6.7.9.1|>=6.8,<6.13.5.1|>=7,<7.2.4.1|>=7.3,<7.3.2.1",
- "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.12.3|>=2011,<2017.12.4.3|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3",
+ "ezsystems/demobundle": ">=5.4,<5.4.6.1",
+ "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1",
+ "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1",
+ "ezsystems/ezplatform": ">=1.7,<1.7.9.1|>=1.13,<1.13.5.1|>=2.5,<2.5.4",
+ "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6",
+ "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2",
+ "ezsystems/ezplatform-user": ">=1,<1.0.1",
+ "ezsystems/ezpublish-kernel": ">=5.3,<5.3.12.1|>=5.4,<5.4.14.1|>=6,<6.7.9.1|>=6.8,<6.13.6.2|>=7,<7.2.4.1|>=7.3,<7.3.2.1|>=7.5,<7.5.6.2",
+ "ezsystems/ezpublish-legacy": ">=5.3,<5.3.12.6|>=5.4,<5.4.14.1|>=2011,<2017.12.7.2|>=2018.6,<2018.6.1.4|>=2018.9,<2018.9.1.3|>=2019.3,<2019.3.4.2",
"ezsystems/repository-forms": ">=2.3,<2.3.2.1",
"ezyang/htmlpurifier": "<4.1.1",
"firebase/php-jwt": "<2",
"fooman/tcpdf": "<6.2.22",
"fossar/tcpdf-parser": "<6.2.22",
+ "friendsofsymfony/oauth2-php": "<1.3",
"friendsofsymfony/rest-bundle": ">=1.2,<1.2.2",
"friendsofsymfony/user-bundle": ">=1.2,<1.3.5",
"fuel/core": "<1.8.1",
+ "getgrav/grav": "<1.7-beta.8",
"gree/jose": "<=2.2",
"gregwar/rst": "<1.0.3",
"guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1",
@@ -1563,6 +1576,7 @@
"illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30",
"illuminate/database": ">=4,<4.0.99|>=4.1,<4.1.29",
"illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15",
+ "illuminate/view": ">=7,<7.1.2",
"ivankristianto/phpwhois": "<=4.3",
"james-heinrich/getid3": "<1.9.9",
"joomla/session": "<1.3.1",
@@ -1570,15 +1584,19 @@
"kazist/phpwhois": "<=4.2.6",
"kreait/firebase-php": ">=3.2,<3.8.1",
"la-haute-societe/tcpdf": "<6.2.22",
- "laravel/framework": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30",
+ "laravel/framework": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.42|>=5.6,<5.6.30|>=7,<7.1.2",
"laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
"league/commonmark": "<0.18.3",
+ "librenms/librenms": "<1.53",
+ "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3",
"magento/magento1ce": "<1.9.4.3",
"magento/magento1ee": ">=1,<1.14.4.3",
"magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2",
"monolog/monolog": ">=1.8,<1.12",
"namshi/jose": "<2.2",
+ "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1",
"onelogin/php-saml": "<2.10.4",
+ "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5",
"openid/php-openid": "<2.3",
"oro/crm": ">=1.7,<1.7.4",
"oro/platform": ">=1.7,<1.7.4",
@@ -1587,49 +1605,67 @@
"paragonie/random_compat": "<2",
"paypal/merchant-sdk-php": "<3.12",
"pear/archive_tar": "<1.4.4",
+ "phpfastcache/phpfastcache": ">=5,<5.0.13",
"phpmailer/phpmailer": ">=5,<5.2.27|>=6,<6.0.6",
- "phpoffice/phpexcel": "<=1.8.1",
- "phpoffice/phpspreadsheet": "<=1.5",
+ "phpmyadmin/phpmyadmin": "<4.9.2",
+ "phpoffice/phpexcel": "<1.8.2",
+ "phpoffice/phpspreadsheet": "<1.8",
"phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3",
"phpwhois/phpwhois": "<=4.2.5",
"phpxmlrpc/extras": "<0.6.1",
+ "pimcore/pimcore": "<6.3",
+ "prestashop/autoupgrade": ">=4,<4.10.1",
+ "prestashop/gamification": "<2.3.2",
+ "prestashop/ps_facetedsearch": "<3.4.1",
+ "privatebin/privatebin": "<1.2.2|>=1.3,<1.3.2",
"propel/propel": ">=2-alpha.1,<=2-alpha.7",
"propel/propel1": ">=1,<=1.7.1",
"pusher/pusher-php-server": "<2.2.1",
- "robrichards/xmlseclibs": ">=1,<3.0.4",
+ "robrichards/xmlseclibs": "<3.0.4",
"sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9",
"scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11",
"sensiolabs/connect": "<4.2.3",
"serluck/phpwhois": "<=4.2.6",
"shopware/shopware": "<5.3.7",
- "silverstripe/cms": ">=3,<=3.0.11|>=3.1,<3.1.11",
+ "silverstripe/admin": ">=1.0.3,<1.0.4|>=1.1,<1.1.1",
+ "silverstripe/assets": ">=1,<1.4.7|>=1.5,<1.5.2",
+ "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4",
+ "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1",
"silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3",
- "silverstripe/framework": ">=3,<3.6.7|>=3.7,<3.7.3|>=4,<4.4",
+ "silverstripe/framework": "<4.4.5|>=4.5,<4.5.2",
"silverstripe/graphql": ">=2,<2.0.5|>=3,<3.1.2",
"silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1",
"silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4",
+ "silverstripe/subsites": ">=2,<2.1.1",
+ "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1",
"silverstripe/userforms": "<3",
"simple-updates/phpwhois": "<=1",
"simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4",
- "simplesamlphp/simplesamlphp": "<1.17.8",
+ "simplesamlphp/simplesamlphp": "<1.18.6",
"simplesamlphp/simplesamlphp-module-infocard": "<1.0.1",
+ "simplito/elliptic-php": "<1.0.6",
"slim/slim": "<2.6",
"smarty/smarty": "<3.1.33",
"socalnick/scn-social-auth": "<1.15.2",
"spoonity/tcpdf": "<6.2.22",
"squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1",
+ "ssddanbrown/bookstack": "<0.29.2",
"stormpath/sdk": ">=0,<9.9.99",
- "studio-42/elfinder": "<2.1.48",
+ "studio-42/elfinder": "<2.1.49",
"swiftmailer/swiftmailer": ">=4,<5.4.5",
"sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2",
"sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1",
"sylius/grid-bundle": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1",
- "sylius/sylius": ">=1,<1.1.18|>=1.2,<1.2.17|>=1.3,<1.3.12|>=1.4,<1.4.4",
+ "sylius/resource-bundle": "<1.3.13|>=1.4,<1.4.6|>=1.5,<1.5.1|>=1.6,<1.6.3",
+ "sylius/sylius": "<1.3.16|>=1.4,<1.4.12|>=1.5,<1.5.9|>=1.6,<1.6.5",
+ "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99",
+ "symbiote/silverstripe-versionedfiles": "<=2.0.3",
"symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8",
"symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7",
+ "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4",
"symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1",
"symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7",
- "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8",
+ "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7",
"symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8",
"symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13",
"symfony/mime": ">=4.3,<4.3.8",
@@ -1638,14 +1674,14 @@
"symfony/polyfill-php55": ">=1,<1.10",
"symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7",
"symfony/routing": ">=2,<2.0.19",
- "symfony/security": ">=2,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7",
+ "symfony/security": ">=2,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=4.4,<4.4.7|>=5,<5.0.7",
"symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11",
"symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.37|>=3,<3.3.17|>=3.4,<3.4.7|>=4,<4.0.7",
"symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11",
"symfony/security-guard": ">=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11",
- "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8",
+ "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7",
"symfony/serializer": ">=2,<2.0.11",
- "symfony/symfony": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8",
+ "symfony/symfony": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7",
"symfony/translation": ">=2,<2.0.17",
"symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3",
"symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8",
@@ -1664,8 +1700,11 @@
"typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4",
"typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1",
"ua-parser/uap-php": "<3.8",
+ "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2",
+ "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4",
"wallabag/tcpdf": "<6.2.22",
"willdurand/js-translation-bundle": "<2.1.1",
+ "yii2mod/yii2-cms": "<1.9.2",
"yiisoft/yii": ">=1.1.14,<1.1.15",
"yiisoft/yii2": "<2.0.15",
"yiisoft/yii2-bootstrap": "<2.0.4",
@@ -1674,6 +1713,7 @@
"yiisoft/yii2-gii": "<2.0.4",
"yiisoft/yii2-jui": "<2.0.4",
"yiisoft/yii2-redis": "<2.0.8",
+ "yourls/yourls": "<1.7.4",
"zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3",
"zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2",
"zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2",
@@ -1710,10 +1750,15 @@
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"role": "maintainer"
+ },
+ {
+ "name": "Ilya Tribusean",
+ "email": "slash3b@gmail.com",
+ "role": "maintainer"
}
],
"description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it",
- "time": "2020-01-06T19:16:46+00:00"
+ "time": "2020-05-09T00:00:21+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@@ -2326,16 +2371,16 @@
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.5.3",
+ "version": "3.5.5",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
- "reference": "557a1fc7ac702c66b0bbfe16ab3d55839ef724cb"
+ "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/557a1fc7ac702c66b0bbfe16ab3d55839ef724cb",
- "reference": "557a1fc7ac702c66b0bbfe16ab3d55839ef724cb",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/73e2e7f57d958e7228fce50dc0c61f58f017f9f6",
+ "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6",
"shasum": ""
},
"require": {
@@ -2373,20 +2418,20 @@
"phpcs",
"standards"
],
- "time": "2019-12-04T04:46:47+00:00"
+ "time": "2020-04-17T01:09:41+00:00"
},
{
"name": "symfony/console",
- "version": "v4.4.2",
+ "version": "v4.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "82437719dab1e6bdd28726af14cb345c2ec816d0"
+ "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/82437719dab1e6bdd28726af14cb345c2ec816d0",
- "reference": "82437719dab1e6bdd28726af14cb345c2ec816d0",
+ "url": "https://api.github.com/repos/symfony/console/zipball/10bb3ee3c97308869d53b3e3d03f6ac23ff985f7",
+ "reference": "10bb3ee3c97308869d53b3e3d03f6ac23ff985f7",
"shasum": ""
},
"require": {
@@ -2449,20 +2494,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2019-12-17T10:32:23+00:00"
+ "time": "2020-03-30T11:41:10+00:00"
},
{
"name": "symfony/finder",
- "version": "v4.4.2",
+ "version": "v4.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "ce8743441da64c41e2a667b8eb66070444ed911e"
+ "reference": "5729f943f9854c5781984ed4907bbb817735776b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/ce8743441da64c41e2a667b8eb66070444ed911e",
- "reference": "ce8743441da64c41e2a667b8eb66070444ed911e",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/5729f943f9854c5781984ed4907bbb817735776b",
+ "reference": "5729f943f9854c5781984ed4907bbb817735776b",
"shasum": ""
},
"require": {
@@ -2498,20 +2543,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2019-11-17T21:56:56+00:00"
+ "time": "2020-03-27T16:54:36+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.13.1",
+ "version": "v1.16.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3"
+ "reference": "1aab00e39cebaef4d8652497f46c15c1b7e45294"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
- "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1aab00e39cebaef4d8652497f46c15c1b7e45294",
+ "reference": "1aab00e39cebaef4d8652497f46c15c1b7e45294",
"shasum": ""
},
"require": {
@@ -2523,7 +2568,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.13-dev"
+ "dev-master": "1.16-dev"
}
},
"autoload": {
@@ -2556,20 +2601,20 @@
"polyfill",
"portable"
],
- "time": "2019-11-27T13:56:44+00:00"
+ "time": "2020-05-08T16:50:20+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.13.1",
+ "version": "v1.16.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f"
+ "reference": "a54881ec0ab3b2005c406aed0023c062879031e7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f",
- "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a54881ec0ab3b2005c406aed0023c062879031e7",
+ "reference": "a54881ec0ab3b2005c406aed0023c062879031e7",
"shasum": ""
},
"require": {
@@ -2581,7 +2626,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.13-dev"
+ "dev-master": "1.16-dev"
}
},
"autoload": {
@@ -2615,20 +2660,20 @@
"portable",
"shim"
],
- "time": "2019-11-27T14:18:11+00:00"
+ "time": "2020-05-08T16:50:20+00:00"
},
{
"name": "symfony/polyfill-php73",
- "version": "v1.13.1",
+ "version": "v1.16.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
- "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f"
+ "reference": "7e95fe59d12169fcf4041487e4bf34fca37ee0ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f",
- "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/7e95fe59d12169fcf4041487e4bf34fca37ee0ed",
+ "reference": "7e95fe59d12169fcf4041487e4bf34fca37ee0ed",
"shasum": ""
},
"require": {
@@ -2637,7 +2682,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.13-dev"
+ "dev-master": "1.16-dev"
}
},
"autoload": {
@@ -2673,7 +2718,7 @@
"portable",
"shim"
],
- "time": "2019-11-27T16:25:15+00:00"
+ "time": "2020-05-02T14:56:09+00:00"
},
{
"name": "symfony/service-contracts",
@@ -2815,16 +2860,16 @@
},
{
"name": "webmozart/assert",
- "version": "1.6.0",
+ "version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
- "reference": "573381c0a64f155a0d9a23f4b0c797194805b925"
+ "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925",
- "reference": "573381c0a64f155a0d9a23f4b0c797194805b925",
+ "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
+ "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"shasum": ""
},
"require": {
@@ -2832,7 +2877,7 @@
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
- "vimeo/psalm": "<3.6.0"
+ "vimeo/psalm": "<3.9.1"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13"
@@ -2859,7 +2904,7 @@
"check",
"validate"
],
- "time": "2019-11-24T13:36:37+00:00"
+ "time": "2020-04-18T12:12:48+00:00"
}
],
"aliases": [],
diff --git a/index.php b/index.php
index 57e13d4e..a42c844a 100644
--- a/index.php
+++ b/index.php
@@ -1916,6 +1916,7 @@ $app->group('', function () {
$this->get('/login', '\Shaarli\Front\Controller\LoginController:index')->setName('login');
$this->get('/logout', '\Shaarli\Front\Controller\LogoutController:index')->setName('logout');
$this->get('/picture-wall', '\Shaarli\Front\Controller\PictureWallController:index')->setName('picwall');
+ $this->get('/add-tag/{newTag}', '\Shaarli\Front\Controller\TagController:addTag')->setName('add-tag');
})->add('\Shaarli\Front\ShaarliMiddleware');
$response = $app->run(true);
diff --git a/tests/bookmark/LinkUtilsTest.php b/tests/bookmark/LinkUtilsTest.php
index 591976f2..7d4a7b89 100644
--- a/tests/bookmark/LinkUtilsTest.php
+++ b/tests/bookmark/LinkUtilsTest.php
@@ -3,8 +3,6 @@
namespace Shaarli\Bookmark;
use PHPUnit\Framework\TestCase;
-use ReferenceLinkDB;
-use Shaarli\Config\ConfigManager;
require_once 'tests/utils/CurlUtils.php';
@@ -491,7 +489,7 @@ class LinkUtilsTest extends TestCase
*/
private function getHashtagLink($hashtag, $index = '')
{
- $hashtagLink = '#$1';
+ $hashtagLink = '#$1';
return str_replace('$1', $hashtag, $hashtagLink);
}
}
diff --git a/tests/feed/FeedBuilderTest.php b/tests/feed/FeedBuilderTest.php
index 54671891..535207aa 100644
--- a/tests/feed/FeedBuilderTest.php
+++ b/tests/feed/FeedBuilderTest.php
@@ -306,6 +306,6 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
$link = $data['links'][array_keys($data['links'])[2]];
$this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']);
$this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']);
- $this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']);
+ $this->assertContains('http://host.tld:8080/~user/shaarli/./add-tag/hashtag', $link['description']);
}
}
diff --git a/tests/formatter/BookmarkDefaultFormatterTest.php b/tests/formatter/BookmarkDefaultFormatterTest.php
index 382a560e..cf48b00b 100644
--- a/tests/formatter/BookmarkDefaultFormatterTest.php
+++ b/tests/formatter/BookmarkDefaultFormatterTest.php
@@ -123,7 +123,7 @@ class BookmarkDefaultFormatterTest extends TestCase
$description[0] = 'This a <strong>description</strong>
';
$url = 'https://sub.domain.tld?query=here&for=real#hash';
$description[1] = 'text '. $url .' more text
';
- $description[2] = 'Also, there is an #hashtag added
';
$description[3] = ' A N D KEEP '.
'SPACES !
';
@@ -148,7 +148,7 @@ class BookmarkDefaultFormatterTest extends TestCase
$this->assertEquals($root . $short, $link['url']);
$this->assertEquals($root . $short, $link['real_url']);
$this->assertEquals(
- 'Text '.
+ 'Text '.
'#hashtag more text',
$link['description']
);
diff --git a/tests/formatter/BookmarkMarkdownFormatterTest.php b/tests/formatter/BookmarkMarkdownFormatterTest.php
index f1f12c04..3e72d1ee 100644
--- a/tests/formatter/BookmarkMarkdownFormatterTest.php
+++ b/tests/formatter/BookmarkMarkdownFormatterTest.php
@@ -125,7 +125,7 @@ class BookmarkMarkdownFormatterTest extends TestCase
$description .= 'This a <strong>description</strong>
'. PHP_EOL;
$url = 'https://sub.domain.tld?query=here&for=real#hash';
$description .= 'text '. $url .' more text
'. PHP_EOL;
- $description .= 'Also, there is an #hashtag added
'. PHP_EOL;
+ $description .= 'Also, there is an #hashtag added
'. PHP_EOL;
$description .= 'A N D KEEP SPACES ! ';
$description .= '
';
@@ -146,7 +146,7 @@ class BookmarkMarkdownFormatterTest extends TestCase
$this->formatter->addContextData('index_url', $root = 'https://domain.tld/hithere/');
$description = '';
- $description .= 'Text #hashtag more text';
+ $description .= 'Text #hashtag more text';
$description .= '
';
$link = $this->formatter->format($bookmark);
diff --git a/tests/front/controller/TagControllerTest.php b/tests/front/controller/TagControllerTest.php
new file mode 100644
index 00000000..bbac5652
--- /dev/null
+++ b/tests/front/controller/TagControllerTest.php
@@ -0,0 +1,191 @@
+container = $this->createMock(ShaarliContainer::class);
+ $this->controller = new TagController($this->container);
+ }
+
+ public function testAddTagWithReferer(): void
+ {
+ $this->createValidContainerMockSet();
+ $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/'];
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $tags = ['newTag' => 'abc'];
+
+ $result = $this->controller->addTag($request, $response, $tags);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location'));
+ }
+
+ public function testAddTagWithRefererAndExistingSearch(): void
+ {
+ $this->createValidContainerMockSet();
+ $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def'];
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $tags = ['newTag' => 'abc'];
+
+ $result = $this->controller->addTag($request, $response, $tags);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location'));
+ }
+
+ public function testAddTagWithoutRefererAndExistingSearch(): void
+ {
+ $this->createValidContainerMockSet();
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $tags = ['newTag' => 'abc'];
+
+ $result = $this->controller->addTag($request, $response, $tags);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['./?searchtags=abc'], $result->getHeader('location'));
+ }
+
+ public function testAddTagRemoveLegacyQueryParam(): void
+ {
+ $this->createValidContainerMockSet();
+ $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc'];
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $tags = ['newTag' => 'abc'];
+
+ $result = $this->controller->addTag($request, $response, $tags);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location'));
+ }
+
+ public function testAddTagResetPagination(): void
+ {
+ $this->createValidContainerMockSet();
+ $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12'];
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $tags = ['newTag' => 'abc'];
+
+ $result = $this->controller->addTag($request, $response, $tags);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location'));
+ }
+
+ public function testAddTagWithRefererAndEmptySearch(): void
+ {
+ $this->createValidContainerMockSet();
+ $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags='];
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $tags = ['newTag' => 'abc'];
+
+ $result = $this->controller->addTag($request, $response, $tags);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location'));
+ }
+
+ public function testAddTagWithoutNewTagWithReferer(): void
+ {
+ $this->createValidContainerMockSet();
+ $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def'];
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $result = $this->controller->addTag($request, $response, []);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location'));
+ }
+
+ public function testAddTagWithoutNewTagWithoutReferer(): void
+ {
+ $this->createValidContainerMockSet();
+
+ $request = $this->createMock(Request::class);
+ $response = new Response();
+
+ $result = $this->controller->addTag($request, $response, []);
+
+ static::assertInstanceOf(Response::class, $result);
+ static::assertSame(302, $result->getStatusCode());
+ static::assertSame(['./'], $result->getHeader('location'));
+ }
+
+ protected function createValidContainerMockSet(): void
+ {
+ // User logged out
+ $loginManager = $this->createMock(LoginManager::class);
+ $loginManager->method('isLoggedIn')->willReturn(false);
+ $loginManager->method('canLogin')->willReturn(true);
+ $this->container->loginManager = $loginManager;
+
+ // Config
+ $conf = $this->createMock(ConfigManager::class);
+ $conf->method('get')->willReturnCallback(function (string $parameter, $default) {
+ return $default;
+ });
+ $this->container->conf = $conf;
+
+ // PageBuilder
+ $pageBuilder = $this->createMock(PageBuilder::class);
+ $pageBuilder
+ ->method('render')
+ ->willReturnCallback(function (string $template): string {
+ return $template;
+ })
+ ;
+ $this->container->pageBuilder = $pageBuilder;
+
+ $pluginManager = $this->createMock(PluginManager::class);
+ $this->container->pluginManager = $pluginManager;
+ $bookmarkService = $this->createMock(BookmarkServiceInterface::class);
+ $this->container->bookmarkService = $bookmarkService;
+ }
+}
diff --git a/tests/plugins/resources/hashtags.md b/tests/plugins/resources/hashtags.md
deleted file mode 100644
index 46326de3..00000000
--- a/tests/plugins/resources/hashtags.md
+++ /dev/null
@@ -1,10 +0,0 @@
-[#lol](?addtag=lol)
-
- #test
-
-`#test2`
-
-```
-bla #bli blo
-#bla
-```
diff --git a/tests/plugins/resources/hashtags.raw b/tests/plugins/resources/hashtags.raw
deleted file mode 100644
index 9d2dc98a..00000000
--- a/tests/plugins/resources/hashtags.raw
+++ /dev/null
@@ -1,10 +0,0 @@
-#lol
-
- #test
-
-`#test2`
-
-```
-bla #bli blo
-#bla
-```
diff --git a/tests/plugins/resources/markdown.html b/tests/plugins/resources/markdown.html
deleted file mode 100644
index c3460bf7..00000000
--- a/tests/plugins/resources/markdown.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
diff --git a/tests/plugins/resources/markdown.md b/tests/plugins/resources/markdown.md
deleted file mode 100644
index 9350a8c7..00000000
--- a/tests/plugins/resources/markdown.md
+++ /dev/null
@@ -1,34 +0,0 @@
-* test:
- * [zero](http://link.tld)
- + [two](http://link.tld)
- - [three](http://link.tld)
-
-1. [zero](http://link.tld)
- 2. [two](http://link.tld)
- 3. [three](http://link.tld)
- 4. [four](http://link.tld)
- 5. foo #foobar
-
-#foobar foo `lol #foo` #bar
-
-fsdfs http://link.tld #foobar `http://link.tld`
-
- http://link.tld #foobar
- next #foo
-
-Block:
-
-```
-lorem ipsum #foobar http://link.tld
-#foobar http://link.tld
-```
-
-[link](?123456)
-![link](/img/train.png)
-[link](test.tld/path/?query=value#hash)
-[link](http://test.tld/path/?query=value#hash)
-[link](https://test.tld/path/?query=value#hash)
-[link](ftp://test.tld/path/?query=value#hash)
-[link](magnet:test.tld/path/?query=value#hash)
-[link](javascript:alert('xss'))
-[link](other://test.tld/path/?query=value#hash)
diff --git a/tpl/default/linklist.html b/tpl/default/linklist.html
index 505b1614..d8a15823 100644
--- a/tpl/default/linklist.html
+++ b/tpl/default/linklist.html
@@ -181,7 +181,7 @@
{$tag_counter=count($value.taglist)}
{loop="value.taglist"}
- {$value}
+ {$value}
{if="$tag_counter - 1 != $counter"}·{/if}
{/loop}
diff --git a/tpl/default/tag.cloud.html b/tpl/default/tag.cloud.html
index 7839fcca..80dcebf5 100644
--- a/tpl/default/tag.cloud.html
+++ b/tpl/default/tag.cloud.html
@@ -49,7 +49,7 @@
{loop="tags"}
{$key}{$value.count}
+ >
{$value.count}
{loop="$value.tag_plugin"}
{$value}
{/loop}
diff --git a/tpl/default/tag.list.html b/tpl/default/tag.list.html
index dbc5ee3a..01b7a642 100644
--- a/tpl/default/tag.list.html
+++ b/tpl/default/tag.list.html
@@ -56,7 +56,7 @@
{/if}
-
{$value}
+
{$value}
{$key}
{loop="$value.tag_plugin"}
diff --git a/tpl/vintage/linklist.html b/tpl/vintage/linklist.html
index dcb14e90..8f1ded95 100644
--- a/tpl/vintage/linklist.html
+++ b/tpl/vintage/linklist.html
@@ -133,7 +133,7 @@
{$value.url}
{if="$value.tags"}
- {loop="$value.taglist"}
{$value} {/loop}
+ {loop="$value.taglist"}
{$value} {/loop}
{/if}
diff --git a/tpl/vintage/tag.cloud.html b/tpl/vintage/tag.cloud.html
index d93bf4f9..23aa381e 100644
--- a/tpl/vintage/tag.cloud.html
+++ b/tpl/vintage/tag.cloud.html
@@ -12,7 +12,7 @@