aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2020-05-30 14:00:06 +0200
committerArthurHoaro <arthur@hoa.ro>2020-07-23 21:19:21 +0200
commit66063ed1a18d739b1a60bfb163d8656417a4c529 (patch)
tree5af628861a42af1a4bf84f6dcd18a24b80cc3a1c
parent465033230da0398426010aa7bd3694735b71c899 (diff)
downloadShaarli-66063ed1a18d739b1a60bfb163d8656417a4c529.tar.gz
Shaarli-66063ed1a18d739b1a60bfb163d8656417a4c529.tar.zst
Shaarli-66063ed1a18d739b1a60bfb163d8656417a4c529.zip
Process configure page through Slim controller
-rw-r--r--application/front/controller/admin/ConfigureController.php120
-rw-r--r--application/render/PageBuilder.php4
-rw-r--r--doc/md/Translations.md2
-rw-r--r--index.php86
-rw-r--r--tests/front/controller/admin/ConfigureControllerTest.php252
-rw-r--r--tests/front/controller/admin/FrontAdminControllerMockHelper.php23
-rw-r--r--tests/front/controller/visitor/DailyControllerTest.php27
-rw-r--r--tests/front/controller/visitor/FrontControllerMockHelper.php10
-rw-r--r--tpl/default/configure.html2
-rw-r--r--tpl/default/tools.html2
-rw-r--r--tpl/vintage/configure.html2
-rw-r--r--tpl/vintage/tools.html2
12 files changed, 427 insertions, 105 deletions
diff --git a/application/front/controller/admin/ConfigureController.php b/application/front/controller/admin/ConfigureController.php
new file mode 100644
index 00000000..b1d32270
--- /dev/null
+++ b/application/front/controller/admin/ConfigureController.php
@@ -0,0 +1,120 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use Shaarli\Languages;
8use Shaarli\Render\ThemeUtils;
9use Shaarli\Thumbnailer;
10use Slim\Http\Request;
11use Slim\Http\Response;
12use Throwable;
13
14/**
15 * Class PasswordController
16 *
17 * Slim controller used to handle Shaarli configuration page (display + save new config).
18 */
19class ConfigureController extends ShaarliAdminController
20{
21 /**
22 * GET /configure - Displays the configuration page
23 */
24 public function index(Request $request, Response $response): Response
25 {
26 $this->assignView('title', $this->container->conf->get('general.title', 'Shaarli'));
27 $this->assignView('theme', $this->container->conf->get('resource.theme'));
28 $this->assignView(
29 'theme_available',
30 ThemeUtils::getThemes($this->container->conf->get('resource.raintpl_tpl'))
31 );
32 $this->assignView('formatter_available', ['default', 'markdown']);
33 list($continents, $cities) = generateTimeZoneData(
34 timezone_identifiers_list(),
35 $this->container->conf->get('general.timezone')
36 );
37 $this->assignView('continents', $continents);
38 $this->assignView('cities', $cities);
39 $this->assignView('retrieve_description', $this->container->conf->get('general.retrieve_description', false));
40 $this->assignView('private_links_default', $this->container->conf->get('privacy.default_private_links', false));
41 $this->assignView(
42 'session_protection_disabled',
43 $this->container->conf->get('security.session_protection_disabled', false)
44 );
45 $this->assignView('enable_rss_permalinks', $this->container->conf->get('feed.rss_permalinks', false));
46 $this->assignView('enable_update_check', $this->container->conf->get('updates.check_updates', true));
47 $this->assignView('hide_public_links', $this->container->conf->get('privacy.hide_public_links', false));
48 $this->assignView('api_enabled', $this->container->conf->get('api.enabled', true));
49 $this->assignView('api_secret', $this->container->conf->get('api.secret'));
50 $this->assignView('languages', Languages::getAvailableLanguages());
51 $this->assignView('gd_enabled', extension_loaded('gd'));
52 $this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE));
53 $this->assignView('pagetitle', t('Configure') .' - '. $this->container->conf->get('general.title', 'Shaarli'));
54
55 return $response->write($this->render('configure'));
56 }
57
58 /**
59 * POST /configure - Update Shaarli's configuration
60 */
61 public function save(Request $request, Response $response): Response
62 {
63 $this->checkToken($request);
64
65 $continent = $request->getParam('continent');
66 $city = $request->getParam('city');
67 $tz = 'UTC';
68 if (null !== $continent && null !== $city && isTimeZoneValid($continent, $city)) {
69 $tz = $continent . '/' . $city;
70 }
71
72 $this->container->conf->set('general.timezone', $tz);
73 $this->container->conf->set('general.title', escape($request->getParam('title')));
74 $this->container->conf->set('general.header_link', escape($request->getParam('titleLink')));
75 $this->container->conf->set('general.retrieve_description', !empty($request->getParam('retrieveDescription')));
76 $this->container->conf->set('resource.theme', escape($request->getParam('theme')));
77 $this->container->conf->set(
78 'security.session_protection_disabled',
79 !empty($request->getParam('disablesessionprotection'))
80 );
81 $this->container->conf->set(
82 'privacy.default_private_links',
83 !empty($request->getParam('privateLinkByDefault'))
84 );
85 $this->container->conf->set('feed.rss_permalinks', !empty($request->getParam('enableRssPermalinks')));
86 $this->container->conf->set('updates.check_updates', !empty($request->getParam('updateCheck')));
87 $this->container->conf->set('privacy.hide_public_links', !empty($request->getParam('hidePublicLinks')));
88 $this->container->conf->set('api.enabled', !empty($request->getParam('enableApi')));
89 $this->container->conf->set('api.secret', escape($request->getParam('apiSecret')));
90 $this->container->conf->set('formatter', escape($request->getParam('formatter')));
91
92 if (!empty($request->getParam('language'))) {
93 $this->container->conf->set('translation.language', escape($request->getParam('language')));
94 }
95
96 $thumbnailsMode = extension_loaded('gd') ? $request->getParam('enableThumbnails') : Thumbnailer::MODE_NONE;
97 if ($thumbnailsMode !== Thumbnailer::MODE_NONE
98 && $thumbnailsMode !== $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
99 ) {
100 $this->saveWarningMessage(t(
101 'You have enabled or changed thumbnails mode. '
102 .'<a href="./?do=thumbs_update">Please synchronize them</a>.'
103 ));
104 }
105 $this->container->conf->set('thumbnails.mode', $thumbnailsMode);
106
107 try {
108 $this->container->conf->write($this->container->loginManager->isLoggedIn());
109 $this->container->history->updateSettings();
110 $this->container->pageCacheManager->invalidateCaches();
111 } catch (Throwable $e) {
112 // TODO: translation + stacktrace
113 $this->saveErrorMessage('ERROR while writing config file after configuration update.');
114 }
115
116 $this->saveSuccessMessage(t('Configuration was saved.'));
117
118 return $response->withRedirect('./configure');
119 }
120}
diff --git a/application/render/PageBuilder.php b/application/render/PageBuilder.php
index 264cd33b..d90ed58b 100644
--- a/application/render/PageBuilder.php
+++ b/application/render/PageBuilder.php
@@ -143,6 +143,10 @@ class PageBuilder
143 $this->tpl->assign('conf', $this->conf); 143 $this->tpl->assign('conf', $this->conf);
144 } 144 }
145 145
146 /**
147 * Affect variable after controller processing.
148 * Used for alert messages.
149 */
146 protected function finalize(): void 150 protected function finalize(): void
147 { 151 {
148 // TODO: use the SessionManager 152 // TODO: use the SessionManager
diff --git a/doc/md/Translations.md b/doc/md/Translations.md
index 38878940..9a16075a 100644
--- a/doc/md/Translations.md
+++ b/doc/md/Translations.md
@@ -35,7 +35,7 @@ http://<replace_domain>/?nonope
35http://<replace_domain>/?do=addlink 35http://<replace_domain>/?do=addlink
36http://<replace_domain>/?do=changepasswd 36http://<replace_domain>/?do=changepasswd
37http://<replace_domain>/?do=changetag 37http://<replace_domain>/?do=changetag
38http://<replace_domain>/?do=configure 38http://<replace_domain>/configure
39http://<replace_domain>/tools 39http://<replace_domain>/tools
40http://<replace_domain>/daily 40http://<replace_domain>/daily
41http://<replace_domain>/?post 41http://<replace_domain>/?post
diff --git a/index.php b/index.php
index ae56b800..50c0634a 100644
--- a/index.php
+++ b/index.php
@@ -513,88 +513,8 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
513 513
514 // -------- User wants to change configuration 514 // -------- User wants to change configuration
515 if ($targetPage == Router::$PAGE_CONFIGURE) { 515 if ($targetPage == Router::$PAGE_CONFIGURE) {
516 if (!empty($_POST['title'])) { 516 header('Location: ./configure');
517 if (!$sessionManager->checkToken($_POST['token'])) { 517 exit;
518 die(t('Wrong token.')); // Go away!
519 }
520 $tz = 'UTC';
521 if (!empty($_POST['continent']) && !empty($_POST['city'])
522 && isTimeZoneValid($_POST['continent'], $_POST['city'])
523 ) {
524 $tz = $_POST['continent'] . '/' . $_POST['city'];
525 }
526 $conf->set('general.timezone', $tz);
527 $conf->set('general.title', escape($_POST['title']));
528 $conf->set('general.header_link', escape($_POST['titleLink']));
529 $conf->set('general.retrieve_description', !empty($_POST['retrieveDescription']));
530 $conf->set('resource.theme', escape($_POST['theme']));
531 $conf->set('security.session_protection_disabled', !empty($_POST['disablesessionprotection']));
532 $conf->set('privacy.default_private_links', !empty($_POST['privateLinkByDefault']));
533 $conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks']));
534 $conf->set('updates.check_updates', !empty($_POST['updateCheck']));
535 $conf->set('privacy.hide_public_links', !empty($_POST['hidePublicLinks']));
536 $conf->set('api.enabled', !empty($_POST['enableApi']));
537 $conf->set('api.secret', escape($_POST['apiSecret']));
538 $conf->set('formatter', escape($_POST['formatter']));
539
540 if (! empty($_POST['language'])) {
541 $conf->set('translation.language', escape($_POST['language']));
542 }
543
544 $thumbnailsMode = extension_loaded('gd') ? $_POST['enableThumbnails'] : Thumbnailer::MODE_NONE;
545 if ($thumbnailsMode !== Thumbnailer::MODE_NONE
546 && $thumbnailsMode !== $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
547 ) {
548 $_SESSION['warnings'][] = t(
549 'You have enabled or changed thumbnails mode. '
550 .'<a href="./?do=thumbs_update">Please synchronize them</a>.'
551 );
552 }
553 $conf->set('thumbnails.mode', $thumbnailsMode);
554
555 try {
556 $conf->write($loginManager->isLoggedIn());
557 $history->updateSettings();
558 $pageCacheManager->invalidateCaches();
559 } catch (Exception $e) {
560 error_log(
561 'ERROR while writing config file after configuration update.' . PHP_EOL .
562 $e->getMessage()
563 );
564
565 // TODO: do not handle exceptions/errors in JS.
566 echo '<script>alert("'. $e->getMessage() .'");document.location=\'./?do=configure\';</script>';
567 exit;
568 }
569 echo '<script>alert("'. t('Configuration was saved.') .'");document.location=\'./?do=configure\';</script>';
570 exit;
571 } else {
572 // Show the configuration form.
573 $PAGE->assign('title', $conf->get('general.title'));
574 $PAGE->assign('theme', $conf->get('resource.theme'));
575 $PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl')));
576 $PAGE->assign('formatter_available', ['default', 'markdown']);
577 list($continents, $cities) = generateTimeZoneData(
578 timezone_identifiers_list(),
579 $conf->get('general.timezone')
580 );
581 $PAGE->assign('continents', $continents);
582 $PAGE->assign('cities', $cities);
583 $PAGE->assign('retrieve_description', $conf->get('general.retrieve_description'));
584 $PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false));
585 $PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false));
586 $PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false));
587 $PAGE->assign('enable_update_check', $conf->get('updates.check_updates', true));
588 $PAGE->assign('hide_public_links', $conf->get('privacy.hide_public_links', false));
589 $PAGE->assign('api_enabled', $conf->get('api.enabled', true));
590 $PAGE->assign('api_secret', $conf->get('api.secret'));
591 $PAGE->assign('languages', Languages::getAvailableLanguages());
592 $PAGE->assign('gd_enabled', extension_loaded('gd'));
593 $PAGE->assign('thumbnails_mode', $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE));
594 $PAGE->assign('pagetitle', t('Configure') .' - '. $conf->get('general.title', 'Shaarli'));
595 $PAGE->renderPage('configure');
596 exit;
597 }
598 } 518 }
599 519
600 // -------- User wants to rename a tag or delete it 520 // -------- User wants to rename a tag or delete it
@@ -1458,6 +1378,8 @@ $app->group('', function () {
1458 $this->get('/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index')->setName('tools'); 1378 $this->get('/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index')->setName('tools');
1459 $this->get('/password', '\Shaarli\Front\Controller\Admin\PasswordController:index')->setName('password'); 1379 $this->get('/password', '\Shaarli\Front\Controller\Admin\PasswordController:index')->setName('password');
1460 $this->post('/password', '\Shaarli\Front\Controller\Admin\PasswordController:change')->setName('changePassword'); 1380 $this->post('/password', '\Shaarli\Front\Controller\Admin\PasswordController:change')->setName('changePassword');
1381 $this->get('/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:index')->setName('configure');
1382 $this->post('/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:save')->setName('saveConfigure');
1461 1383
1462 $this 1384 $this
1463 ->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage') 1385 ->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage')
diff --git a/tests/front/controller/admin/ConfigureControllerTest.php b/tests/front/controller/admin/ConfigureControllerTest.php
new file mode 100644
index 00000000..40304a18
--- /dev/null
+++ b/tests/front/controller/admin/ConfigureControllerTest.php
@@ -0,0 +1,252 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Exception\WrongTokenException;
10use Shaarli\Security\SessionManager;
11use Shaarli\Thumbnailer;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15class ConfigureControllerTest extends TestCase
16{
17 use FrontAdminControllerMockHelper;
18
19 /** @var ConfigureController */
20 protected $controller;
21
22 public function setUp(): void
23 {
24 $this->createContainer();
25
26 $this->controller = new ConfigureController($this->container);
27 }
28
29 /**
30 * Test displaying configure page - it should display all config variables
31 */
32 public function testIndex(): void
33 {
34 $assignedVariables = [];
35 $this->assignTemplateVars($assignedVariables);
36
37 $request = $this->createMock(Request::class);
38 $response = new Response();
39
40 $this->container->conf = $this->createMock(ConfigManager::class);
41 $this->container->conf->method('get')->willReturnCallback(function (string $key) {
42 return $key;
43 });
44
45 $result = $this->controller->index($request, $response);
46
47 static::assertSame(200, $result->getStatusCode());
48 static::assertSame('configure', (string) $result->getBody());
49
50 static::assertSame('Configure - general.title', $assignedVariables['pagetitle']);
51 static::assertSame('general.title', $assignedVariables['title']);
52 static::assertSame('resource.theme', $assignedVariables['theme']);
53 static::assertEmpty($assignedVariables['theme_available']);
54 static::assertSame(['default', 'markdown'], $assignedVariables['formatter_available']);
55 static::assertNotEmpty($assignedVariables['continents']);
56 static::assertNotEmpty($assignedVariables['cities']);
57 static::assertSame('general.retrieve_description', $assignedVariables['retrieve_description']);
58 static::assertSame('privacy.default_private_links', $assignedVariables['private_links_default']);
59 static::assertSame('security.session_protection_disabled', $assignedVariables['session_protection_disabled']);
60 static::assertSame('feed.rss_permalinks', $assignedVariables['enable_rss_permalinks']);
61 static::assertSame('updates.check_updates', $assignedVariables['enable_update_check']);
62 static::assertSame('privacy.hide_public_links', $assignedVariables['hide_public_links']);
63 static::assertSame('api.enabled', $assignedVariables['api_enabled']);
64 static::assertSame('api.secret', $assignedVariables['api_secret']);
65 static::assertCount(4, $assignedVariables['languages']);
66 static::assertArrayHasKey('gd_enabled', $assignedVariables);
67 static::assertSame('thumbnails.mode', $assignedVariables['thumbnails_mode']);
68 }
69
70 /**
71 * Test posting a new config - make sure that everything is saved properly, without errors.
72 */
73 public function testSaveNewConfig(): void
74 {
75 $session = [];
76 $this->assignSessionVars($session);
77
78 $parameters = [
79 'token' => 'token',
80 'continent' => 'Europe',
81 'city' => 'Moscow',
82 'title' => 'Shaarli',
83 'titleLink' => './',
84 'retrieveDescription' => 'on',
85 'theme' => 'vintage',
86 'disablesessionprotection' => null,
87 'privateLinkByDefault' => true,
88 'enableRssPermalinks' => true,
89 'updateCheck' => false,
90 'hidePublicLinks' => 'on',
91 'enableApi' => 'on',
92 'apiSecret' => 'abcdef',
93 'formatter' => 'markdown',
94 'language' => 'fr',
95 'enableThumbnails' => Thumbnailer::MODE_NONE,
96 ];
97
98 $parametersConfigMapping = [
99 'general.timezone' => $parameters['continent'] . '/' . $parameters['city'],
100 'general.title' => $parameters['title'],
101 'general.header_link' => $parameters['titleLink'],
102 'general.retrieve_description' => !!$parameters['retrieveDescription'],
103 'resource.theme' => $parameters['theme'],
104 'security.session_protection_disabled' => !!$parameters['disablesessionprotection'],
105 'privacy.default_private_links' => !!$parameters['privateLinkByDefault'],
106 'feed.rss_permalinks' => !!$parameters['enableRssPermalinks'],
107 'updates.check_updates' => !!$parameters['updateCheck'],
108 'privacy.hide_public_links' => !!$parameters['hidePublicLinks'],
109 'api.enabled' => !!$parameters['enableApi'],
110 'api.secret' => $parameters['apiSecret'],
111 'formatter' => $parameters['formatter'],
112 'translation.language' => $parameters['language'],
113 'thumbnails.mode' => $parameters['enableThumbnails'],
114 ];
115
116 $request = $this->createMock(Request::class);
117 $request
118 ->expects(static::atLeastOnce())
119 ->method('getParam')->willReturnCallback(function (string $key) use ($parameters) {
120 if (false === array_key_exists($key, $parameters)) {
121 static::fail('unknown key: ' . $key);
122 }
123
124 return $parameters[$key];
125 }
126 );
127
128 $response = new Response();
129
130 $this->container->conf = $this->createMock(ConfigManager::class);
131 $this->container->conf
132 ->expects(static::atLeastOnce())
133 ->method('set')
134 ->willReturnCallback(function (string $key, $value) use ($parametersConfigMapping): void {
135 if (false === array_key_exists($key, $parametersConfigMapping)) {
136 static::fail('unknown key: ' . $key);
137 }
138
139 static::assertSame($parametersConfigMapping[$key], $value);
140 }
141 );
142
143 $result = $this->controller->save($request, $response);
144 static::assertSame(302, $result->getStatusCode());
145 static::assertSame(['./configure'], $result->getHeader('Location'));
146
147 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
148 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
149 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
150 static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
151 }
152
153 /**
154 * Test posting a new config - wrong token.
155 */
156 public function testSaveNewConfigWrongToken(): void
157 {
158 $this->container->sessionManager = $this->createMock(SessionManager::class);
159 $this->container->sessionManager->method('checkToken')->willReturn(false);
160
161 $this->container->conf->expects(static::never())->method('set');
162 $this->container->conf->expects(static::never())->method('write');
163
164 $request = $this->createMock(Request::class);
165 $response = new Response();
166
167 $this->expectException(WrongTokenException::class);
168
169 $this->controller->save($request, $response);
170 }
171
172 /**
173 * Test posting a new config - thumbnail activation.
174 */
175 public function testSaveNewConfigThumbnailsActivation(): void
176 {
177 $session = [];
178 $this->assignSessionVars($session);
179
180 $request = $this->createMock(Request::class);
181 $request
182 ->expects(static::atLeastOnce())
183 ->method('getParam')->willReturnCallback(function (string $key) {
184 if ('enableThumbnails' === $key) {
185 return Thumbnailer::MODE_ALL;
186 }
187
188 return $key;
189 })
190 ;
191 $response = new Response();
192
193 $result = $this->controller->save($request, $response);
194
195 static::assertSame(302, $result->getStatusCode());
196 static::assertSame(['./configure'], $result->getHeader('Location'));
197
198 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
199 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
200 static::assertStringContainsString(
201 'You have enabled or changed thumbnails mode',
202 $session[SessionManager::KEY_WARNING_MESSAGES][0]
203 );
204 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
205 static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
206 }
207
208 /**
209 * Test posting a new config - thumbnail activation.
210 */
211 public function testSaveNewConfigThumbnailsAlreadyActive(): void
212 {
213 $session = [];
214 $this->assignSessionVars($session);
215
216 $request = $this->createMock(Request::class);
217 $request
218 ->expects(static::atLeastOnce())
219 ->method('getParam')->willReturnCallback(function (string $key) {
220 if ('enableThumbnails' === $key) {
221 return Thumbnailer::MODE_ALL;
222 }
223
224 return $key;
225 })
226 ;
227 $response = new Response();
228
229 $this->container->conf = $this->createMock(ConfigManager::class);
230 $this->container->conf
231 ->expects(static::atLeastOnce())
232 ->method('get')
233 ->willReturnCallback(function (string $key): string {
234 if ('thumbnails.mode' === $key) {
235 return Thumbnailer::MODE_ALL;
236 }
237
238 return $key;
239 })
240 ;
241
242 $result = $this->controller->save($request, $response);
243
244 static::assertSame(302, $result->getStatusCode());
245 static::assertSame(['./configure'], $result->getHeader('Location'));
246
247 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
248 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
249 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
250 static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
251 }
252}
diff --git a/tests/front/controller/admin/FrontAdminControllerMockHelper.php b/tests/front/controller/admin/FrontAdminControllerMockHelper.php
index bd40c0c7..2b9f2ef1 100644
--- a/tests/front/controller/admin/FrontAdminControllerMockHelper.php
+++ b/tests/front/controller/admin/FrontAdminControllerMockHelper.php
@@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller\Admin;
6 6
7use Shaarli\Container\ShaarliTestContainer; 7use Shaarli\Container\ShaarliTestContainer;
8use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper; 8use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper;
9use Shaarli\History;
9 10
10/** 11/**
11 * Trait FrontControllerMockHelper 12 * Trait FrontControllerMockHelper
@@ -27,7 +28,29 @@ trait FrontAdminControllerMockHelper
27 { 28 {
28 $this->parentCreateContainer(); 29 $this->parentCreateContainer();
29 30
31 $this->container->history = $this->createMock(History::class);
32
30 $this->container->loginManager->method('isLoggedIn')->willReturn(true); 33 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
31 $this->container->sessionManager->method('checkToken')->willReturn(true); 34 $this->container->sessionManager->method('checkToken')->willReturn(true);
32 } 35 }
36
37
38 /**
39 * Pass a reference of an array which will be populated by `sessionManager->setSessionParameter`
40 * calls during execution.
41 *
42 * @param mixed $variables Array reference to populate.
43 */
44 protected function assignSessionVars(array &$variables): void
45 {
46 $this->container->sessionManager
47 ->expects(static::atLeastOnce())
48 ->method('setSessionParameter')
49 ->willReturnCallback(function ($key, $value) use (&$variables) {
50 $variables[$key] = $value;
51
52 return $this->container->sessionManager;
53 })
54 ;
55 }
33} 56}
diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php
index 872420fd..b802c62c 100644
--- a/tests/front/controller/visitor/DailyControllerTest.php
+++ b/tests/front/controller/visitor/DailyControllerTest.php
@@ -57,20 +57,20 @@ class DailyControllerTest extends TestCase
57 (new Bookmark()) 57 (new Bookmark())
58 ->setId(1) 58 ->setId(1)
59 ->setUrl('http://url.tld') 59 ->setUrl('http://url.tld')
60 ->setTitle(static::generateContent(50)) 60 ->setTitle(static::generateString(50))
61 ->setDescription(static::generateContent(500)) 61 ->setDescription(static::generateString(500))
62 , 62 ,
63 (new Bookmark()) 63 (new Bookmark())
64 ->setId(2) 64 ->setId(2)
65 ->setUrl('http://url2.tld') 65 ->setUrl('http://url2.tld')
66 ->setTitle(static::generateContent(50)) 66 ->setTitle(static::generateString(50))
67 ->setDescription(static::generateContent(500)) 67 ->setDescription(static::generateString(500))
68 , 68 ,
69 (new Bookmark()) 69 (new Bookmark())
70 ->setId(3) 70 ->setId(3)
71 ->setUrl('http://url3.tld') 71 ->setUrl('http://url3.tld')
72 ->setTitle(static::generateContent(50)) 72 ->setTitle(static::generateString(50))
73 ->setDescription(static::generateContent(500)) 73 ->setDescription(static::generateString(500))
74 , 74 ,
75 ]; 75 ];
76 }) 76 })
@@ -194,8 +194,8 @@ class DailyControllerTest extends TestCase
194 (new Bookmark()) 194 (new Bookmark())
195 ->setId(1) 195 ->setId(1)
196 ->setUrl('http://url.tld') 196 ->setUrl('http://url.tld')
197 ->setTitle(static::generateContent(50)) 197 ->setTitle(static::generateString(50))
198 ->setDescription(static::generateContent(500)) 198 ->setDescription(static::generateString(500))
199 , 199 ,
200 ]; 200 ];
201 }) 201 })
@@ -267,8 +267,8 @@ class DailyControllerTest extends TestCase
267 (new Bookmark()) 267 (new Bookmark())
268 ->setId(2) 268 ->setId(2)
269 ->setUrl('http://url.tld') 269 ->setUrl('http://url.tld')
270 ->setTitle(static::generateContent(50)) 270 ->setTitle(static::generateString(50))
271 ->setDescription(static::generateContent(5000)) 271 ->setDescription(static::generateString(5000))
272 , 272 ,
273 (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), 273 (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'),
274 (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), 274 (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'),
@@ -473,11 +473,4 @@ class DailyControllerTest extends TestCase
473 static::assertFalse($assignedVariables['hide_timestamps']); 473 static::assertFalse($assignedVariables['hide_timestamps']);
474 static::assertCount(0, $assignedVariables['days']); 474 static::assertCount(0, $assignedVariables['days']);
475 } 475 }
476
477 protected static function generateContent(int $length): string
478 {
479 // bin2hex(random_bytes) generates string twice as long as given parameter
480 $length = (int) ceil($length / 2);
481 return bin2hex(random_bytes($length));
482 }
483} 476}
diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php
index d16b6949..fecd0c82 100644
--- a/tests/front/controller/visitor/FrontControllerMockHelper.php
+++ b/tests/front/controller/visitor/FrontControllerMockHelper.php
@@ -42,7 +42,7 @@ trait FrontControllerMockHelper
42 // Config 42 // Config
43 $this->container->conf = $this->createMock(ConfigManager::class); 43 $this->container->conf = $this->createMock(ConfigManager::class);
44 $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { 44 $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) {
45 return $default; 45 return $default === null ? $parameter : $default;
46 }); 46 });
47 47
48 // PageBuilder 48 // PageBuilder
@@ -101,6 +101,14 @@ trait FrontControllerMockHelper
101 ; 101 ;
102 } 102 }
103 103
104 protected static function generateString(int $length): string
105 {
106 // bin2hex(random_bytes) generates string twice as long as given parameter
107 $length = (int) ceil($length / 2);
108
109 return bin2hex(random_bytes($length));
110 }
111
104 /** 112 /**
105 * Force to be used in PHPUnit context. 113 * Force to be used in PHPUnit context.
106 */ 114 */
diff --git a/tpl/default/configure.html b/tpl/default/configure.html
index 9b6a9c46..46bef052 100644
--- a/tpl/default/configure.html
+++ b/tpl/default/configure.html
@@ -35,7 +35,7 @@
35 <div class="form-label"> 35 <div class="form-label">
36 <label for="titleLink"> 36 <label for="titleLink">
37 <span class="label-name">{'Home link'|t}</span><br> 37 <span class="label-name">{'Home link'|t}</span><br>
38 <span class="label-desc">{'Default value'|t}: ?</span> 38 <span class="label-desc">{'Default value'|t}: ./</span>
39 </label> 39 </label>
40 </div> 40 </div>
41 </div> 41 </div>
diff --git a/tpl/default/tools.html b/tpl/default/tools.html
index 4a490963..0135c480 100644
--- a/tpl/default/tools.html
+++ b/tpl/default/tools.html
@@ -11,7 +11,7 @@
11 <div class="pure-u-lg-1-3 pure-u-22-24 page-form page-form-light"> 11 <div class="pure-u-lg-1-3 pure-u-22-24 page-form page-form-light">
12 <h2 class="window-title">{'Settings'|t}</h2> 12 <h2 class="window-title">{'Settings'|t}</h2>
13 <div class="tools-item"> 13 <div class="tools-item">
14 <a href="./?do=configure" title="{'Change Shaarli settings: title, timezone, etc.'|t}"> 14 <a href="./configure" title="{'Change Shaarli settings: title, timezone, etc.'|t}">
15 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Configure your Shaarli'|t}</span> 15 <span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Configure your Shaarli'|t}</span>
16 </a> 16 </a>
17 </div> 17 </div>
diff --git a/tpl/vintage/configure.html b/tpl/vintage/configure.html
index 8d20ea80..a87fdce7 100644
--- a/tpl/vintage/configure.html
+++ b/tpl/vintage/configure.html
@@ -16,7 +16,7 @@
16 <tr> 16 <tr>
17 <td><b>Home link:</b></td> 17 <td><b>Home link:</b></td>
18 <td><input type="text" name="titleLink" id="titleLink" size="50" value="{$titleLink}"><br/><label 18 <td><input type="text" name="titleLink" id="titleLink" size="50" value="{$titleLink}"><br/><label
19 for="titleLink">(default value is: ?)</label></td> 19 for="titleLink">(default value is: ./)</label></td>
20 </tr> 20 </tr>
21 21
22 <tr> 22 <tr>
diff --git a/tpl/vintage/tools.html b/tpl/vintage/tools.html
index 174dc88f..0d8fcdec 100644
--- a/tpl/vintage/tools.html
+++ b/tpl/vintage/tools.html
@@ -5,7 +5,7 @@
5<div id="pageheader"> 5<div id="pageheader">
6 {include="page.header"} 6 {include="page.header"}
7 <div id="toolsdiv"> 7 <div id="toolsdiv">
8 <a href="./?do=configure"><b>Configure your Shaarli</b><span>: Change Title, timezone...</span></a> 8 <a href="./configure"><b>Configure your Shaarli</b><span>: Change Title, timezone...</span></a>
9 <br><br> 9 <br><br>
10 <a href="./?do=pluginadmin"><b>Plugin administration</b><span>: Enable, disable and configure plugins.</span></a> 10 <a href="./?do=pluginadmin"><b>Plugin administration</b><span>: Enable, disable and configure plugins.</span></a>
11 <br><br> 11 <br><br>