Skip to content

Commit

Permalink
Adds ConfigJson which handle the configuration in JSON format.
Browse files Browse the repository at this point in the history
Also use the Updater to make the transition
  • Loading branch information
ArthurHoaro committed Jun 11, 2016
1 parent 684e662 commit b74b96b
Show file tree
Hide file tree
Showing 13 changed files with 462 additions and 25 deletions.
1 change: 1 addition & 0 deletions application/PageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ private function initialize()
$this->tpl->assign('shaarlititle', $conf->get('title', 'Shaarli'));
$this->tpl->assign('openshaarli', $conf->get('config.OPEN_SHAARLI', false));
$this->tpl->assign('showatom', $conf->get('config.SHOW_ATOM', false));
$this->tpl->assign('hide_timestamps', $conf->get('config.HIDE_TIMESTAMPS', false));
// FIXME! Globals
if (!empty($GLOBALS['plugin_errors'])) {
$this->tpl->assign('plugin_errors', $GLOBALS['plugin_errors']);
Expand Down
43 changes: 42 additions & 1 deletion application/Updater.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,48 @@ public function updateMethodRenameDashTags()
$this->linkDB->savedb($conf->get('config.PAGECACHE'));
return true;
}

/**
* Move old configuration in PHP to the new config system in JSON format.
*
* Will rename 'config.php' into 'config.save.php' and create 'config.json'.
*/
public function updateMethodConfigToJson()
{
$conf = ConfigManager::getInstance();

// JSON config already exists, nothing to do.
if ($conf->getConfigIO() instanceof ConfigJson) {
return true;
}

$configPhp = new ConfigPhp();
$configJson = new ConfigJson();
$oldConfig = $configPhp->read($conf::$CONFIG_FILE . '.php');
rename($conf->getConfigFile(), $conf::$CONFIG_FILE . '.save.php');
$conf->setConfigIO($configJson);
$conf->reload();

foreach (ConfigPhp::$ROOT_KEYS as $key) {
$conf->set($key, $oldConfig[$key]);
}

// Set sub config keys (config and plugins)
$subConfig = array('config', 'plugins');
foreach ($subConfig as $sub) {
foreach ($oldConfig[$sub] as $key => $value) {
$conf->set($sub .'.'. $key, $value);
}
}

try{
$conf->write($this->isLoggedIn);
return true;
} catch (IOException $e) {
error_log($e->getMessage());
return false;
}
}
}

/**
Expand Down Expand Up @@ -199,7 +241,6 @@ private function buildMessage($message)
}
}


/**
* Read the updates file, and return already done updates.
*
Expand Down
2 changes: 0 additions & 2 deletions application/config/ConfigIO.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ function read($filepath);
*
* @param string $filepath Config file absolute path.
* @param array $conf All configuration in an array.
*
* @return bool True if the configuration has been successfully written, false otherwise.
*/
function write($filepath, $conf);

Expand Down
66 changes: 66 additions & 0 deletions application/config/ConfigJson.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

/**
* Class ConfigJson (ConfigIO implementation)
*
* Handle Shaarli's JSON configuration file.
*/
class ConfigJson implements ConfigIO
{
/**
* The JSON data is wrapped in a PHP file for security purpose.
* This way, even if the file is accessible, credentials and configuration won't be exposed.
*
* @var string PHP start tag and comment tag.
*/
public static $PHP_HEADER;

public function __construct()
{
// The field can't be initialized directly with concatenation before PHP 5.6.
self::$PHP_HEADER = '<?php /*'. PHP_EOL;
}

/**
* @inheritdoc
*/
function read($filepath)
{
if (! file_exists($filepath) || ! is_readable($filepath)) {
return array();
}
$data = file_get_contents($filepath);
$data = str_replace(self::$PHP_HEADER, '', $data);
$data = json_decode($data, true);
if ($data === null) {
$error = json_last_error();
throw new Exception('An error occured while parsing JSON file: error code #'. $error);
}
return $data;
}

/**
* @inheritdoc
*/
function write($filepath, $conf)
{
// JSON_PRETTY_PRINT is available from PHP 5.4.
$print = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0;
$data = self::$PHP_HEADER . json_encode($conf, $print);
if (!file_put_contents($filepath, $data)) {
throw new IOException(
$filepath,
'Shaarli could not create the config file.
Please make sure Shaarli has the right to write in the folder is it installed in.'
);
}
}

/**
* @inheritdoc
*/
function getExtension()
{
return '.json.php';
}
}
7 changes: 3 additions & 4 deletions application/config/ConfigManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// FIXME! Namespaces...
require_once 'ConfigIO.php';
require_once 'ConfigPhp.php';
#require_once 'ConfigJson.php';
require_once 'ConfigJson.php';

