diff --git a/composer.lock b/composer.lock index fccc741c..ae7a9269 100644 --- a/composer.lock +++ b/composer.lock @@ -1498,12 +1498,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "ec1a75b10126327b351fdea7c2b9bfb94e2f6f35" + "reference": "5a342e2dc0408d026b97ee3176b5b406e54e3766" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/ec1a75b10126327b351fdea7c2b9bfb94e2f6f35", - "reference": "ec1a75b10126327b351fdea7c2b9bfb94e2f6f35", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/5a342e2dc0408d026b97ee3176b5b406e54e3766", + "reference": "5a342e2dc0408d026b97ee3176b5b406e54e3766", "shasum": "" }, "conflict": { @@ -1694,8 +1694,8 @@ "titon/framework": ">=0,<9.9.99", "truckersmp/phpwhois": "<=4.3.1", "twig/twig": "<1.38|>=2,<2.7", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.30|>=9,<9.5.12|>=10,<10.2.1", - "typo3/cms-core": ">=8,<8.7.30|>=9,<9.5.12|>=10,<10.2.1", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.30|>=9,<9.5.17|>=10,<10.4.2", + "typo3/cms-core": ">=8,<8.7.30|>=9,<9.5.17|>=10,<10.4.2", "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", "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", @@ -1758,7 +1758,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2020-05-09T00:00:21+00:00" + "time": "2020-05-12T11:18:47+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -2547,16 +2547,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "1aab00e39cebaef4d8652497f46c15c1b7e45294" + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/1aab00e39cebaef4d8652497f46c15c1b7e45294", - "reference": "1aab00e39cebaef4d8652497f46c15c1b7e45294", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", "shasum": "" }, "require": { @@ -2568,7 +2568,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.16-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -2601,20 +2601,20 @@ "polyfill", "portable" ], - "time": "2020-05-08T16:50:20+00:00" + "time": "2020-05-12T16:14:59+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "a54881ec0ab3b2005c406aed0023c062879031e7" + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/a54881ec0ab3b2005c406aed0023c062879031e7", - "reference": "a54881ec0ab3b2005c406aed0023c062879031e7", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c", + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c", "shasum": "" }, "require": { @@ -2626,7 +2626,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.16-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -2660,20 +2660,20 @@ "portable", "shim" ], - "time": "2020-05-08T16:50:20+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "7e95fe59d12169fcf4041487e4bf34fca37ee0ed" + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/7e95fe59d12169fcf4041487e4bf34fca37ee0ed", - "reference": "7e95fe59d12169fcf4041487e4bf34fca37ee0ed", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a760d8964ff79ab9bf057613a5808284ec852ccc", + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc", "shasum": "" }, "require": { @@ -2682,7 +2682,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.16-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -2718,7 +2718,7 @@ "portable", "shim" ], - "time": "2020-05-02T14:56:09+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/service-contracts", diff --git a/index.php b/index.php index 83f1264f..423a68f4 100644 --- a/index.php +++ b/index.php @@ -852,7 +852,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM // Show login screen, then redirect to ?post=... if (isset($_GET['post'])) { header( // Redirect to login page, then back to post link. - 'Location: /login?post='.urlencode($_GET['post']). + 'Location: ./login?post='.urlencode($_GET['post']). (!empty($_GET['title'])?'&title='.urlencode($_GET['title']):''). (!empty($_GET['description'])?'&description='.urlencode($_GET['description']):''). (!empty($_GET['tags'])?'&tags='.urlencode($_GET['tags']):''). @@ -863,7 +863,7 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM showLinkList($PAGE, $bookmarkService, $conf, $pluginManager, $loginManager); if (isset($_GET['edit_link'])) { - header('Location: /login?edit_link='. escape($_GET['edit_link'])); + header('Location: ./login?edit_link='. escape($_GET['edit_link'])); exit; } diff --git a/tests/front/controller/TagCloudControllerTest.php b/tests/front/controller/TagCloudControllerTest.php new file mode 100644 index 00000000..a76d5835 --- /dev/null +++ b/tests/front/controller/TagCloudControllerTest.php @@ -0,0 +1,258 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new TagCloudController($this->container); + } + + public function testValidCloudControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'ghi' => 1, + 'abc' => 3, + 'def' => 12, + ]; + $expectedOrder = ['abc', 'def', 'ghi']; + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getQueryParam')->with('searchtags')->willReturn(null); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(3, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(3, $assignedVariables['tags']); + static::assertSame($expectedOrder, array_keys($assignedVariables['tags'])); + + foreach ($allTags as $tag => $count) { + static::assertArrayHasKey($tag, $assignedVariables['tags']); + static::assertSame($count, $assignedVariables['tags'][$tag]['count']); + static::assertGreaterThan(0, $assignedVariables['tags'][$tag]['size']); + static::assertLessThan(5, $assignedVariables['tags'][$tag]['size']); + } + } + + /** + * Additional parameters: + * - logged in + * - visibility private + * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) + */ + public function testValidCloudControllerInvokeWithParameters(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'ghi' => 1, + 'abc' => 3, + 'def' => 12, + ]; + + $request = $this->createMock(Request::class); + $request + ->expects(static::once()) + ->method('getQueryParam') + ->with('searchtags') + ->willReturn('ghi def') + ; + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->loginManager->method('isLoggedin')->willReturn(true); + $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('ghi def', $data['search_tags']); + static::assertCount(1, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('ghi def - Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('ghi def', $assignedVariables['search_tags']); + static::assertCount(1, $assignedVariables['tags']); + + static::assertArrayHasKey('abc', $assignedVariables['tags']); + static::assertSame(3, $assignedVariables['tags']['abc']['count']); + static::assertGreaterThan(0, $assignedVariables['tags']['abc']['size']); + static::assertLessThan(5, $assignedVariables['tags']['abc']['size']); + } + + public function testEmptyCloud(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getQueryParam')->with('searchtags')->willReturn(null); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(0, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(0, $assignedVariables['tags']); + } + + protected function createValidContainerMockSet(): void + { + $loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager = $loginManager; + + $sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager = $sessionManager; + + // Config + $conf = $this->createMock(ConfigManager::class); + $this->container->conf = $conf; + + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + // Plugin Manager + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + + // BookmarkService + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + } + + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } +} diff --git a/tpl/default/page.header.html b/tpl/default/page.header.html index ea89a209..6b686580 100644 --- a/tpl/default/page.header.html +++ b/tpl/default/page.header.html @@ -56,11 +56,11 @@ {if="$is_logged_in"}
  • - {'Logout'|t} + {'Logout'|t}
  • {else}
  • - {'Login'|t} + {'Login'|t}
  • {/if} @@ -80,7 +80,7 @@ {if="!$is_logged_in"}
  • - @@ -88,7 +88,7 @@
  • {else}
  • - +
  • diff --git a/tpl/vintage/page.header.html b/tpl/vintage/page.header.html index 971fac9a..d9451555 100644 --- a/tpl/vintage/page.header.html +++ b/tpl/vintage/page.header.html @@ -18,14 +18,14 @@ {else}
  • Home
  • {if="$is_logged_in"} -
  • Logout
  • +
  • Logout
  • Tools
  • Add link
  • {elseif="$openshaarli"}
  • Tools
  • Add link
  • {else} -
  • Login
  • +
  • Login
  • {/if}
  • RSS Feed
  • {if="$showatom"}