Process configure page through Slim controller
This commit is contained in:
parent
465033230d
commit
66063ed1a1
12 changed files with 427 additions and 105 deletions
120
application/front/controller/admin/ConfigureController.php
Normal file
120
application/front/controller/admin/ConfigureController.php
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shaarli\Front\Controller\Admin;
|
||||||
|
|
||||||
|
use Shaarli\Languages;
|
||||||
|
use Shaarli\Render\ThemeUtils;
|
||||||
|
use Shaarli\Thumbnailer;
|
||||||
|
use Slim\Http\Request;
|
||||||
|
use Slim\Http\Response;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PasswordController
|
||||||
|
*
|
||||||
|
* Slim controller used to handle Shaarli configuration page (display + save new config).
|
||||||
|
*/
|
||||||
|
class ConfigureController extends ShaarliAdminController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* GET /configure - Displays the configuration page
|
||||||
|
*/
|
||||||
|
public function index(Request $request, Response $response): Response
|
||||||
|
{
|
||||||
|
$this->assignView('title', $this->container->conf->get('general.title', 'Shaarli'));
|
||||||
|
$this->assignView('theme', $this->container->conf->get('resource.theme'));
|
||||||
|
$this->assignView(
|
||||||
|
'theme_available',
|
||||||
|
ThemeUtils::getThemes($this->container->conf->get('resource.raintpl_tpl'))
|
||||||
|
);
|
||||||
|
$this->assignView('formatter_available', ['default', 'markdown']);
|
||||||
|
list($continents, $cities) = generateTimeZoneData(
|
||||||
|
timezone_identifiers_list(),
|
||||||
|
$this->container->conf->get('general.timezone')
|
||||||
|
);
|
||||||
|
$this->assignView('continents', $continents);
|
||||||
|
$this->assignView('cities', $cities);
|
||||||
|
$this->assignView('retrieve_description', $this->container->conf->get('general.retrieve_description', false));
|
||||||
|
$this->assignView('private_links_default', $this->container->conf->get('privacy.default_private_links', false));
|
||||||
|
$this->assignView(
|
||||||
|
'session_protection_disabled',
|
||||||
|
$this->container->conf->get('security.session_protection_disabled', false)
|
||||||
|
);
|
||||||
|
$this->assignView('enable_rss_permalinks', $this->container->conf->get('feed.rss_permalinks', false));
|
||||||
|
$this->assignView('enable_update_check', $this->container->conf->get('updates.check_updates', true));
|
||||||
|
$this->assignView('hide_public_links', $this->container->conf->get('privacy.hide_public_links', false));
|
||||||
|
$this->assignView('api_enabled', $this->container->conf->get('api.enabled', true));
|
||||||
|
$this->assignView('api_secret', $this->container->conf->get('api.secret'));
|
||||||
|
$this->assignView('languages', Languages::getAvailableLanguages());
|
||||||
|
$this->assignView('gd_enabled', extension_loaded('gd'));
|
||||||
|
$this->assignView('thumbnails_mode', $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE));
|
||||||
|
$this->assignView('pagetitle', t('Configure') .' - '. $this->container->conf->get('general.title', 'Shaarli'));
|
||||||
|
|
||||||
|
return $response->write($this->render('configure'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /configure - Update Shaarli's configuration
|
||||||
|
*/
|
||||||
|
public function save(Request $request, Response $response): Response
|
||||||
|
{
|
||||||
|
$this->checkToken($request);
|
||||||
|
|
||||||
|
$continent = $request->getParam('continent');
|
||||||
|
$city = $request->getParam('city');
|
||||||
|
$tz = 'UTC';
|
||||||
|
if (null !== $continent && null !== $city && isTimeZoneValid($continent, $city)) {
|
||||||
|
$tz = $continent . '/' . $city;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->container->conf->set('general.timezone', $tz);
|
||||||
|
$this->container->conf->set('general.title', escape($request->getParam('title')));
|
||||||
|
$this->container->conf->set('general.header_link', escape($request->getParam('titleLink')));
|
||||||
|
$this->container->conf->set('general.retrieve_description', !empty($request->getParam('retrieveDescription')));
|
||||||
|
$this->container->conf->set('resource.theme', escape($request->getParam('theme')));
|
||||||
|
$this->container->conf->set(
|
||||||
|
'security.session_protection_disabled',
|
||||||
|
!empty($request->getParam('disablesessionprotection'))
|
||||||
|
);
|
||||||
|
$this->container->conf->set(
|
||||||
|
'privacy.default_private_links',
|
||||||
|
!empty($request->getParam('privateLinkByDefault'))
|
||||||
|
);
|
||||||
|
$this->container->conf->set('feed.rss_permalinks', !empty($request->getParam('enableRssPermalinks')));
|
||||||
|
$this->container->conf->set('updates.check_updates', !empty($request->getParam('updateCheck')));
|
||||||
|
$this->container->conf->set('privacy.hide_public_links', !empty($request->getParam('hidePublicLinks')));
|
||||||
|
$this->container->conf->set('api.enabled', !empty($request->getParam('enableApi')));
|
||||||
|
$this->container->conf->set('api.secret', escape($request->getParam('apiSecret')));
|
||||||
|
$this->container->conf->set('formatter', escape($request->getParam('formatter')));
|
||||||
|
|
||||||
|
if (!empty($request->getParam('language'))) {
|
||||||
|
$this->container->conf->set('translation.language', escape($request->getParam('language')));
|
||||||
|
}
|
||||||
|
|
||||||
|
$thumbnailsMode = extension_loaded('gd') ? $request->getParam('enableThumbnails') : Thumbnailer::MODE_NONE;
|
||||||
|
if ($thumbnailsMode !== Thumbnailer::MODE_NONE
|
||||||
|
&& $thumbnailsMode !== $this->container->conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
|
||||||
|
) {
|
||||||
|
$this->saveWarningMessage(t(
|
||||||
|
'You have enabled or changed thumbnails mode. '
|
||||||
|
.'<a href="./?do=thumbs_update">Please synchronize them</a>.'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
$this->container->conf->set('thumbnails.mode', $thumbnailsMode);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->container->conf->write($this->container->loginManager->isLoggedIn());
|
||||||
|
$this->container->history->updateSettings();
|
||||||
|
$this->container->pageCacheManager->invalidateCaches();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
// TODO: translation + stacktrace
|
||||||
|
$this->saveErrorMessage('ERROR while writing config file after configuration update.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->saveSuccessMessage(t('Configuration was saved.'));
|
||||||
|
|
||||||
|
return $response->withRedirect('./configure');
|
||||||
|
}
|
||||||
|
}
|
|
@ -143,6 +143,10 @@ private function initialize()
|
||||||
$this->tpl->assign('conf', $this->conf);
|
$this->tpl->assign('conf', $this->conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affect variable after controller processing.
|
||||||
|
* Used for alert messages.
|
||||||
|
*/
|
||||||
protected function finalize(): void
|
protected function finalize(): void
|
||||||
{
|
{
|
||||||
// TODO: use the SessionManager
|
// TODO: use the SessionManager
|
||||||
|
|
|
@ -35,7 +35,7 @@ http://<replace_domain>/?nonope
|
||||||
http://<replace_domain>/?do=addlink
|
http://<replace_domain>/?do=addlink
|
||||||
http://<replace_domain>/?do=changepasswd
|
http://<replace_domain>/?do=changepasswd
|
||||||
http://<replace_domain>/?do=changetag
|
http://<replace_domain>/?do=changetag
|
||||||
http://<replace_domain>/?do=configure
|
http://<replace_domain>/configure
|
||||||
http://<replace_domain>/tools
|
http://<replace_domain>/tools
|
||||||
http://<replace_domain>/daily
|
http://<replace_domain>/daily
|
||||||
http://<replace_domain>/?post
|
http://<replace_domain>/?post
|
||||||
|
|
84
index.php
84
index.php
|
@ -513,89 +513,9 @@ function renderPage($conf, $pluginManager, $bookmarkService, $history, $sessionM
|
||||||
|
|
||||||
// -------- User wants to change configuration
|
// -------- User wants to change configuration
|
||||||
if ($targetPage == Router::$PAGE_CONFIGURE) {
|
if ($targetPage == Router::$PAGE_CONFIGURE) {
|
||||||
if (!empty($_POST['title'])) {
|
header('Location: ./configure');
|
||||||
if (!$sessionManager->checkToken($_POST['token'])) {
|
|
||||||
die(t('Wrong token.')); // Go away!
|
|
||||||
}
|
|
||||||
$tz = 'UTC';
|
|
||||||
if (!empty($_POST['continent']) && !empty($_POST['city'])
|
|
||||||
&& isTimeZoneValid($_POST['continent'], $_POST['city'])
|
|
||||||
) {
|
|
||||||
$tz = $_POST['continent'] . '/' . $_POST['city'];
|
|
||||||
}
|
|
||||||
$conf->set('general.timezone', $tz);
|
|
||||||
$conf->set('general.title', escape($_POST['title']));
|
|
||||||
$conf->set('general.header_link', escape($_POST['titleLink']));
|
|
||||||
$conf->set('general.retrieve_description', !empty($_POST['retrieveDescription']));
|
|
||||||
$conf->set('resource.theme', escape($_POST['theme']));
|
|
||||||
$conf->set('security.session_protection_disabled', !empty($_POST['disablesessionprotection']));
|
|
||||||
$conf->set('privacy.default_private_links', !empty($_POST['privateLinkByDefault']));
|
|
||||||
$conf->set('feed.rss_permalinks', !empty($_POST['enableRssPermalinks']));
|
|
||||||
$conf->set('updates.check_updates', !empty($_POST['updateCheck']));
|
|
||||||
$conf->set('privacy.hide_public_links', !empty($_POST['hidePublicLinks']));
|
|
||||||
$conf->set('api.enabled', !empty($_POST['enableApi']));
|
|
||||||
$conf->set('api.secret', escape($_POST['apiSecret']));
|
|
||||||
$conf->set('formatter', escape($_POST['formatter']));
|
|
||||||
|
|
||||||
if (! empty($_POST['language'])) {
|
|
||||||
$conf->set('translation.language', escape($_POST['language']));
|
|
||||||
}
|
|
||||||
|
|
||||||
$thumbnailsMode = extension_loaded('gd') ? $_POST['enableThumbnails'] : Thumbnailer::MODE_NONE;
|
|
||||||
if ($thumbnailsMode !== Thumbnailer::MODE_NONE
|
|
||||||
&& $thumbnailsMode !== $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE)
|
|
||||||
) {
|
|
||||||
$_SESSION['warnings'][] = t(
|
|
||||||
'You have enabled or changed thumbnails mode. '
|
|
||||||
.'<a href="./?do=thumbs_update">Please synchronize them</a>.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$conf->set('thumbnails.mode', $thumbnailsMode);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$conf->write($loginManager->isLoggedIn());
|
|
||||||
$history->updateSettings();
|
|
||||||
$pageCacheManager->invalidateCaches();
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log(
|
|
||||||
'ERROR while writing config file after configuration update.' . PHP_EOL .
|
|
||||||
$e->getMessage()
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: do not handle exceptions/errors in JS.
|
|
||||||
echo '<script>alert("'. $e->getMessage() .'");document.location=\'./?do=configure\';</script>';
|
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
echo '<script>alert("'. t('Configuration was saved.') .'");document.location=\'./?do=configure\';</script>';
|
|
||||||
exit;
|
|
||||||
} else {
|
|
||||||
// Show the configuration form.
|
|
||||||
$PAGE->assign('title', $conf->get('general.title'));
|
|
||||||
$PAGE->assign('theme', $conf->get('resource.theme'));
|
|
||||||
$PAGE->assign('theme_available', ThemeUtils::getThemes($conf->get('resource.raintpl_tpl')));
|
|
||||||
$PAGE->assign('formatter_available', ['default', 'markdown']);
|
|
||||||
list($continents, $cities) = generateTimeZoneData(
|
|
||||||
timezone_identifiers_list(),
|
|
||||||
$conf->get('general.timezone')
|
|
||||||
);
|
|
||||||
$PAGE->assign('continents', $continents);
|
|
||||||
$PAGE->assign('cities', $cities);
|
|
||||||
$PAGE->assign('retrieve_description', $conf->get('general.retrieve_description'));
|
|
||||||
$PAGE->assign('private_links_default', $conf->get('privacy.default_private_links', false));
|
|
||||||
$PAGE->assign('session_protection_disabled', $conf->get('security.session_protection_disabled', false));
|
|
||||||
$PAGE->assign('enable_rss_permalinks', $conf->get('feed.rss_permalinks', false));
|
|
||||||
$PAGE->assign('enable_update_check', $conf->get('updates.check_updates', true));
|
|
||||||
$PAGE->assign('hide_public_links', $conf->get('privacy.hide_public_links', false));
|
|
||||||
$PAGE->assign('api_enabled', $conf->get('api.enabled', true));
|
|
||||||
$PAGE->assign('api_secret', $conf->get('api.secret'));
|
|
||||||
$PAGE->assign('languages', Languages::getAvailableLanguages());
|
|
||||||
$PAGE->assign('gd_enabled', extension_loaded('gd'));
|
|
||||||
$PAGE->assign('thumbnails_mode', $conf->get('thumbnails.mode', Thumbnailer::MODE_NONE));
|
|
||||||
$PAGE->assign('pagetitle', t('Configure') .' - '. $conf->get('general.title', 'Shaarli'));
|
|
||||||
$PAGE->renderPage('configure');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------- User wants to rename a tag or delete it
|
// -------- User wants to rename a tag or delete it
|
||||||
if ($targetPage == Router::$PAGE_CHANGETAG) {
|
if ($targetPage == Router::$PAGE_CHANGETAG) {
|
||||||
|
@ -1458,6 +1378,8 @@ function install($conf, $sessionManager, $loginManager)
|
||||||
$this->get('/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index')->setName('tools');
|
$this->get('/tools', '\Shaarli\Front\Controller\Admin\ToolsController:index')->setName('tools');
|
||||||
$this->get('/password', '\Shaarli\Front\Controller\Admin\PasswordController:index')->setName('password');
|
$this->get('/password', '\Shaarli\Front\Controller\Admin\PasswordController:index')->setName('password');
|
||||||
$this->post('/password', '\Shaarli\Front\Controller\Admin\PasswordController:change')->setName('changePassword');
|
$this->post('/password', '\Shaarli\Front\Controller\Admin\PasswordController:change')->setName('changePassword');
|
||||||
|
$this->get('/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:index')->setName('configure');
|
||||||
|
$this->post('/configure', '\Shaarli\Front\Controller\Admin\ConfigureController:save')->setName('saveConfigure');
|
||||||
|
|
||||||
$this
|
$this
|
||||||
->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage')
|
->get('/links-per-page', '\Shaarli\Front\Controller\Admin\SessionFilterController:linksPerPage')
|
||||||
|
|
252
tests/front/controller/admin/ConfigureControllerTest.php
Normal file
252
tests/front/controller/admin/ConfigureControllerTest.php
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Shaarli\Front\Controller\Admin;
|
||||||
|
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Shaarli\Config\ConfigManager;
|
||||||
|
use Shaarli\Front\Exception\WrongTokenException;
|
||||||
|
use Shaarli\Security\SessionManager;
|
||||||
|
use Shaarli\Thumbnailer;
|
||||||
|
use Slim\Http\Request;
|
||||||
|
use Slim\Http\Response;
|
||||||
|
|
||||||
|
class ConfigureControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
use FrontAdminControllerMockHelper;
|
||||||
|
|
||||||
|
/** @var ConfigureController */
|
||||||
|
protected $controller;
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->createContainer();
|
||||||
|
|
||||||
|
$this->controller = new ConfigureController($this->container);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test displaying configure page - it should display all config variables
|
||||||
|
*/
|
||||||
|
public function testIndex(): void
|
||||||
|
{
|
||||||
|
$assignedVariables = [];
|
||||||
|
$this->assignTemplateVars($assignedVariables);
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$this->container->conf = $this->createMock(ConfigManager::class);
|
||||||
|
$this->container->conf->method('get')->willReturnCallback(function (string $key) {
|
||||||
|
return $key;
|
||||||
|
});
|
||||||
|
|
||||||
|
$result = $this->controller->index($request, $response);
|
||||||
|
|
||||||
|
static::assertSame(200, $result->getStatusCode());
|
||||||
|
static::assertSame('configure', (string) $result->getBody());
|
||||||
|
|
||||||
|
static::assertSame('Configure - general.title', $assignedVariables['pagetitle']);
|
||||||
|
static::assertSame('general.title', $assignedVariables['title']);
|
||||||
|
static::assertSame('resource.theme', $assignedVariables['theme']);
|
||||||
|
static::assertEmpty($assignedVariables['theme_available']);
|
||||||
|
static::assertSame(['default', 'markdown'], $assignedVariables['formatter_available']);
|
||||||
|
static::assertNotEmpty($assignedVariables['continents']);
|
||||||
|
static::assertNotEmpty($assignedVariables['cities']);
|
||||||
|
static::assertSame('general.retrieve_description', $assignedVariables['retrieve_description']);
|
||||||
|
static::assertSame('privacy.default_private_links', $assignedVariables['private_links_default']);
|
||||||
|
static::assertSame('security.session_protection_disabled', $assignedVariables['session_protection_disabled']);
|
||||||
|
static::assertSame('feed.rss_permalinks', $assignedVariables['enable_rss_permalinks']);
|
||||||
|
static::assertSame('updates.check_updates', $assignedVariables['enable_update_check']);
|
||||||
|
static::assertSame('privacy.hide_public_links', $assignedVariables['hide_public_links']);
|
||||||
|
static::assertSame('api.enabled', $assignedVariables['api_enabled']);
|
||||||
|
static::assertSame('api.secret', $assignedVariables['api_secret']);
|
||||||
|
static::assertCount(4, $assignedVariables['languages']);
|
||||||
|
static::assertArrayHasKey('gd_enabled', $assignedVariables);
|
||||||
|
static::assertSame('thumbnails.mode', $assignedVariables['thumbnails_mode']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test posting a new config - make sure that everything is saved properly, without errors.
|
||||||
|
*/
|
||||||
|
public function testSaveNewConfig(): void
|
||||||
|
{
|
||||||
|
$session = [];
|
||||||
|
$this->assignSessionVars($session);
|
||||||
|
|
||||||
|
$parameters = [
|
||||||
|
'token' => 'token',
|
||||||
|
'continent' => 'Europe',
|
||||||
|
'city' => 'Moscow',
|
||||||
|
'title' => 'Shaarli',
|
||||||
|
'titleLink' => './',
|
||||||
|
'retrieveDescription' => 'on',
|
||||||
|
'theme' => 'vintage',
|
||||||
|
'disablesessionprotection' => null,
|
||||||
|
'privateLinkByDefault' => true,
|
||||||
|
'enableRssPermalinks' => true,
|
||||||
|
'updateCheck' => false,
|
||||||
|
'hidePublicLinks' => 'on',
|
||||||
|
'enableApi' => 'on',
|
||||||
|
'apiSecret' => 'abcdef',
|
||||||
|
'formatter' => 'markdown',
|
||||||
|
'language' => 'fr',
|
||||||
|
'enableThumbnails' => Thumbnailer::MODE_NONE,
|
||||||
|
];
|
||||||
|
|
||||||
|
$parametersConfigMapping = [
|
||||||
|
'general.timezone' => $parameters['continent'] . '/' . $parameters['city'],
|
||||||
|
'general.title' => $parameters['title'],
|
||||||
|
'general.header_link' => $parameters['titleLink'],
|
||||||
|
'general.retrieve_description' => !!$parameters['retrieveDescription'],
|
||||||
|
'resource.theme' => $parameters['theme'],
|
||||||
|
'security.session_protection_disabled' => !!$parameters['disablesessionprotection'],
|
||||||
|
'privacy.default_private_links' => !!$parameters['privateLinkByDefault'],
|
||||||
|
'feed.rss_permalinks' => !!$parameters['enableRssPermalinks'],
|
||||||
|
'updates.check_updates' => !!$parameters['updateCheck'],
|
||||||
|
'privacy.hide_public_links' => !!$parameters['hidePublicLinks'],
|
||||||
|
'api.enabled' => !!$parameters['enableApi'],
|
||||||
|
'api.secret' => $parameters['apiSecret'],
|
||||||
|
'formatter' => $parameters['formatter'],
|
||||||
|
'translation.language' => $parameters['language'],
|
||||||
|
'thumbnails.mode' => $parameters['enableThumbnails'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$request
|
||||||
|
->expects(static::atLeastOnce())
|
||||||
|
->method('getParam')->willReturnCallback(function (string $key) use ($parameters) {
|
||||||
|
if (false === array_key_exists($key, $parameters)) {
|
||||||
|
static::fail('unknown key: ' . $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parameters[$key];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$this->container->conf = $this->createMock(ConfigManager::class);
|
||||||
|
$this->container->conf
|
||||||
|
->expects(static::atLeastOnce())
|
||||||
|
->method('set')
|
||||||
|
->willReturnCallback(function (string $key, $value) use ($parametersConfigMapping): void {
|
||||||
|
if (false === array_key_exists($key, $parametersConfigMapping)) {
|
||||||
|
static::fail('unknown key: ' . $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static::assertSame($parametersConfigMapping[$key], $value);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = $this->controller->save($request, $response);
|
||||||
|
static::assertSame(302, $result->getStatusCode());
|
||||||
|
static::assertSame(['./configure'], $result->getHeader('Location'));
|
||||||
|
|
||||||
|
static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
|
||||||
|
static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
|
||||||
|
static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
|
||||||
|
static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test posting a new config - wrong token.
|
||||||
|
*/
|
||||||
|
public function testSaveNewConfigWrongToken(): void
|
||||||
|
{
|
||||||
|
$this->container->sessionManager = $this->createMock(SessionManager::class);
|
||||||
|
$this->container->sessionManager->method('checkToken')->willReturn(false);
|
||||||
|
|
||||||
|
$this->container->conf->expects(static::never())->method('set');
|
||||||
|
$this->container->conf->expects(static::never())->method('write');
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$this->expectException(WrongTokenException::class);
|
||||||
|
|
||||||
|
$this->controller->save($request, $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test posting a new config - thumbnail activation.
|
||||||
|
*/
|
||||||
|
public function testSaveNewConfigThumbnailsActivation(): void
|
||||||
|
{
|
||||||
|
$session = [];
|
||||||
|
$this->assignSessionVars($session);
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$request
|
||||||
|
->expects(static::atLeastOnce())
|
||||||
|
->method('getParam')->willReturnCallback(function (string $key) {
|
||||||
|
if ('enableThumbnails' === $key) {
|
||||||
|
return Thumbnailer::MODE_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $key;
|
||||||
|
})
|
||||||
|
;
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$result = $this->controller->save($request, $response);
|
||||||
|
|
||||||
|
static::assertSame(302, $result->getStatusCode());
|
||||||
|
static::assertSame(['./configure'], $result->getHeader('Location'));
|
||||||
|
|
||||||
|
static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
|
||||||
|
static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
|
||||||
|
static::assertStringContainsString(
|
||||||
|
'You have enabled or changed thumbnails mode',
|
||||||
|
$session[SessionManager::KEY_WARNING_MESSAGES][0]
|
||||||
|
);
|
||||||
|
static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
|
||||||
|
static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test posting a new config - thumbnail activation.
|
||||||
|
*/
|
||||||
|
public function testSaveNewConfigThumbnailsAlreadyActive(): void
|
||||||
|
{
|
||||||
|
$session = [];
|
||||||
|
$this->assignSessionVars($session);
|
||||||
|
|
||||||
|
$request = $this->createMock(Request::class);
|
||||||
|
$request
|
||||||
|
->expects(static::atLeastOnce())
|
||||||
|
->method('getParam')->willReturnCallback(function (string $key) {
|
||||||
|
if ('enableThumbnails' === $key) {
|
||||||
|
return Thumbnailer::MODE_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $key;
|
||||||
|
})
|
||||||
|
;
|
||||||
|
$response = new Response();
|
||||||
|
|
||||||
|
$this->container->conf = $this->createMock(ConfigManager::class);
|
||||||
|
$this->container->conf
|
||||||
|
->expects(static::atLeastOnce())
|
||||||
|
->method('get')
|
||||||
|
->willReturnCallback(function (string $key): string {
|
||||||
|
if ('thumbnails.mode' === $key) {
|
||||||
|
return Thumbnailer::MODE_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $key;
|
||||||
|
})
|
||||||
|
;
|
||||||
|
|
||||||
|
$result = $this->controller->save($request, $response);
|
||||||
|
|
||||||
|
static::assertSame(302, $result->getStatusCode());
|
||||||
|
static::assertSame(['./configure'], $result->getHeader('Location'));
|
||||||
|
|
||||||
|
static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
|
||||||
|
static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
|
||||||
|
static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
|
||||||
|
static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use Shaarli\Container\ShaarliTestContainer;
|
use Shaarli\Container\ShaarliTestContainer;
|
||||||
use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper;
|
use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper;
|
||||||
|
use Shaarli\History;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trait FrontControllerMockHelper
|
* Trait FrontControllerMockHelper
|
||||||
|
@ -27,7 +28,29 @@ protected function createContainer(): void
|
||||||
{
|
{
|
||||||
$this->parentCreateContainer();
|
$this->parentCreateContainer();
|
||||||
|
|
||||||
|
$this->container->history = $this->createMock(History::class);
|
||||||
|
|
||||||
$this->container->loginManager->method('isLoggedIn')->willReturn(true);
|
$this->container->loginManager->method('isLoggedIn')->willReturn(true);
|
||||||
$this->container->sessionManager->method('checkToken')->willReturn(true);
|
$this->container->sessionManager->method('checkToken')->willReturn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass a reference of an array which will be populated by `sessionManager->setSessionParameter`
|
||||||
|
* calls during execution.
|
||||||
|
*
|
||||||
|
* @param mixed $variables Array reference to populate.
|
||||||
|
*/
|
||||||
|
protected function assignSessionVars(array &$variables): void
|
||||||
|
{
|
||||||
|
$this->container->sessionManager
|
||||||
|
->expects(static::atLeastOnce())
|
||||||
|
->method('setSessionParameter')
|
||||||
|
->willReturnCallback(function ($key, $value) use (&$variables) {
|
||||||
|
$variables[$key] = $value;
|
||||||
|
|
||||||
|
return $this->container->sessionManager;
|
||||||
|
})
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,20 +57,20 @@ public function testValidIndexControllerInvokeDefault(): void
|
||||||
(new Bookmark())
|
(new Bookmark())
|
||||||
->setId(1)
|
->setId(1)
|
||||||
->setUrl('http://url.tld')
|
->setUrl('http://url.tld')
|
||||||
->setTitle(static::generateContent(50))
|
->setTitle(static::generateString(50))
|
||||||
->setDescription(static::generateContent(500))
|
->setDescription(static::generateString(500))
|
||||||
,
|
,
|
||||||
(new Bookmark())
|
(new Bookmark())
|
||||||
->setId(2)
|
->setId(2)
|
||||||
->setUrl('http://url2.tld')
|
->setUrl('http://url2.tld')
|
||||||
->setTitle(static::generateContent(50))
|
->setTitle(static::generateString(50))
|
||||||
->setDescription(static::generateContent(500))
|
->setDescription(static::generateString(500))
|
||||||
,
|
,
|
||||||
(new Bookmark())
|
(new Bookmark())
|
||||||
->setId(3)
|
->setId(3)
|
||||||
->setUrl('http://url3.tld')
|
->setUrl('http://url3.tld')
|
||||||
->setTitle(static::generateContent(50))
|
->setTitle(static::generateString(50))
|
||||||
->setDescription(static::generateContent(500))
|
->setDescription(static::generateString(500))
|
||||||
,
|
,
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
|
@ -194,8 +194,8 @@ public function testValidIndexControllerInvokeNoFutureOrPast(): void
|
||||||
(new Bookmark())
|
(new Bookmark())
|
||||||
->setId(1)
|
->setId(1)
|
||||||
->setUrl('http://url.tld')
|
->setUrl('http://url.tld')
|
||||||
->setTitle(static::generateContent(50))
|
->setTitle(static::generateString(50))
|
||||||
->setDescription(static::generateContent(500))
|
->setDescription(static::generateString(500))
|
||||||
,
|
,
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
|
@ -267,8 +267,8 @@ public function testValidIndexControllerInvokeHeightAdjustment(): void
|
||||||
(new Bookmark())
|
(new Bookmark())
|
||||||
->setId(2)
|
->setId(2)
|
||||||
->setUrl('http://url.tld')
|
->setUrl('http://url.tld')
|
||||||
->setTitle(static::generateContent(50))
|
->setTitle(static::generateString(50))
|
||||||
->setDescription(static::generateContent(5000))
|
->setDescription(static::generateString(5000))
|
||||||
,
|
,
|
||||||
(new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'),
|
(new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'),
|
||||||
(new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'),
|
(new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'),
|
||||||
|
@ -473,11 +473,4 @@ public function testValidRssControllerInvokeNoBookmark(): void
|
||||||
static::assertFalse($assignedVariables['hide_timestamps']);
|
static::assertFalse($assignedVariables['hide_timestamps']);
|
||||||
static::assertCount(0, $assignedVariables['days']);
|
static::assertCount(0, $assignedVariables['days']);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function generateContent(int $length): string
|
|
||||||
{
|
|
||||||
// bin2hex(random_bytes) generates string twice as long as given parameter
|
|
||||||
$length = (int) ceil($length / 2);
|
|
||||||
return bin2hex(random_bytes($length));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ protected function createContainer(): void
|
||||||
// Config
|
// Config
|
||||||
$this->container->conf = $this->createMock(ConfigManager::class);
|
$this->container->conf = $this->createMock(ConfigManager::class);
|
||||||
$this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) {
|
$this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) {
|
||||||
return $default;
|
return $default === null ? $parameter : $default;
|
||||||
});
|
});
|
||||||
|
|
||||||
// PageBuilder
|
// PageBuilder
|
||||||
|
@ -101,6 +101,14 @@ protected function assignTemplateVars(array &$variables): void
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static function generateString(int $length): string
|
||||||
|
{
|
||||||
|
// bin2hex(random_bytes) generates string twice as long as given parameter
|
||||||
|
$length = (int) ceil($length / 2);
|
||||||
|
|
||||||
|
return bin2hex(random_bytes($length));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force to be used in PHPUnit context.
|
* Force to be used in PHPUnit context.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -35,7 +35,7 @@ <h2 class="window-title">{'Configure'|t}</h2>
|
||||||
<div class="form-label">
|
<div class="form-label">
|
||||||
<label for="titleLink">
|
<label for="titleLink">
|
||||||
<span class="label-name">{'Home link'|t}</span><br>
|
<span class="label-name">{'Home link'|t}</span><br>
|
||||||
<span class="label-desc">{'Default value'|t}: ?</span>
|
<span class="label-desc">{'Default value'|t}: ./</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<div class="pure-u-lg-1-3 pure-u-22-24 page-form page-form-light">
|
<div class="pure-u-lg-1-3 pure-u-22-24 page-form page-form-light">
|
||||||
<h2 class="window-title">{'Settings'|t}</h2>
|
<h2 class="window-title">{'Settings'|t}</h2>
|
||||||
<div class="tools-item">
|
<div class="tools-item">
|
||||||
<a href="./?do=configure" title="{'Change Shaarli settings: title, timezone, etc.'|t}">
|
<a href="./configure" title="{'Change Shaarli settings: title, timezone, etc.'|t}">
|
||||||
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Configure your Shaarli'|t}</span>
|
<span class="pure-button pure-u-lg-2-3 pure-u-3-4">{'Configure your Shaarli'|t}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>Home link:</b></td>
|
<td><b>Home link:</b></td>
|
||||||
<td><input type="text" name="titleLink" id="titleLink" size="50" value="{$titleLink}"><br/><label
|
<td><input type="text" name="titleLink" id="titleLink" size="50" value="{$titleLink}"><br/><label
|
||||||
for="titleLink">(default value is: ?)</label></td>
|
for="titleLink">(default value is: ./)</label></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div id="pageheader">
|
<div id="pageheader">
|
||||||
{include="page.header"}
|
{include="page.header"}
|
||||||
<div id="toolsdiv">
|
<div id="toolsdiv">
|
||||||
<a href="./?do=configure"><b>Configure your Shaarli</b><span>: Change Title, timezone...</span></a>
|
<a href="./configure"><b>Configure your Shaarli</b><span>: Change Title, timezone...</span></a>
|
||||||
<br><br>
|
<br><br>
|
||||||
<a href="./?do=pluginadmin"><b>Plugin administration</b><span>: Enable, disable and configure plugins.</span></a>
|
<a href="./?do=pluginadmin"><b>Plugin administration</b><span>: Enable, disable and configure plugins.</span></a>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
Loading…
Reference in a new issue