/**
* Class ConfigManager
Expand Down Expand Up @@ -84,12 +84,11 @@ public function reload()
*/
protected function initialize()
{
/*if (! file_exists(self::$CONFIG_FILE .'.php')) {
if (! file_exists(self::$CONFIG_FILE .'.php')) {
$this->configIO = new ConfigJson();
} else {
$this->configIO = new ConfigPhp();
}*/
$this->configIO = new ConfigPhp();
}
$this->load();
}

Expand Down
66 changes: 60 additions & 6 deletions tests/Updater/UpdaterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class UpdaterTest extends PHPUnit_Framework_TestCase
protected static $testDatastore = 'sandbox/datastore.php';

/**
* @var string Config file path.
* @var string Config file path (without extension).
*/
protected static $configFile = 'tests/Updater/config.php';
protected static $configFile = 'tests/utils/config/configUpdater';

/**
* @var ConfigManager
Expand Down Expand Up @@ -52,8 +52,9 @@ public function setUp()
)
);

ConfigManager::$CONFIG_FILE = 'tests/Updater/config';
$this->conf = ConfigManager::getInstance();
ConfigManager::$CONFIG_FILE = self::$configFile;
$this->conf = ConfigManager::reset();
$this->conf->reload();
foreach (self::$configFields as $key => $value) {
$this->conf->set($key, $value);
}
Expand All @@ -67,8 +68,8 @@ public function setUp()
*/
public function tearDown()
{
if (is_file(self::$configFile)) {
unlink(self::$configFile);
if (is_file('tests/Updater/config.json')) {
unlink('tests/Updater/config.json');
}

if (is_file(self::$configFields['config']['DATADIR'] . '/options.php')) {
Expand Down Expand Up @@ -214,6 +215,8 @@ public function testUpdateMergeDeprecatedConfig()
{
// Use writeConfig to create a options.php
ConfigManager::$CONFIG_FILE = 'tests/Updater/options';
$this->conf->setConfigIO(new ConfigPhp());

$invert = !$this->conf->get('privateLinkByDefault');
$this->conf->set('privateLinkByDefault', $invert);
$this->conf->write(true);
Expand All @@ -225,12 +228,15 @@ public function testUpdateMergeDeprecatedConfig()

// merge configs
$updater = new Updater(array(), array(), true);
// This writes a new config file in tests/Updater/config.php
$updater->updateMethodMergeDeprecatedConfigFile();

// make sure updated field is changed
$this->conf->reload();
$this->assertEquals($invert, $this->conf->get('privateLinkByDefault'));
$this->assertFalse(is_file($optionsFile));
// Delete the generated file.
unlink($this->conf->getConfigFile());
}

/**
Expand All @@ -257,4 +263,52 @@ public function testRenameDashTags()
$updater->updateMethodRenameDashTags();
$this->assertNotEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
}

/**
* Convert old PHP config file to JSON config.
*/
public function testConfigToJson()
{
$configFile = 'tests/utils/config/configPhp';
ConfigManager::$CONFIG_FILE = $configFile;
$conf = ConfigManager::reset();

// The ConfigIO is initialized with ConfigPhp.
$this->assertTrue($conf->getConfigIO() instanceof ConfigPhp);

$updater = new Updater(array(), array(), false);
$done = $updater->updateMethodConfigToJson();
$this->assertTrue($done);

// The ConfigIO has been updated to ConfigJson.
$this->assertTrue($conf->getConfigIO() instanceof ConfigJson);
$this->assertTrue(file_exists($conf->getConfigFile()));

// Check JSON config data.
$conf->reload();
$this->assertEquals('root', $conf->get('login'));
$this->assertEquals('lala', $conf->get('redirector'));
$this->assertEquals('data/datastore.php', $conf->get('config.DATASTORE'));
$this->assertEquals('1', $conf->get('plugins.WALLABAG_VERSION'));

rename($configFile . '.save.php', $configFile . '.php');
unlink($conf->getConfigFile());
}

/**
* Launch config conversion update with an existing JSON file => nothing to do.
*/
public function testConfigToJsonNothingToDo()
{
$configFile = 'tests/utils/config/configUpdateDone';
ConfigManager::$CONFIG_FILE = $configFile;
$conf = ConfigManager::reset();
$conf->reload();
$filetime = filemtime($conf->getConfigFile());
$updater = new Updater(array(), array(), false);
$done = $updater->updateMethodConfigToJson();
$this->assertTrue($done);
$expected = filemtime($conf->getConfigFile());
$this->assertEquals($expected, $filetime);
}
}
Loading

1 comment on commit b74b96b

@mro
Copy link

@mro mro commented on b74b96b Jul 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.