aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2016-05-29 12:32:14 +0200
committerArthurHoaro <arthur@hoa.ro>2016-06-11 09:30:56 +0200
commitb74b96bfbd0b778ac50fd17f5e107c51435b1678 (patch)
treefd2debc510c2c51e9b75e2081a31a10e9c02ad06
parent684e662a58b02bde225e44d3677987b6fc3adf0b (diff)
downloadShaarli-b74b96bfbd0b778ac50fd17f5e107c51435b1678.tar.gz
Shaarli-b74b96bfbd0b778ac50fd17f5e107c51435b1678.tar.zst
Shaarli-b74b96bfbd0b778ac50fd17f5e107c51435b1678.zip
Adds ConfigJson which handle the configuration in JSON format.
Also use the Updater to make the transition
-rw-r--r--application/PageBuilder.php1
-rw-r--r--application/Updater.php43
-rw-r--r--application/config/ConfigIO.php2
-rw-r--r--application/config/ConfigJson.php66
-rw-r--r--application/config/ConfigManager.php7
-rw-r--r--tests/Updater/UpdaterTest.php66
-rw-r--r--tests/config/ConfigJsonTest.php125
-rw-r--r--tests/config/ConfigManagerTest.php146
-rw-r--r--tests/utils/config/configInvalid.json.php4
-rw-r--r--tests/utils/config/configJson.json.php19
-rw-r--r--tests/utils/config/configUpdateDone.json.php4
-rw-r--r--tpl/linklist.html2
-rw-r--r--tpl/tools.html2
13 files changed, 462 insertions, 25 deletions
diff --git a/application/PageBuilder.php b/application/PageBuilder.php
index cf13c714..1d3ba9e8 100644
--- a/application/PageBuilder.php
+++ b/application/PageBuilder.php
@@ -75,6 +75,7 @@ class PageBuilder
75 $this->tpl->assign('shaarlititle', $conf->get('title', 'Shaarli')); 75 $this->tpl->assign('shaarlititle', $conf->get('title', 'Shaarli'));
76 $this->tpl->assign('openshaarli', $conf->get('config.OPEN_SHAARLI', false)); 76 $this->tpl->assign('openshaarli', $conf->get('config.OPEN_SHAARLI', false));
77 $this->tpl->assign('showatom', $conf->get('config.SHOW_ATOM', false)); 77 $this->tpl->assign('showatom', $conf->get('config.SHOW_ATOM', false));
78 $this->tpl->assign('hide_timestamps', $conf->get('config.HIDE_TIMESTAMPS', false));
78 // FIXME! Globals 79 // FIXME! Globals
79 if (!empty($GLOBALS['plugin_errors'])) { 80 if (!empty($GLOBALS['plugin_errors'])) {
80 $this->tpl->assign('plugin_errors', $GLOBALS['plugin_errors']); 81 $this->tpl->assign('plugin_errors', $GLOBALS['plugin_errors']);
diff --git a/application/Updater.php b/application/Updater.php
index 6b92af3d..8552850c 100644
--- a/application/Updater.php
+++ b/application/Updater.php
@@ -142,6 +142,48 @@ class Updater
142 $this->linkDB->savedb($conf->get('config.PAGECACHE')); 142 $this->linkDB->savedb($conf->get('config.PAGECACHE'));
143 return true; 143 return true;
144 } 144 }
145
146 /**
147 * Move old configuration in PHP to the new config system in JSON format.
148 *
149 * Will rename 'config.php' into 'config.save.php' and create 'config.json'.
150 */
151 public function updateMethodConfigToJson()
152 {
153 $conf = ConfigManager::getInstance();
154
155 // JSON config already exists, nothing to do.
156 if ($conf->getConfigIO() instanceof ConfigJson) {
157 return true;
158 }
159
160 $configPhp = new ConfigPhp();
161 $configJson = new ConfigJson();
162 $oldConfig = $configPhp->read($conf::$CONFIG_FILE . '.php');
163 rename($conf->getConfigFile(), $conf::$CONFIG_FILE . '.save.php');
164 $conf->setConfigIO($configJson);
165 $conf->reload();
166
167 foreach (ConfigPhp::$ROOT_KEYS as $key) {
168 $conf->set($key, $oldConfig[$key]);
169 }
170
171 // Set sub config keys (config and plugins)
172 $subConfig = array('config', 'plugins');
173 foreach ($subConfig as $sub) {
174 foreach ($oldConfig[$sub] as $key => $value) {
175 $conf->set($sub .'.'. $key, $value);
176 }
177 }
178
179 try{
180 $conf->write($this->isLoggedIn);
181 return true;
182 } catch (IOException $e) {
183 error_log($e->getMessage());
184 return false;
185 }
186 }
145} 187}
146 188
147/** 189/**
@@ -199,7 +241,6 @@ class UpdaterException extends Exception
199 } 241 }
200} 242}
201 243
202
203/** 244/**
204 * Read the updates file, and return already done updates. 245 * Read the updates file, and return already done updates.
205 * 246 *
diff --git a/application/config/ConfigIO.php b/application/config/ConfigIO.php
index 4b1c9901..2b68fe6a 100644
--- a/application/config/ConfigIO.php
+++ b/application/config/ConfigIO.php
@@ -21,8 +21,6 @@ interface ConfigIO
21 * 21 *
22 * @param string $filepath Config file absolute path. 22 * @param string $filepath Config file absolute path.
23 * @param array $conf All configuration in an array. 23 * @param array $conf All configuration in an array.
24 *
25 * @return bool True if the configuration has been successfully written, false otherwise.
26 */ 24 */
27 function write($filepath, $conf); 25 function write($filepath, $conf);
28 26
diff --git a/application/config/ConfigJson.php b/application/config/ConfigJson.php
new file mode 100644
index 00000000..cbafbf6d
--- /dev/null
+++ b/application/config/ConfigJson.php
@@ -0,0 +1,66 @@
1<?php
2
3/**
4 * Class ConfigJson (ConfigIO implementation)
5 *
6 * Handle Shaarli's JSON configuration file.
7 */
8class ConfigJson implements ConfigIO
9{
10 /**
11 * The JSON data is wrapped in a PHP file for security purpose.
12 * This way, even if the file is accessible, credentials and configuration won't be exposed.
13 *
14 * @var string PHP start tag and comment tag.
15 */
16 public static $PHP_HEADER;
17
18 public function __construct()
19 {
20 // The field can't be initialized directly with concatenation before PHP 5.6.
21 self::$PHP_HEADER = '<?php /*'. PHP_EOL;
22 }
23
24 /**
25 * @inheritdoc
26 */
27 function read($filepath)
28 {
29 if (! file_exists($filepath) || ! is_readable($filepath)) {
30 return array();
31 }
32 $data = file_get_contents($filepath);
33 $data = str_replace(self::$PHP_HEADER, '', $data);
34 $data = json_decode($data, true);
35 if ($data === null) {
36 $error = json_last_error();
37 throw new Exception('An error occured while parsing JSON file: error code #'. $error);
38 }
39 return $data;
40 }
41
42 /**
43 * @inheritdoc
44 */
45 function write($filepath, $conf)
46 {
47 // JSON_PRETTY_PRINT is available from PHP 5.4.
48 $print = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
49 $data = self::$PHP_HEADER . json_encode($conf, $print);
50 if (!file_put_contents($filepath, $data)) {
51 throw new IOException(
52 $filepath,
53 'Shaarli could not create the config file.
54 Please make sure Shaarli has the right to write in the folder is it installed in.'
55 );
56 }
57 }
58
59 /**
60 * @inheritdoc
61 */
62 function getExtension()
63 {
64 return '.json.php';
65 }
66}
diff --git a/application/config/ConfigManager.php b/application/config/ConfigManager.php
index 212aac05..70456737 100644
--- a/application/config/ConfigManager.php
+++ b/application/config/ConfigManager.php
@@ -3,7 +3,7 @@
3// FIXME! Namespaces... 3// FIXME! Namespaces...
4require_once 'ConfigIO.php'; 4require_once 'ConfigIO.php';
5require_once 'ConfigPhp.php'; 5require_once 'ConfigPhp.php';
6#require_once 'ConfigJson.php'; 6require_once 'ConfigJson.php';
7 7
8/** 8/**
9 * Class ConfigManager 9 * Class ConfigManager
@@ -84,12 +84,11 @@ class ConfigManager
84 */ 84 */
85 protected function initialize() 85 protected function initialize()
86 { 86 {
87 /*if (! file_exists(self::$CONFIG_FILE .'.php')) { 87 if (! file_exists(self::$CONFIG_FILE .'.php')) {
88 $this->configIO = new ConfigJson(); 88 $this->configIO = new ConfigJson();
89 } else { 89 } else {
90 $this->configIO = new ConfigPhp(); 90 $this->configIO = new ConfigPhp();
91 }*/ 91 }
92 $this->configIO = new ConfigPhp();
93 $this->load(); 92 $this->load();
94 } 93 }
95 94
diff --git a/tests/Updater/UpdaterTest.php b/tests/Updater/UpdaterTest.php
index 8bfb4ba3..f8de2f70 100644
--- a/tests/Updater/UpdaterTest.php
+++ b/tests/Updater/UpdaterTest.php
@@ -20,9 +20,9 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
20 protected static $testDatastore = 'sandbox/datastore.php'; 20 protected static $testDatastore = 'sandbox/datastore.php';
21 21
22 /** 22 /**
23 * @var string Config file path. 23 * @var string Config file path (without extension).
24 */ 24 */
25 protected static $configFile = 'tests/Updater/config.php'; 25 protected static $configFile = 'tests/utils/config/configUpdater';
26 26
27 /** 27 /**
28 * @var ConfigManager 28 * @var ConfigManager
@@ -52,8 +52,9 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
52 ) 52 )
53 ); 53 );
54 54
55 ConfigManager::$CONFIG_FILE = 'tests/Updater/config'; 55 ConfigManager::$CONFIG_FILE = self::$configFile;
56 $this->conf = ConfigManager::getInstance(); 56 $this->conf = ConfigManager::reset();
57 $this->conf->reload();
57 foreach (self::$configFields as $key => $value) { 58 foreach (self::$configFields as $key => $value) {
58 $this->conf->set($key, $value); 59 $this->conf->set($key, $value);
59 } 60 }
@@ -67,8 +68,8 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
67 */ 68 */
68 public function tearDown() 69 public function tearDown()
69 { 70 {
70 if (is_file(self::$configFile)) { 71 if (is_file('tests/Updater/config.json')) {
71 unlink(self::$configFile); 72 unlink('tests/Updater/config.json');
72 } 73 }
73 74
74 if (is_file(self::$configFields['config']['DATADIR'] . '/options.php')) { 75 if (is_file(self::$configFields['config']['DATADIR'] . '/options.php')) {
@@ -214,6 +215,8 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
214 { 215 {
215 // Use writeConfig to create a options.php 216 // Use writeConfig to create a options.php
216 ConfigManager::$CONFIG_FILE = 'tests/Updater/options'; 217 ConfigManager::$CONFIG_FILE = 'tests/Updater/options';
218 $this->conf->setConfigIO(new ConfigPhp());
219
217 $invert = !$this->conf->get('privateLinkByDefault'); 220 $invert = !$this->conf->get('privateLinkByDefault');
218 $this->conf->set('privateLinkByDefault', $invert); 221 $this->conf->set('privateLinkByDefault', $invert);
219 $this->conf->write(true); 222 $this->conf->write(true);
@@ -225,12 +228,15 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
225 228
226 // merge configs 229 // merge configs
227 $updater = new Updater(array(), array(), true); 230 $updater = new Updater(array(), array(), true);
231 // This writes a new config file in tests/Updater/config.php
228 $updater->updateMethodMergeDeprecatedConfigFile(); 232 $updater->updateMethodMergeDeprecatedConfigFile();
229 233
230 // make sure updated field is changed 234 // make sure updated field is changed
231 $this->conf->reload(); 235 $this->conf->reload();
232 $this->assertEquals($invert, $this->conf->get('privateLinkByDefault')); 236 $this->assertEquals($invert, $this->conf->get('privateLinkByDefault'));
233 $this->assertFalse(is_file($optionsFile)); 237 $this->assertFalse(is_file($optionsFile));
238 // Delete the generated file.
239 unlink($this->conf->getConfigFile());
234 } 240 }
235 241
236 /** 242 /**
@@ -257,4 +263,52 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
257 $updater->updateMethodRenameDashTags(); 263 $updater->updateMethodRenameDashTags();
258 $this->assertNotEmpty($linkDB->filterSearch(array('searchtags' => 'exclude'))); 264 $this->assertNotEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
259 } 265 }
266
267 /**
268 * Convert old PHP config file to JSON config.
269 */
270 public function testConfigToJson()
271 {
272 $configFile = 'tests/utils/config/configPhp';
273 ConfigManager::$CONFIG_FILE = $configFile;
274 $conf = ConfigManager::reset();
275
276 // The ConfigIO is initialized with ConfigPhp.
277 $this->assertTrue($conf->getConfigIO() instanceof ConfigPhp);
278
279 $updater = new Updater(array(), array(), false);
280 $done = $updater->updateMethodConfigToJson();
281 $this->assertTrue($done);
282
283 // The ConfigIO has been updated to ConfigJson.
284 $this->assertTrue($conf->getConfigIO() instanceof ConfigJson);
285 $this->assertTrue(file_exists($conf->getConfigFile()));
286
287 // Check JSON config data.
288 $conf->reload();
289 $this->assertEquals('root', $conf->get('login'));
290 $this->assertEquals('lala', $conf->get('redirector'));
291 $this->assertEquals('data/datastore.php', $conf->get('config.DATASTORE'));
292 $this->assertEquals('1', $conf->get('plugins.WALLABAG_VERSION'));
293
294 rename($configFile . '.save.php', $configFile . '.php');
295 unlink($conf->getConfigFile());
296 }
297
298 /**
299 * Launch config conversion update with an existing JSON file => nothing to do.
300 */
301 public function testConfigToJsonNothingToDo()
302 {
303 $configFile = 'tests/utils/config/configUpdateDone';
304 ConfigManager::$CONFIG_FILE = $configFile;
305 $conf = ConfigManager::reset();
306 $conf->reload();
307 $filetime = filemtime($conf->getConfigFile());
308 $updater = new Updater(array(), array(), false);
309 $done = $updater->updateMethodConfigToJson();
310 $this->assertTrue($done);
311 $expected = filemtime($conf->getConfigFile());
312 $this->assertEquals($expected, $filetime);
313 }
260} 314}
diff --git a/tests/config/ConfigJsonTest.php b/tests/config/ConfigJsonTest.php
new file mode 100644
index 00000000..5b3bce46
--- /dev/null
+++ b/tests/config/ConfigJsonTest.php
@@ -0,0 +1,125 @@
1<?php
2
3require_once 'application/config/ConfigJson.php';
4
5/**
6 * Class ConfigJsonTest
7 */
8class ConfigJsonTest extends PHPUnit_Framework_TestCase
9{
10 /**
11 * @var ConfigJson
12 */
13 protected $configIO;
14
15 public function setUp()
16 {
17 $this->configIO = new ConfigJson();
18 }
19
20 /**
21 * Read a simple existing config file.
22 */
23 public function testRead()
24 {
25 $conf = $this->configIO->read('tests/utils/config/configJson.json.php');
26 $this->assertEquals('root', $conf['login']);
27 $this->assertEquals('lala', $conf['redirector']);
28 $this->assertEquals('data/datastore.php', $conf['config']['DATASTORE']);
29 $this->assertEquals('1', $conf['plugins']['WALLABAG_VERSION']);
30 }
31
32 /**
33 * Read a non existent config file -> empty array.
34 */
35 public function testReadNonExistent()
36 {
37 $this->assertEquals(array(), $this->configIO->read('nope'));
38 }
39
40 /**
41 * Read a non existent config file -> empty array.
42 *
43 * @expectedException Exception
44 * @expectedExceptionMessage An error occured while parsing JSON file: error code #4
45 */
46 public function testReadInvalidJson()
47 {
48 $this->configIO->read('tests/utils/config/configInvalid.json.php');
49 }
50
51 /**
52 * Write a new config file.
53 */
54 public function testWriteNew()
55 {
56 $dataFile = 'tests/utils/config/configWrite.json.php';
57 $data = array(
58 'login' => 'root',
59 'redirector' => 'lala',
60 'config' => array(
61 'DATASTORE' => 'data/datastore.php',
62 ),
63 'plugins' => array(
64 'WALLABAG_VERSION' => '1',
65 )
66 );
67 $this->configIO->write($dataFile, $data);
68 // PHP 5.3 doesn't support json pretty print.
69 if (defined('JSON_PRETTY_PRINT')) {
70 $expected = '{
71 "login": "root",
72 "redirector": "lala",
73 "config": {
74 "DATASTORE": "data\/datastore.php"
75 },
76 "plugins": {
77 "WALLABAG_VERSION": "1"
78 }
79}';
80 } else {
81 $expected = '{"login":"root","redirector":"lala","config":{"DATASTORE":"data\/datastore.php"},"plugins":{"WALLABAG_VERSION":"1"}}';
82 }
83 $expected = ConfigJson::$PHP_HEADER . $expected;
84 $this->assertEquals($expected, file_get_contents($dataFile));
85 unlink($dataFile);
86 }
87
88 /**
89 * Overwrite an existing setting.
90 */
91 public function testOverwrite()
92 {
93 $source = 'tests/utils/config/configJson.json.php';
94 $dest = 'tests/utils/config/configOverwrite.json.php';
95 copy($source, $dest);
96 $conf = $this->configIO->read($dest);
97 $conf['redirector'] = 'blabla';
98 $this->configIO->write($dest, $conf);
99 $conf = $this->configIO->read($dest);
100 $this->assertEquals('blabla', $conf['redirector']);
101 unlink($dest);
102 }
103
104 /**
105 * Write to invalid path.
106 *
107 * @expectedException IOException
108 */
109 public function testWriteInvalidArray()
110 {
111 $conf = array('conf' => 'value');
112 @$this->configIO->write(array(), $conf);
113 }
114
115 /**
116 * Write to invalid path.
117 *
118 * @expectedException IOException
119 */
120 public function testWriteInvalidBlank()
121 {
122 $conf = array('conf' => 'value');
123 @$this->configIO->write('', $conf);
124 }
125}
diff --git a/tests/config/ConfigManagerTest.php b/tests/config/ConfigManagerTest.php
index 1b6358f3..7390699c 100644
--- a/tests/config/ConfigManagerTest.php
+++ b/tests/config/ConfigManagerTest.php
@@ -6,7 +6,7 @@
6 * Note: it only test the manager with ConfigJson, 6 * Note: it only test the manager with ConfigJson,
7 * ConfigPhp is only a workaround to handle the transition to JSON type. 7 * ConfigPhp is only a workaround to handle the transition to JSON type.
8 */ 8 */
9class ConfigManagerTest extends \PHPUnit_Framework_TestCase 9class ConfigManagerTest extends PHPUnit_Framework_TestCase
10{ 10{
11 /** 11 /**
12 * @var ConfigManager 12 * @var ConfigManager
@@ -15,28 +15,49 @@ class ConfigManagerTest extends \PHPUnit_Framework_TestCase
15 15
16 public function setUp() 16 public function setUp()
17 { 17 {
18 ConfigManager::$CONFIG_FILE = 'tests/config/config'; 18 ConfigManager::$CONFIG_FILE = 'tests/utils/config/configJson';
19 $this->conf = ConfigManager::getInstance(); 19 $this->conf = ConfigManager::reset();
20 } 20 }
21 21
22 public function tearDown() 22 /**
23 * Simple config test:
24 * 1. Set settings.
25 * 2. Check settings value.
26 */
27 public function testSetGet()
23 { 28 {
24 @unlink($this->conf->getConfigFile()); 29 $this->conf->set('paramInt', 42);
30 $this->conf->set('paramString', 'value1');
31 $this->conf->set('paramBool', false);
32 $this->conf->set('paramArray', array('foo' => 'bar'));
33 $this->conf->set('paramNull', null);
34
35 $this->assertEquals(42, $this->conf->get('paramInt'));
36 $this->assertEquals('value1', $this->conf->get('paramString'));
37 $this->assertFalse($this->conf->get('paramBool'));
38 $this->assertEquals(array('foo' => 'bar'), $this->conf->get('paramArray'));
39 $this->assertEquals(null, $this->conf->get('paramNull'));
25 } 40 }
26 41
42 /**
43 * Set/write/get config test:
44 * 1. Set settings.
45 * 2. Write it to the config file.
46 * 3. Read the file.
47 * 4. Check settings value.
48 */
27 public function testSetWriteGet() 49 public function testSetWriteGet()
28 { 50 {
29 // This won't work with ConfigPhp.
30 $this->markTestIncomplete();
31
32 $this->conf->set('paramInt', 42); 51 $this->conf->set('paramInt', 42);
33 $this->conf->set('paramString', 'value1'); 52 $this->conf->set('paramString', 'value1');
34 $this->conf->set('paramBool', false); 53 $this->conf->set('paramBool', false);
35 $this->conf->set('paramArray', array('foo' => 'bar')); 54 $this->conf->set('paramArray', array('foo' => 'bar'));
36 $this->conf->set('paramNull', null); 55 $this->conf->set('paramNull', null);
37 56
57 ConfigManager::$CONFIG_FILE = 'tests/utils/config/configTmp';
38 $this->conf->write(true); 58 $this->conf->write(true);
39 $this->conf->reload(); 59 $this->conf->reload();
60 unlink($this->conf->getConfigFile());
40 61
41 $this->assertEquals(42, $this->conf->get('paramInt')); 62 $this->assertEquals(42, $this->conf->get('paramInt'));
42 $this->assertEquals('value1', $this->conf->get('paramString')); 63 $this->assertEquals('value1', $this->conf->get('paramString'));
@@ -44,5 +65,110 @@ class ConfigManagerTest extends \PHPUnit_Framework_TestCase
44 $this->assertEquals(array('foo' => 'bar'), $this->conf->get('paramArray')); 65 $this->assertEquals(array('foo' => 'bar'), $this->conf->get('paramArray'));
45 $this->assertEquals(null, $this->conf->get('paramNull')); 66 $this->assertEquals(null, $this->conf->get('paramNull'));
46 } 67 }
47 68
48} \ No newline at end of file 69 /**
70 * Test set/write/get with nested keys.
71 */
72 public function testSetWriteGetNested()
73 {
74 $this->conf->set('foo.bar.key.stuff', 'testSetWriteGetNested');
75
76 ConfigManager::$CONFIG_FILE = 'tests/utils/config/configTmp';
77 $this->conf->write(true);
78 $this->conf->reload();
79 unlink($this->conf->getConfigFile());
80
81 $this->assertEquals('testSetWriteGetNested', $this->conf->get('foo.bar.key.stuff'));
82 }
83
84 /**
85 * Set with an empty key.
86 *
87 * @expectedException Exception
88 * @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*#
89 */
90 public function testSetEmptyKey()
91 {
92 $this->conf->set('', 'stuff');
93 }
94
95 /**
96 * Set with an array key.
97 *
98 * @expectedException Exception
99 * @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*#
100 */
101 public function testSetArrayKey()
102 {
103 $this->conf->set(array('foo' => 'bar'), 'stuff');
104 }
105
106 /**
107 * Try to write the config without mandatory parameter (e.g. 'login').
108 *
109 * @expectedException MissingFieldConfigException
110 */
111 public function testWriteMissingParameter()
112 {
113 ConfigManager::$CONFIG_FILE = 'tests/utils/config/configTmp';
114 $this->assertFalse(file_exists($this->conf->getConfigFile()));
115 $this->conf->reload();
116
117 $this->conf->write(true);
118 }
119
120 /**
121 * Try to get non existent config keys.
122 */
123 public function testGetNonExistent()
124 {
125 $this->assertEquals('', $this->conf->get('nope.test'));
126 $this->assertEquals('default', $this->conf->get('nope.test', 'default'));
127 }
128
129 /**
130 * Test the 'exists' method with existent values.
131 */
132 public function testExistsOk()
133 {
134 $this->assertTrue($this->conf->exists('login'));
135 $this->assertTrue($this->conf->exists('config.foo'));
136 }
137
138 /**
139 * Test the 'exists' method with non existent or invalid values.
140 */
141 public function testExistsKo()
142 {
143 $this->assertFalse($this->conf->exists('nope'));
144 $this->assertFalse($this->conf->exists('nope.nope'));
145 $this->assertFalse($this->conf->exists(''));
146 $this->assertFalse($this->conf->exists(false));
147 }
148
149 /**
150 * Reset the ConfigManager instance.
151 */
152 public function testReset()
153 {
154 $conf = $this->conf;
155 $this->assertTrue($conf === ConfigManager::getInstance());
156 $this->assertFalse($conf === $this->conf->reset());
157 $this->assertFalse($conf === ConfigManager::getInstance());
158 }
159
160 /**
161 * Reload the config from file.
162 */
163 public function testReload()
164 {
165 ConfigManager::$CONFIG_FILE = 'tests/utils/config/configTmp';
166 $newConf = ConfigJson::$PHP_HEADER . '{ "key": "value" }';
167 file_put_contents($this->conf->getConfigFile(), $newConf);
168 $this->conf->reload();
169 unlink($this->conf->getConfigFile());
170 // Previous conf no longer exists, and new values have been loaded.
171 $this->assertFalse($this->conf->exists('login'));
172 $this->assertEquals('value', $this->conf->get('key'));
173 }
174}
diff --git a/tests/utils/config/configInvalid.json.php b/tests/utils/config/configInvalid.json.php
new file mode 100644
index 00000000..c53e471d
--- /dev/null
+++ b/tests/utils/config/configInvalid.json.php
@@ -0,0 +1,4 @@
1<?php /*
2{
3 bad: bad,
4}
diff --git a/tests/utils/config/configJson.json.php b/tests/utils/config/configJson.json.php
new file mode 100644
index 00000000..71b59edd
--- /dev/null
+++ b/tests/utils/config/configJson.json.php
@@ -0,0 +1,19 @@
1<?php /*
2{
3 "redirector":"lala",
4 "login":"root",
5 "hash":"hash",
6 "salt":"salt",
7 "timezone":"Europe\/Paris",
8 "disablesessionprotection":false,
9 "privateLinkByDefault":true,
10 "title": "Shaarli",
11 "titleLink": "?",
12 "config": {
13 "foo": "bar",
14 "DATASTORE": "data\/datastore.php"
15 },
16 "plugins": {
17 "WALLABAG_VERSION": 1
18 }
19}
diff --git a/tests/utils/config/configUpdateDone.json.php b/tests/utils/config/configUpdateDone.json.php
new file mode 100644
index 00000000..a4e460d1
--- /dev/null
+++ b/tests/utils/config/configUpdateDone.json.php
@@ -0,0 +1,4 @@
1<?php /*
2{
3 "login": "root"
4}
diff --git a/tpl/linklist.html b/tpl/linklist.html
index c0d42006..2316f145 100644
--- a/tpl/linklist.html
+++ b/tpl/linklist.html
@@ -88,7 +88,7 @@
88 </span> 88 </span>
89 <br> 89 <br>
90 {if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if} 90 {if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if}
91 {if="!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()"} 91 {if="!$hide_timestamps || isLoggedIn()"}
92 <span class="linkdate" title="Permalink"><a href="?{$value.linkdate|smallHash}">{function="strftime('%c', $value.timestamp)"} - permalink</a> - </span> 92 <span class="linkdate" title="Permalink"><a href="?{$value.linkdate|smallHash}">{function="strftime('%c', $value.timestamp)"} - permalink</a> - </span>
93 {else} 93 {else}
94 <span class="linkdate" title="Short link here"><a href="?{$value.shorturl}">permalink</a> - </span> 94 <span class="linkdate" title="Short link here"><a href="?{$value.shorturl}">permalink</a> - </span>
diff --git a/tpl/tools.html b/tpl/tools.html
index 78b81663..29ade725 100644
--- a/tpl/tools.html
+++ b/tpl/tools.html
@@ -9,7 +9,7 @@
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>
12 {if="!$GLOBALS['config']['OPEN_SHAARLI']"}<a href="?do=changepasswd"><b>Change password</b><span>: Change your password.</span></a> 12 {if="$openshaarli"}<a href="?do=changepasswd"><b>Change password</b><span>: Change your password.</span></a>
13 <br><br>{/if} 13 <br><br>{/if}
14 <a href="?do=changetag"><b>Rename/delete tags</b><span>: Rename or delete a tag in all links</span></a> 14 <a href="?do=changetag"><b>Rename/delete tags</b><span>: Rename or delete a tag in all links</span></a>
15 <br><br> 15 <br><br>