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 @@ /** * 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 @@ function ($match) use ($allowedProtocols, $indexUrl) { /** * 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 @@ protected function formatHashTags($description) * \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 @@ function install($conf, $sessionManager, $loginManager) $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 @@ public function testIsNotNote() */ 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 @@ public function testBuildDataServerSubdir() $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 @@ public function testFormatDescription() $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 @@ public function testFormatNoteWithIndexUrl() $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 @@ public function testFormatDescription() $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 @@ public function testFormatNoteWithIndexUrl() $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 @@ -
-
    -
  1. zero -
      -
    1. two
    2. -
    3. three
    4. -
    5. four
    6. -
    7. foo #foobar
    8. -
  2. -
-

#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
-link
-link
-link
-link
-link
-link
-link
-link

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 @@

{'Tag cloud'|t} - {$countTags} {'tags'|t}

{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 @@

{'Tag list'|t} - {$countTags} {'tags'|t}

{/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 @@
{loop="$tags"} - {$value.count}{$value.count}{$key} {loop="$value.tag_plugin"} {$value}