Merge pull request #570 from ArthurHoaro/config-manager
Introduce a configuration manager
This commit is contained in:
commit
649af5b501
41 changed files with 2099 additions and 1133 deletions
|
@ -132,11 +132,11 @@ public static function checkPHPVersion($minVersion, $curVersion)
|
||||||
/**
|
/**
|
||||||
* Checks Shaarli has the proper access permissions to its resources
|
* Checks Shaarli has the proper access permissions to its resources
|
||||||
*
|
*
|
||||||
* @param array $globalConfig The $GLOBALS['config'] array
|
* @param ConfigManager $conf Configuration Manager instance.
|
||||||
*
|
*
|
||||||
* @return array A list of the detected configuration issues
|
* @return array A list of the detected configuration issues
|
||||||
*/
|
*/
|
||||||
public static function checkResourcePermissions($globalConfig)
|
public static function checkResourcePermissions($conf)
|
||||||
{
|
{
|
||||||
$errors = array();
|
$errors = array();
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ public static function checkResourcePermissions($globalConfig)
|
||||||
'application',
|
'application',
|
||||||
'inc',
|
'inc',
|
||||||
'plugins',
|
'plugins',
|
||||||
$globalConfig['RAINTPL_TPL']
|
$conf->get('resource.raintpl_tpl'),
|
||||||
) as $path) {
|
) as $path) {
|
||||||
if (! is_readable(realpath($path))) {
|
if (! is_readable(realpath($path))) {
|
||||||
$errors[] = '"'.$path.'" directory is not readable';
|
$errors[] = '"'.$path.'" directory is not readable';
|
||||||
|
@ -154,10 +154,10 @@ public static function checkResourcePermissions($globalConfig)
|
||||||
|
|
||||||
// Check cache and data directories are readable and writeable
|
// Check cache and data directories are readable and writeable
|
||||||
foreach (array(
|
foreach (array(
|
||||||
$globalConfig['CACHEDIR'],
|
$conf->get('resource.thumbnails_cache'),
|
||||||
$globalConfig['DATADIR'],
|
$conf->get('resource.data_dir'),
|
||||||
$globalConfig['PAGECACHE'],
|
$conf->get('resource.page_cache'),
|
||||||
$globalConfig['RAINTPL_TMP']
|
$conf->get('resource.raintpl_tmp'),
|
||||||
) as $path) {
|
) as $path) {
|
||||||
if (! is_readable(realpath($path))) {
|
if (! is_readable(realpath($path))) {
|
||||||
$errors[] = '"'.$path.'" directory is not readable';
|
$errors[] = '"'.$path.'" directory is not readable';
|
||||||
|
@ -169,11 +169,11 @@ public static function checkResourcePermissions($globalConfig)
|
||||||
|
|
||||||
// Check configuration files are readable and writeable
|
// Check configuration files are readable and writeable
|
||||||
foreach (array(
|
foreach (array(
|
||||||
$globalConfig['CONFIG_FILE'],
|
$conf->getConfigFileExt(),
|
||||||
$globalConfig['DATASTORE'],
|
$conf->get('resource.datastore'),
|
||||||
$globalConfig['IPBANS_FILENAME'],
|
$conf->get('resource.ban_file'),
|
||||||
$globalConfig['LOG_FILE'],
|
$conf->get('resource.log'),
|
||||||
$globalConfig['UPDATECHECK_FILENAME']
|
$conf->get('resource.update_check'),
|
||||||
) as $path) {
|
) as $path) {
|
||||||
if (! is_file(realpath($path))) {
|
if (! is_file(realpath($path))) {
|
||||||
# the file may not exist yet
|
# the file may not exist yet
|
||||||
|
|
|
@ -1,221 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Functions related to configuration management.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-write configuration file according to given array.
|
|
||||||
* Requires mandatory fields listed in $MANDATORY_FIELDS.
|
|
||||||
*
|
|
||||||
* @param array $config contains all configuration fields.
|
|
||||||
* @param bool $isLoggedIn true if user is logged in.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*
|
|
||||||
* @throws MissingFieldConfigException: a mandatory field has not been provided in $config.
|
|
||||||
* @throws UnauthorizedConfigException: user is not authorize to change configuration.
|
|
||||||
* @throws Exception: an error occured while writing the new config file.
|
|
||||||
*/
|
|
||||||
function writeConfig($config, $isLoggedIn)
|
|
||||||
{
|
|
||||||
// These fields are required in configuration.
|
|
||||||
$MANDATORY_FIELDS = array(
|
|
||||||
'login', 'hash', 'salt', 'timezone', 'title', 'titleLink',
|
|
||||||
'redirector', 'disablesessionprotection', 'privateLinkByDefault'
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isset($config['config']['CONFIG_FILE'])) {
|
|
||||||
throw new MissingFieldConfigException('CONFIG_FILE');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only logged in user can alter config.
|
|
||||||
if (is_file($config['config']['CONFIG_FILE']) && !$isLoggedIn) {
|
|
||||||
throw new UnauthorizedConfigException();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that all mandatory fields are provided in $config.
|
|
||||||
foreach ($MANDATORY_FIELDS as $field) {
|
|
||||||
if (!isset($config[$field])) {
|
|
||||||
throw new MissingFieldConfigException($field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$configStr = '<?php '. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'login\'] = '.var_export($config['login'], true).';'. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'hash\'] = '.var_export($config['hash'], true).';'. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'salt\'] = '.var_export($config['salt'], true).'; '. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'timezone\'] = '.var_export($config['timezone'], true).';'. PHP_EOL;
|
|
||||||
$configStr .= 'date_default_timezone_set('.var_export($config['timezone'], true).');'. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'title\'] = '.var_export($config['title'], true).';'. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'titleLink\'] = '.var_export($config['titleLink'], true).'; '. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'redirector\'] = '.var_export($config['redirector'], true).'; '. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'disablesessionprotection\'] = '.var_export($config['disablesessionprotection'], true).'; '. PHP_EOL;
|
|
||||||
$configStr .= '$GLOBALS[\'privateLinkByDefault\'] = '.var_export($config['privateLinkByDefault'], true).'; '. PHP_EOL;
|
|
||||||
|
|
||||||
// Store all $config['config']
|
|
||||||
foreach ($config['config'] as $key => $value) {
|
|
||||||
$configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($config['config'][$key], true).';'. PHP_EOL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['plugins'])) {
|
|
||||||
foreach ($config['plugins'] as $key => $value) {
|
|
||||||
$configStr .= '$GLOBALS[\'plugins\'][\''. $key .'\'] = '.var_export($config['plugins'][$key], true).';'. PHP_EOL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_put_contents($config['config']['CONFIG_FILE'], $configStr)
|
|
||||||
|| strcmp(file_get_contents($config['config']['CONFIG_FILE']), $configStr) != 0
|
|
||||||
) {
|
|
||||||
throw new Exception(
|
|
||||||
'Shaarli could not create the config file.
|
|
||||||
Please make sure Shaarli has the right to write in the folder is it installed in.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process plugin administration form data and save it in an array.
|
|
||||||
*
|
|
||||||
* @param array $formData Data sent by the plugin admin form.
|
|
||||||
*
|
|
||||||
* @return array New list of enabled plugin, ordered.
|
|
||||||
*
|
|
||||||
* @throws PluginConfigOrderException Plugins can't be sorted because their order is invalid.
|
|
||||||
*/
|
|
||||||
function save_plugin_config($formData)
|
|
||||||
{
|
|
||||||
// Make sure there are no duplicates in orders.
|
|
||||||
if (!validate_plugin_order($formData)) {
|
|
||||||
throw new PluginConfigOrderException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$plugins = array();
|
|
||||||
$newEnabledPlugins = array();
|
|
||||||
foreach ($formData as $key => $data) {
|
|
||||||
if (startsWith($key, 'order')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no order, it means a disabled plugin has been enabled.
|
|
||||||
if (isset($formData['order_' . $key])) {
|
|
||||||
$plugins[(int) $formData['order_' . $key]] = $key;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$newEnabledPlugins[] = $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New enabled plugins will be added at the end of order.
|
|
||||||
$plugins = array_merge($plugins, $newEnabledPlugins);
|
|
||||||
|
|
||||||
// Sort plugins by order.
|
|
||||||
if (!ksort($plugins)) {
|
|
||||||
throw new PluginConfigOrderException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$finalPlugins = array();
|
|
||||||
// Make plugins order continuous.
|
|
||||||
foreach ($plugins as $plugin) {
|
|
||||||
$finalPlugins[] = $plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $finalPlugins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate plugin array submitted.
|
|
||||||
* Will fail if there is duplicate orders value.
|
|
||||||
*
|
|
||||||
* @param array $formData Data from submitted form.
|
|
||||||
*
|
|
||||||
* @return bool true if ok, false otherwise.
|
|
||||||
*/
|
|
||||||
function validate_plugin_order($formData)
|
|
||||||
{
|
|
||||||
$orders = array();
|
|
||||||
foreach ($formData as $key => $value) {
|
|
||||||
// No duplicate order allowed.
|
|
||||||
if (in_array($value, $orders)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startsWith($key, 'order')) {
|
|
||||||
$orders[] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Affect plugin parameters values into plugins array.
|
|
||||||
*
|
|
||||||
* @param mixed $plugins Plugins array ($plugins[<plugin_name>]['parameters']['param_name'] = <value>.
|
|
||||||
* @param mixed $config Plugins configuration.
|
|
||||||
*
|
|
||||||
* @return mixed Updated $plugins array.
|
|
||||||
*/
|
|
||||||
function load_plugin_parameter_values($plugins, $config)
|
|
||||||
{
|
|
||||||
$out = $plugins;
|
|
||||||
foreach ($plugins as $name => $plugin) {
|
|
||||||
if (empty($plugin['parameters'])) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($plugin['parameters'] as $key => $param) {
|
|
||||||
if (!empty($config[$key])) {
|
|
||||||
$out[$name]['parameters'][$key] = $config[$key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception used if a mandatory field is missing in given configuration.
|
|
||||||
*/
|
|
||||||
class MissingFieldConfigException extends Exception
|
|
||||||
{
|
|
||||||
public $field;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct exception.
|
|
||||||
*
|
|
||||||
* @param string $field field name missing.
|
|
||||||
*/
|
|
||||||
public function __construct($field)
|
|
||||||
{
|
|
||||||
$this->field = $field;
|
|
||||||
$this->message = 'Configuration value is required for '. $this->field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception used if an unauthorized attempt to edit configuration has been made.
|
|
||||||
*/
|
|
||||||
class UnauthorizedConfigException extends Exception
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Construct exception.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->message = 'You are not authorized to alter config.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception used if an error occur while saving plugin configuration.
|
|
||||||
*/
|
|
||||||
class PluginConfigOrderException extends Exception
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Construct exception.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->message = 'An error occurred while trying to save plugins loading order.';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,11 +9,13 @@ class IOException extends Exception
|
||||||
/**
|
/**
|
||||||
* Construct a new IOException
|
* Construct a new IOException
|
||||||
*
|
*
|
||||||
* @param string $path path to the ressource that cannot be accessed
|
* @param string $path path to the resource that cannot be accessed
|
||||||
|
* @param string $message Custom exception message.
|
||||||
*/
|
*/
|
||||||
public function __construct($path)
|
public function __construct($path, $message = '')
|
||||||
{
|
{
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
$this->message = 'Error accessing '.$this->path;
|
$this->message = empty($message) ? 'Error accessing' : $message;
|
||||||
|
$this->message .= PHP_EOL . $this->path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,21 @@ class PageBuilder
|
||||||
*/
|
*/
|
||||||
private $tpl;
|
private $tpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ConfigManager $conf Configuration Manager instance.
|
||||||
|
*/
|
||||||
|
protected $conf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PageBuilder constructor.
|
* PageBuilder constructor.
|
||||||
* $tpl is initialized at false for lazy loading.
|
* $tpl is initialized at false for lazy loading.
|
||||||
|
*
|
||||||
|
* @param ConfigManager $conf Configuration Manager instance (reference).
|
||||||
*/
|
*/
|
||||||
function __construct()
|
function __construct(&$conf)
|
||||||
{
|
{
|
||||||
$this->tpl = false;
|
$this->tpl = false;
|
||||||
|
$this->conf = $conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,17 +41,17 @@ private function initialize()
|
||||||
try {
|
try {
|
||||||
$version = ApplicationUtils::checkUpdate(
|
$version = ApplicationUtils::checkUpdate(
|
||||||
shaarli_version,
|
shaarli_version,
|
||||||
$GLOBALS['config']['UPDATECHECK_FILENAME'],
|
$this->conf->get('resource.update_check'),
|
||||||
$GLOBALS['config']['UPDATECHECK_INTERVAL'],
|
$this->conf->get('updates.check_updates_interval'),
|
||||||
$GLOBALS['config']['ENABLE_UPDATECHECK'],
|
$this->conf->get('updates.check_updates'),
|
||||||
isLoggedIn(),
|
isLoggedIn(),
|
||||||
$GLOBALS['config']['UPDATECHECK_BRANCH']
|
$this->conf->get('updates.check_updates_branch')
|
||||||
);
|
);
|
||||||
$this->tpl->assign('newVersion', escape($version));
|
$this->tpl->assign('newVersion', escape($version));
|
||||||
$this->tpl->assign('versionError', '');
|
$this->tpl->assign('versionError', '');
|
||||||
|
|
||||||
} catch (Exception $exc) {
|
} catch (Exception $exc) {
|
||||||
logm($GLOBALS['config']['LOG_FILE'], $_SERVER['REMOTE_ADDR'], $exc->getMessage());
|
logm($this->conf->get('resource.log'), $_SERVER['REMOTE_ADDR'], $exc->getMessage());
|
||||||
$this->tpl->assign('newVersion', '');
|
$this->tpl->assign('newVersion', '');
|
||||||
$this->tpl->assign('versionError', escape($exc->getMessage()));
|
$this->tpl->assign('versionError', escape($exc->getMessage()));
|
||||||
}
|
}
|
||||||
|
@ -62,19 +70,24 @@ private function initialize()
|
||||||
$this->tpl->assign('scripturl', index_url($_SERVER));
|
$this->tpl->assign('scripturl', index_url($_SERVER));
|
||||||
$this->tpl->assign('pagetitle', 'Shaarli');
|
$this->tpl->assign('pagetitle', 'Shaarli');
|
||||||
$this->tpl->assign('privateonly', !empty($_SESSION['privateonly'])); // Show only private links?
|
$this->tpl->assign('privateonly', !empty($_SESSION['privateonly'])); // Show only private links?
|
||||||
if (!empty($GLOBALS['title'])) {
|
if ($this->conf->exists('general.title')) {
|
||||||
$this->tpl->assign('pagetitle', $GLOBALS['title']);
|
$this->tpl->assign('pagetitle', $this->conf->get('general.title'));
|
||||||
}
|
}
|
||||||
if (!empty($GLOBALS['titleLink'])) {
|
if ($this->conf->exists('general.header_link')) {
|
||||||
$this->tpl->assign('titleLink', $GLOBALS['titleLink']);
|
$this->tpl->assign('titleLink', $this->conf->get('general.header_link'));
|
||||||
}
|
}
|
||||||
if (!empty($GLOBALS['pagetitle'])) {
|
if ($this->conf->exists('pagetitle')) {
|
||||||
$this->tpl->assign('pagetitle', $GLOBALS['pagetitle']);
|
$this->tpl->assign('pagetitle', $this->conf->get('pagetitle'));
|
||||||
}
|
}
|
||||||
$this->tpl->assign('shaarlititle', empty($GLOBALS['title']) ? 'Shaarli': $GLOBALS['title']);
|
$this->tpl->assign('shaarlititle', $this->conf->get('title', 'Shaarli'));
|
||||||
|
$this->tpl->assign('openshaarli', $this->conf->get('security.open_shaarli', false));
|
||||||
|
$this->tpl->assign('showatom', $this->conf->get('feed.show_atom', false));
|
||||||
|
$this->tpl->assign('hide_timestamps', $this->conf->get('privacy.hide_timestamps', false));
|
||||||
if (!empty($GLOBALS['plugin_errors'])) {
|
if (!empty($GLOBALS['plugin_errors'])) {
|
||||||
$this->tpl->assign('plugin_errors', $GLOBALS['plugin_errors']);
|
$this->tpl->assign('plugin_errors', $GLOBALS['plugin_errors']);
|
||||||
}
|
}
|
||||||
|
// To be removed with a proper theme configuration.
|
||||||
|
$this->tpl->assign('conf', $this->conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,7 +98,6 @@ private function initialize()
|
||||||
*/
|
*/
|
||||||
public function assign($placeholder, $value)
|
public function assign($placeholder, $value)
|
||||||
{
|
{
|
||||||
// Lazy initialization
|
|
||||||
if ($this->tpl === false) {
|
if ($this->tpl === false) {
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
}
|
}
|
||||||
|
@ -101,7 +113,6 @@ public function assign($placeholder, $value)
|
||||||
*/
|
*/
|
||||||
public function assignAll($data)
|
public function assignAll($data)
|
||||||
{
|
{
|
||||||
// Lazy initialization
|
|
||||||
if ($this->tpl === false) {
|
if ($this->tpl === false) {
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
}
|
}
|
||||||
|
@ -113,6 +124,7 @@ public function assignAll($data)
|
||||||
foreach ($data as $key => $value) {
|
foreach ($data as $key => $value) {
|
||||||
$this->assign($key, $value);
|
$this->assign($key, $value);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,10 +135,10 @@ public function assignAll($data)
|
||||||
*/
|
*/
|
||||||
public function renderPage($page)
|
public function renderPage($page)
|
||||||
{
|
{
|
||||||
// Lazy initialization
|
if ($this->tpl === false) {
|
||||||
if ($this->tpl===false) {
|
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->tpl->draw($page);
|
$this->tpl->draw($page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,9 @@
|
||||||
* Class PluginManager
|
* Class PluginManager
|
||||||
*
|
*
|
||||||
* Use to manage, load and execute plugins.
|
* Use to manage, load and execute plugins.
|
||||||
*
|
|
||||||
* Using Singleton design pattern.
|
|
||||||
*/
|
*/
|
||||||
class PluginManager
|
class PluginManager
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* PluginManager singleton instance.
|
|
||||||
* @var PluginManager $instance
|
|
||||||
*/
|
|
||||||
private static $instance;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of authorized plugins from configuration file.
|
* List of authorized plugins from configuration file.
|
||||||
* @var array $authorizedPlugins
|
* @var array $authorizedPlugins
|
||||||
|
@ -27,6 +19,11 @@ class PluginManager
|
||||||
*/
|
*/
|
||||||
private $loadedPlugins = array();
|
private $loadedPlugins = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ConfigManager Configuration Manager instance.
|
||||||
|
*/
|
||||||
|
protected $conf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugins subdirectory.
|
* Plugins subdirectory.
|
||||||
* @var string $PLUGINS_PATH
|
* @var string $PLUGINS_PATH
|
||||||
|
@ -40,33 +37,13 @@ class PluginManager
|
||||||
public static $META_EXT = 'meta';
|
public static $META_EXT = 'meta';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor: new instances not allowed.
|
* Constructor.
|
||||||
*/
|
|
||||||
private function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cloning isn't allowed either.
|
|
||||||
*
|
*
|
||||||
* @return void
|
* @param ConfigManager $conf Configuration Manager instance.
|
||||||
*/
|
*/
|
||||||
private function __clone()
|
public function __construct(&$conf)
|
||||||
{
|
{
|
||||||
}
|
$this->conf = $conf;
|
||||||
|
|
||||||
/**
|
|
||||||
* Return existing instance of PluginManager, or create it.
|
|
||||||
*
|
|
||||||
* @return PluginManager instance.
|
|
||||||
*/
|
|
||||||
public static function getInstance()
|
|
||||||
{
|
|
||||||
if (!(self::$instance instanceof self)) {
|
|
||||||
self::$instance = new self();
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,9 +79,9 @@ public function load($authorizedPlugins)
|
||||||
/**
|
/**
|
||||||
* Execute all plugins registered hook.
|
* Execute all plugins registered hook.
|
||||||
*
|
*
|
||||||
* @param string $hook name of the hook to trigger.
|
* @param string $hook name of the hook to trigger.
|
||||||
* @param array $data list of data to manipulate passed by reference.
|
* @param array $data list of data to manipulate passed by reference.
|
||||||
* @param array $params additional parameters such as page target.
|
* @param array $params additional parameters such as page target.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
@ -122,7 +99,7 @@ public function executeHooks($hook, &$data, $params = array())
|
||||||
$hookFunction = $this->buildHookName($hook, $plugin);
|
$hookFunction = $this->buildHookName($hook, $plugin);
|
||||||
|
|
||||||
if (function_exists($hookFunction)) {
|
if (function_exists($hookFunction)) {
|
||||||
$data = call_user_func($hookFunction, $data);
|
$data = call_user_func($hookFunction, $data, $this->conf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,6 +125,7 @@ private function loadPlugin($dir, $pluginName)
|
||||||
throw new PluginFileNotFoundException($pluginName);
|
throw new PluginFileNotFoundException($pluginName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$conf = $this->conf;
|
||||||
include_once $pluginFilePath;
|
include_once $pluginFilePath;
|
||||||
|
|
||||||
$this->loadedPlugins[] = $pluginName;
|
$this->loadedPlugins[] = $pluginName;
|
||||||
|
|
|
@ -12,16 +12,16 @@ class Updater
|
||||||
*/
|
*/
|
||||||
protected $doneUpdates;
|
protected $doneUpdates;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array Shaarli's configuration array.
|
|
||||||
*/
|
|
||||||
protected $config;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var LinkDB instance.
|
* @var LinkDB instance.
|
||||||
*/
|
*/
|
||||||
protected $linkDB;
|
protected $linkDB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ConfigManager $conf Configuration Manager instance.
|
||||||
|
*/
|
||||||
|
protected $conf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool True if the user is logged in, false otherwise.
|
* @var bool True if the user is logged in, false otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ -35,16 +35,16 @@ class Updater
|
||||||
/**
|
/**
|
||||||
* Object constructor.
|
* Object constructor.
|
||||||
*
|
*
|
||||||
* @param array $doneUpdates Updates which are already done.
|
* @param array $doneUpdates Updates which are already done.
|
||||||
* @param array $config Shaarli's configuration array.
|
* @param LinkDB $linkDB LinkDB instance.
|
||||||
* @param LinkDB $linkDB LinkDB instance.
|
* @oaram ConfigManager $conf Configuration Manager instance.
|
||||||
* @param boolean $isLoggedIn True if the user is logged in.
|
* @param boolean $isLoggedIn True if the user is logged in.
|
||||||
*/
|
*/
|
||||||
public function __construct($doneUpdates, $config, $linkDB, $isLoggedIn)
|
public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn)
|
||||||
{
|
{
|
||||||
$this->doneUpdates = $doneUpdates;
|
$this->doneUpdates = $doneUpdates;
|
||||||
$this->config = $config;
|
|
||||||
$this->linkDB = $linkDB;
|
$this->linkDB = $linkDB;
|
||||||
|
$this->conf = $conf;
|
||||||
$this->isLoggedIn = $isLoggedIn;
|
$this->isLoggedIn = $isLoggedIn;
|
||||||
|
|
||||||
// Retrieve all update methods.
|
// Retrieve all update methods.
|
||||||
|
@ -114,19 +114,19 @@ public function getDoneUpdates()
|
||||||
*/
|
*/
|
||||||
public function updateMethodMergeDeprecatedConfigFile()
|
public function updateMethodMergeDeprecatedConfigFile()
|
||||||
{
|
{
|
||||||
$config_file = $this->config['config']['CONFIG_FILE'];
|
if (is_file($this->conf->get('resource.data_dir') . '/options.php')) {
|
||||||
|
include $this->conf->get('resource.data_dir') . '/options.php';
|
||||||
if (is_file($this->config['config']['DATADIR'].'/options.php')) {
|
|
||||||
include $this->config['config']['DATADIR'].'/options.php';
|
|
||||||
|
|
||||||
// Load GLOBALS into config
|
// Load GLOBALS into config
|
||||||
|
$allowedKeys = array_merge(ConfigPhp::$ROOT_KEYS);
|
||||||
|
$allowedKeys[] = 'config';
|
||||||
foreach ($GLOBALS as $key => $value) {
|
foreach ($GLOBALS as $key => $value) {
|
||||||
$this->config[$key] = $value;
|
if (in_array($key, $allowedKeys)) {
|
||||||
|
$this->conf->set($key, $value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$this->config['config']['CONFIG_FILE'] = $config_file;
|
$this->conf->write($this->isLoggedIn);
|
||||||
writeConfig($this->config, $this->isLoggedIn);
|
unlink($this->conf->get('resource.data_dir').'/options.php');
|
||||||
|
|
||||||
unlink($this->config['config']['DATADIR'].'/options.php');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -143,7 +143,76 @@ public function updateMethodRenameDashTags()
|
||||||
$link['tags'] = implode(' ', array_unique(LinkFilter::tagsStrToArray($link['tags'], true)));
|
$link['tags'] = implode(' ', array_unique(LinkFilter::tagsStrToArray($link['tags'], true)));
|
||||||
$this->linkDB[$link['linkdate']] = $link;
|
$this->linkDB[$link['linkdate']] = $link;
|
||||||
}
|
}
|
||||||
$this->linkDB->savedb($this->config['config']['PAGECACHE']);
|
$this->linkDB->savedb($this->conf->get('resource.page_cache'));
|
||||||
|
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.php'.
|
||||||
|
* It will also convert legacy setting keys to the new ones.
|
||||||
|
*/
|
||||||
|
public function updateMethodConfigToJson()
|
||||||
|
{
|
||||||
|
// JSON config already exists, nothing to do.
|
||||||
|
if ($this->conf->getConfigIO() instanceof ConfigJson) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$configPhp = new ConfigPhp();
|
||||||
|
$configJson = new ConfigJson();
|
||||||
|
$oldConfig = $configPhp->read($this->conf->getConfigFile() . '.php');
|
||||||
|
rename($this->conf->getConfigFileExt(), $this->conf->getConfigFile() . '.save.php');
|
||||||
|
$this->conf->setConfigIO($configJson);
|
||||||
|
$this->conf->reload();
|
||||||
|
|
||||||
|
$legacyMap = array_flip(ConfigPhp::$LEGACY_KEYS_MAPPING);
|
||||||
|
foreach (ConfigPhp::$ROOT_KEYS as $key) {
|
||||||
|
$this->conf->set($legacyMap[$key], $oldConfig[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sub config keys (config and plugins)
|
||||||
|
$subConfig = array('config', 'plugins');
|
||||||
|
foreach ($subConfig as $sub) {
|
||||||
|
foreach ($oldConfig[$sub] as $key => $value) {
|
||||||
|
if (isset($legacyMap[$sub .'.'. $key])) {
|
||||||
|
$configKey = $legacyMap[$sub .'.'. $key];
|
||||||
|
} else {
|
||||||
|
$configKey = $sub .'.'. $key;
|
||||||
|
}
|
||||||
|
$this->conf->set($configKey, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
$this->conf->write($this->isLoggedIn);
|
||||||
|
return true;
|
||||||
|
} catch (IOException $e) {
|
||||||
|
error_log($e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape settings which have been manually escaped in every request in previous versions:
|
||||||
|
* - general.title
|
||||||
|
* - general.header_link
|
||||||
|
* - extras.redirector
|
||||||
|
*
|
||||||
|
* @return bool true if the update is successful, false otherwise.
|
||||||
|
*/
|
||||||
|
public function escapeUnescapedConfig()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->conf->set('general.title', escape($this->conf->get('general.title')));
|
||||||
|
$this->conf->set('general.header_link', escape($this->conf->get('general.header_link')));
|
||||||
|
$this->conf->set('redirector.url', escape($this->conf->get('redirector.url')));
|
||||||
|
$this->conf->write($this->isLoggedIn);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log($e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,7 +272,6 @@ private function buildMessage($message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the updates file, and return already done updates.
|
* Read the updates file, and return already done updates.
|
||||||
*
|
*
|
||||||
|
|
|
@ -273,4 +273,4 @@ function autoLocale($headerLocale)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setlocale(LC_ALL, $attempts);
|
setlocale(LC_ALL, $attempts);
|
||||||
}
|
}
|
||||||
|
|
33
application/config/ConfigIO.php
Normal file
33
application/config/ConfigIO.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface ConfigIO
|
||||||
|
*
|
||||||
|
* This describes how Config types should store their configuration.
|
||||||
|
*/
|
||||||
|
interface ConfigIO
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read configuration.
|
||||||
|
*
|
||||||
|
* @param string $filepath Config file absolute path.
|
||||||
|
*
|
||||||
|
* @return array All configuration in an array.
|
||||||
|
*/
|
||||||
|
function read($filepath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write configuration.
|
||||||
|
*
|
||||||
|
* @param string $filepath Config file absolute path.
|
||||||
|
* @param array $conf All configuration in an array.
|
||||||
|
*/
|
||||||
|
function write($filepath, $conf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get config file extension according to config type.
|
||||||
|
*
|
||||||
|
* @return string Config file extension.
|
||||||
|
*/
|
||||||
|
function getExtension();
|
||||||
|
}
|
78
application/config/ConfigJson.php
Normal file
78
application/config/ConfigJson.php
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConfigJson (ConfigIO implementation)
|
||||||
|
*
|
||||||
|
* Handle Shaarli's JSON configuration file.
|
||||||
|
*/
|
||||||
|
class ConfigJson implements ConfigIO
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
function read($filepath)
|
||||||
|
{
|
||||||
|
if (! is_readable($filepath)) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
$data = file_get_contents($filepath);
|
||||||
|
$data = str_replace(self::getPhpHeaders(), '', $data);
|
||||||
|
$data = str_replace(self::getPhpSuffix(), '', $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::getPhpHeaders() . json_encode($conf, $print) . self::getPhpSuffix();
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Note: this isn't a static field because concatenation isn't supported in field declaration before PHP 5.6.
|
||||||
|
*
|
||||||
|
* @return string PHP start tag and comment tag.
|
||||||
|
*/
|
||||||
|
public static function getPhpHeaders()
|
||||||
|
{
|
||||||
|
return '<?php /*'. PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get PHP comment closing tags.
|
||||||
|
*
|
||||||
|
* Static method for consistency with getPhpHeaders.
|
||||||
|
*
|
||||||
|
* @return string PHP comment closing.
|
||||||
|
*/
|
||||||
|
public static function getPhpSuffix()
|
||||||
|
{
|
||||||
|
return PHP_EOL . '*/ ?>';
|
||||||
|
}
|
||||||
|
}
|
392
application/config/ConfigManager.php
Normal file
392
application/config/ConfigManager.php
Normal file
|
@ -0,0 +1,392 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// FIXME! Namespaces...
|
||||||
|
require_once 'ConfigIO.php';
|
||||||
|
require_once 'ConfigJson.php';
|
||||||
|
require_once 'ConfigPhp.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConfigManager
|
||||||
|
*
|
||||||
|
* Manages all Shaarli's settings.
|
||||||
|
* See the documentation for more information on settings:
|
||||||
|
* - doc/Shaarli-configuration.html
|
||||||
|
* - https://github.com/shaarli/Shaarli/wiki/Shaarli-configuration
|
||||||
|
*/
|
||||||
|
class ConfigManager
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string Flag telling a setting is not found.
|
||||||
|
*/
|
||||||
|
protected static $NOT_FOUND = 'NOT_FOUND';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Config folder.
|
||||||
|
*/
|
||||||
|
protected $configFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array Loaded config array.
|
||||||
|
*/
|
||||||
|
protected $loadedConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ConfigIO implementation instance.
|
||||||
|
*/
|
||||||
|
protected $configIO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct($configFile = 'data/config')
|
||||||
|
{
|
||||||
|
$this->configFile = $configFile;
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the ConfigManager instance.
|
||||||
|
*/
|
||||||
|
public function reset()
|
||||||
|
{
|
||||||
|
$this->initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuild the loaded config array from config files.
|
||||||
|
*/
|
||||||
|
public function reload()
|
||||||
|
{
|
||||||
|
$this->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the ConfigIO and loaded the conf.
|
||||||
|
*/
|
||||||
|
protected function initialize()
|
||||||
|
{
|
||||||
|
if (file_exists($this->configFile . '.php')) {
|
||||||
|
$this->configIO = new ConfigPhp();
|
||||||
|
} else {
|
||||||
|
$this->configIO = new ConfigJson();
|
||||||
|
}
|
||||||
|
$this->load();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load configuration in the ConfigurationManager.
|
||||||
|
*/
|
||||||
|
protected function load()
|
||||||
|
{
|
||||||
|
$this->loadedConfig = $this->configIO->read($this->getConfigFileExt());
|
||||||
|
$this->setDefaultValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a setting.
|
||||||
|
*
|
||||||
|
* Supports nested settings with dot separated keys.
|
||||||
|
* Eg. 'config.stuff.option' will find $conf[config][stuff][option],
|
||||||
|
* or in JSON:
|
||||||
|
* { "config": { "stuff": {"option": "mysetting" } } } }
|
||||||
|
*
|
||||||
|
* @param string $setting Asked setting, keys separated with dots.
|
||||||
|
* @param string $default Default value if not found.
|
||||||
|
*
|
||||||
|
* @return mixed Found setting, or the default value.
|
||||||
|
*/
|
||||||
|
public function get($setting, $default = '')
|
||||||
|
{
|
||||||
|
// During the ConfigIO transition, map legacy settings to the new ones.
|
||||||
|
if ($this->configIO instanceof ConfigPhp && isset(ConfigPhp::$LEGACY_KEYS_MAPPING[$setting])) {
|
||||||
|
$setting = ConfigPhp::$LEGACY_KEYS_MAPPING[$setting];
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = explode('.', $setting);
|
||||||
|
$value = self::getConfig($settings, $this->loadedConfig);
|
||||||
|
if ($value === self::$NOT_FOUND) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a setting, and eventually write it.
|
||||||
|
*
|
||||||
|
* Supports nested settings with dot separated keys.
|
||||||
|
*
|
||||||
|
* @param string $setting Asked setting, keys separated with dots.
|
||||||
|
* @param string $value Value to set.
|
||||||
|
* @param bool $write Write the new setting in the config file, default false.
|
||||||
|
* @param bool $isLoggedIn User login state, default false.
|
||||||
|
*
|
||||||
|
* @throws Exception Invalid
|
||||||
|
*/
|
||||||
|
public function set($setting, $value, $write = false, $isLoggedIn = false)
|
||||||
|
{
|
||||||
|
if (empty($setting) || ! is_string($setting)) {
|
||||||
|
throw new Exception('Invalid setting key parameter. String expected, got: '. gettype($setting));
|
||||||
|
}
|
||||||
|
|
||||||
|
// During the ConfigIO transition, map legacy settings to the new ones.
|
||||||
|
if ($this->configIO instanceof ConfigPhp && isset(ConfigPhp::$LEGACY_KEYS_MAPPING[$setting])) {
|
||||||
|
$setting = ConfigPhp::$LEGACY_KEYS_MAPPING[$setting];
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = explode('.', $setting);
|
||||||
|
self::setConfig($settings, $value, $this->loadedConfig);
|
||||||
|
if ($write) {
|
||||||
|
$this->write($isLoggedIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a settings exists.
|
||||||
|
*
|
||||||
|
* Supports nested settings with dot separated keys.
|
||||||
|
*
|
||||||
|
* @param string $setting Asked setting, keys separated with dots.
|
||||||
|
*
|
||||||
|
* @return bool true if the setting exists, false otherwise.
|
||||||
|
*/
|
||||||
|
public function exists($setting)
|
||||||
|
{
|
||||||
|
// During the ConfigIO transition, map legacy settings to the new ones.
|
||||||
|
if ($this->configIO instanceof ConfigPhp && isset(ConfigPhp::$LEGACY_KEYS_MAPPING[$setting])) {
|
||||||
|
$setting = ConfigPhp::$LEGACY_KEYS_MAPPING[$setting];
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = explode('.', $setting);
|
||||||
|
$value = self::getConfig($settings, $this->loadedConfig);
|
||||||
|
if ($value === self::$NOT_FOUND) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the config writer.
|
||||||
|
*
|
||||||
|
* @param bool $isLoggedIn User login state.
|
||||||
|
*
|
||||||
|
* @return bool True if the configuration has been successfully written, false otherwise.
|
||||||
|
*
|
||||||
|
* @throws MissingFieldConfigException: a mandatory field has not been provided in $conf.
|
||||||
|
* @throws UnauthorizedConfigException: user is not authorize to change configuration.
|
||||||
|
* @throws IOException: an error occurred while writing the new config file.
|
||||||
|
*/
|
||||||
|
public function write($isLoggedIn)
|
||||||
|
{
|
||||||
|
// These fields are required in configuration.
|
||||||
|
$mandatoryFields = array(
|
||||||
|
'credentials.login',
|
||||||
|
'credentials.hash',
|
||||||
|
'credentials.salt',
|
||||||
|
'security.session_protection_disabled',
|
||||||
|
'general.timezone',
|
||||||
|
'general.title',
|
||||||
|
'general.header_link',
|
||||||
|
'privacy.default_private_links',
|
||||||
|
'redirector.url',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Only logged in user can alter config.
|
||||||
|
if (is_file($this->getConfigFileExt()) && !$isLoggedIn) {
|
||||||
|
throw new UnauthorizedConfigException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that all mandatory fields are provided in $conf.
|
||||||
|
foreach ($mandatoryFields as $field) {
|
||||||
|
if (! $this->exists($field)) {
|
||||||
|
throw new MissingFieldConfigException($field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->configIO->write($this->getConfigFileExt(), $this->loadedConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the config file path (without extension).
|
||||||
|
*
|
||||||
|
* @param string $configFile File path.
|
||||||
|
*/
|
||||||
|
public function setConfigFile($configFile)
|
||||||
|
{
|
||||||
|
$this->configFile = $configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the configuration file path (without extension).
|
||||||
|
*
|
||||||
|
* @return string Config path.
|
||||||
|
*/
|
||||||
|
public function getConfigFile()
|
||||||
|
{
|
||||||
|
return $this->configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the configuration file path with its extension.
|
||||||
|
*
|
||||||
|
* @return string Config file path.
|
||||||
|
*/
|
||||||
|
public function getConfigFileExt()
|
||||||
|
{
|
||||||
|
return $this->configFile . $this->configIO->getExtension();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive function which find asked setting in the loaded config.
|
||||||
|
*
|
||||||
|
* @param array $settings Ordered array which contains keys to find.
|
||||||
|
* @param array $conf Loaded settings, then sub-array.
|
||||||
|
*
|
||||||
|
* @return mixed Found setting or NOT_FOUND flag.
|
||||||
|
*/
|
||||||
|
protected static function getConfig($settings, $conf)
|
||||||
|
{
|
||||||
|
if (!is_array($settings) || count($settings) == 0) {
|
||||||
|
return self::$NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
$setting = array_shift($settings);
|
||||||
|
if (!isset($conf[$setting])) {
|
||||||
|
return self::$NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($settings) > 0) {
|
||||||
|
return self::getConfig($settings, $conf[$setting]);
|
||||||
|
}
|
||||||
|
return $conf[$setting];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursive function which find asked setting in the loaded config.
|
||||||
|
*
|
||||||
|
* @param array $settings Ordered array which contains keys to find.
|
||||||
|
* @param mixed $value
|
||||||
|
* @param array $conf Loaded settings, then sub-array.
|
||||||
|
*
|
||||||
|
* @return mixed Found setting or NOT_FOUND flag.
|
||||||
|
*/
|
||||||
|
protected static function setConfig($settings, $value, &$conf)
|
||||||
|
{
|
||||||
|
if (!is_array($settings) || count($settings) == 0) {
|
||||||
|
return self::$NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
$setting = array_shift($settings);
|
||||||
|
if (count($settings) > 0) {
|
||||||
|
return self::setConfig($settings, $value, $conf[$setting]);
|
||||||
|
}
|
||||||
|
$conf[$setting] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a bunch of default values allowing Shaarli to start without a config file.
|
||||||
|
*/
|
||||||
|
protected function setDefaultValues()
|
||||||
|
{
|
||||||
|
$this->setEmpty('resource.data_dir', 'data');
|
||||||
|
$this->setEmpty('resource.config', 'data/config.php');
|
||||||
|
$this->setEmpty('resource.datastore', 'data/datastore.php');
|
||||||
|
$this->setEmpty('resource.ban_file', 'data/ipbans.php');
|
||||||
|
$this->setEmpty('resource.updates', 'data/updates.txt');
|
||||||
|
$this->setEmpty('resource.log', 'data/log.txt');
|
||||||
|
$this->setEmpty('resource.update_check', 'data/lastupdatecheck.txt');
|
||||||
|
$this->setEmpty('resource.raintpl_tpl', 'tpl/');
|
||||||
|
$this->setEmpty('resource.raintpl_tmp', 'tmp/');
|
||||||
|
$this->setEmpty('resource.thumbnails_cache', 'cache');
|
||||||
|
$this->setEmpty('resource.page_cache', 'pagecache');
|
||||||
|
|
||||||
|
$this->setEmpty('security.ban_after', 4);
|
||||||
|
$this->setEmpty('security.ban_duration', 1800);
|
||||||
|
$this->setEmpty('security.session_protection_disabled', false);
|
||||||
|
$this->setEmpty('security.open_shaarli', false);
|
||||||
|
|
||||||
|
$this->setEmpty('general.header_link', '?');
|
||||||
|
$this->setEmpty('general.links_per_page', 20);
|
||||||
|
$this->setEmpty('general.enabled_plugins', array('qrcode'));
|
||||||
|
|
||||||
|
$this->setEmpty('updates.check_updates', false);
|
||||||
|
$this->setEmpty('updates.check_updates_branch', 'stable');
|
||||||
|
$this->setEmpty('updates.check_updates_interval', 86400);
|
||||||
|
|
||||||
|
$this->setEmpty('feed.rss_permalinks', true);
|
||||||
|
$this->setEmpty('feed.show_atom', false);
|
||||||
|
|
||||||
|
$this->setEmpty('privacy.default_private_links', false);
|
||||||
|
$this->setEmpty('privacy.hide_public_links', false);
|
||||||
|
$this->setEmpty('privacy.hide_timestamps', false);
|
||||||
|
|
||||||
|
$this->setEmpty('thumbnail.enable_thumbnails', true);
|
||||||
|
$this->setEmpty('thumbnail.enable_localcache', true);
|
||||||
|
|
||||||
|
$this->setEmpty('redirector.url', '');
|
||||||
|
$this->setEmpty('redirector.encode_url', true);
|
||||||
|
|
||||||
|
$this->setEmpty('plugins', array());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set only if the setting does not exists.
|
||||||
|
*
|
||||||
|
* @param string $key Setting key.
|
||||||
|
* @param mixed $value Setting value.
|
||||||
|
*/
|
||||||
|
public function setEmpty($key, $value)
|
||||||
|
{
|
||||||
|
if (! $this->exists($key)) {
|
||||||
|
$this->set($key, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ConfigIO
|
||||||
|
*/
|
||||||
|
public function getConfigIO()
|
||||||
|
{
|
||||||
|
return $this->configIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ConfigIO $configIO
|
||||||
|
*/
|
||||||
|
public function setConfigIO($configIO)
|
||||||
|
{
|
||||||
|
$this->configIO = $configIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception used if a mandatory field is missing in given configuration.
|
||||||
|
*/
|
||||||
|
class MissingFieldConfigException extends Exception
|
||||||
|
{
|
||||||
|
public $field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct exception.
|
||||||
|
*
|
||||||
|
* @param string $field field name missing.
|
||||||
|
*/
|
||||||
|
public function __construct($field)
|
||||||
|
{
|
||||||
|
$this->field = $field;
|
||||||
|
$this->message = 'Configuration value is required for '. $this->field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception used if an unauthorized attempt to edit configuration has been made.
|
||||||
|
*/
|
||||||
|
class UnauthorizedConfigException extends Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Construct exception.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->message = 'You are not authorized to alter config.';
|
||||||
|
}
|
||||||
|
}
|
132
application/config/ConfigPhp.php
Normal file
132
application/config/ConfigPhp.php
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConfigPhp (ConfigIO implementation)
|
||||||
|
*
|
||||||
|
* Handle Shaarli's legacy PHP configuration file.
|
||||||
|
* Note: this is only designed to support the transition to JSON configuration.
|
||||||
|
*/
|
||||||
|
class ConfigPhp implements ConfigIO
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array List of config key without group.
|
||||||
|
*/
|
||||||
|
public static $ROOT_KEYS = array(
|
||||||
|
'login',
|
||||||
|
'hash',
|
||||||
|
'salt',
|
||||||
|
'timezone',
|
||||||
|
'title',
|
||||||
|
'titleLink',
|
||||||
|
'redirector',
|
||||||
|
'disablesessionprotection',
|
||||||
|
'privateLinkByDefault',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map legacy config keys with the new ones.
|
||||||
|
* If ConfigPhp is used, getting <newkey> will actually look for <legacykey>.
|
||||||
|
* The Updater will use this array to transform keys when switching to JSON.
|
||||||
|
*
|
||||||
|
* @var array current key => legacy key.
|
||||||
|
*/
|
||||||
|
public static $LEGACY_KEYS_MAPPING = array(
|
||||||
|
'credentials.login' => 'login',
|
||||||
|
'credentials.hash' => 'hash',
|
||||||
|
'credentials.salt' => 'salt',
|
||||||
|
'resource.data_dir' => 'config.DATADIR',
|
||||||
|
'resource.config' => 'config.CONFIG_FILE',
|
||||||
|
'resource.datastore' => 'config.DATASTORE',
|
||||||
|
'resource.updates' => 'config.UPDATES_FILE',
|
||||||
|
'resource.log' => 'config.LOG_FILE',
|
||||||
|
'resource.update_check' => 'config.UPDATECHECK_FILENAME',
|
||||||
|
'resource.raintpl_tpl' => 'config.RAINTPL_TPL',
|
||||||
|
'resource.raintpl_tmp' => 'config.RAINTPL_TMP',
|
||||||
|
'resource.thumbnails_cache' => 'config.CACHEDIR',
|
||||||
|
'resource.page_cache' => 'config.PAGECACHE',
|
||||||
|
'resource.ban_file' => 'config.IPBANS_FILENAME',
|
||||||
|
'security.session_protection_disabled' => 'disablesessionprotection',
|
||||||
|
'security.ban_after' => 'config.BAN_AFTER',
|
||||||
|
'security.ban_duration' => 'config.BAN_DURATION',
|
||||||
|
'general.title' => 'title',
|
||||||
|
'general.timezone' => 'timezone',
|
||||||
|
'general.header_link' => 'titleLink',
|
||||||
|
'updates.check_updates' => 'config.ENABLE_UPDATECHECK',
|
||||||
|
'updates.check_updates_branch' => 'config.UPDATECHECK_BRANCH',
|
||||||
|
'updates.check_updates_interval' => 'config.UPDATECHECK_INTERVAL',
|
||||||
|
'privacy.default_private_links' => 'privateLinkByDefault',
|
||||||
|
'feed.rss_permalinks' => 'config.ENABLE_RSS_PERMALINKS',
|
||||||
|
'general.links_per_page' => 'config.LINKS_PER_PAGE',
|
||||||
|
'thumbnail.enable_thumbnails' => 'config.ENABLE_THUMBNAILS',
|
||||||
|
'thumbnail.enable_localcache' => 'config.ENABLE_LOCALCACHE',
|
||||||
|
'general.enabled_plugins' => 'config.ENABLED_PLUGINS',
|
||||||
|
'redirector.url' => 'redirector',
|
||||||
|
'redirector.encode_url' => 'config.REDIRECTOR_URLENCODE',
|
||||||
|
'feed.show_atom' => 'config.SHOW_ATOM',
|
||||||
|
'privacy.hide_public_links' => 'config.HIDE_PUBLIC_LINKS',
|
||||||
|
'privacy.hide_timestamps' => 'config.HIDE_TIMESTAMPS',
|
||||||
|
'security.open_shaarli' => 'config.OPEN_SHAARLI',
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
function read($filepath)
|
||||||
|
{
|
||||||
|
if (! file_exists($filepath) || ! is_readable($filepath)) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
include $filepath;
|
||||||
|
|
||||||
|
$out = array();
|
||||||
|
foreach (self::$ROOT_KEYS as $key) {
|
||||||
|
$out[$key] = $GLOBALS[$key];
|
||||||
|
}
|
||||||
|
$out['config'] = $GLOBALS['config'];
|
||||||
|
$out['plugins'] = !empty($GLOBALS['plugins']) ? $GLOBALS['plugins'] : array();
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
function write($filepath, $conf)
|
||||||
|
{
|
||||||
|
$configStr = '<?php '. PHP_EOL;
|
||||||
|
foreach (self::$ROOT_KEYS as $key) {
|
||||||
|
if (isset($conf[$key])) {
|
||||||
|
$configStr .= '$GLOBALS[\'' . $key . '\'] = ' . var_export($conf[$key], true) . ';' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store all $conf['config']
|
||||||
|
foreach ($conf['config'] as $key => $value) {
|
||||||
|
$configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($conf['config'][$key], true).';'. PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($conf['plugins'])) {
|
||||||
|
foreach ($conf['plugins'] as $key => $value) {
|
||||||
|
$configStr .= '$GLOBALS[\'plugins\'][\''. $key .'\'] = '.var_export($conf['plugins'][$key], true).';'. PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_put_contents($filepath, $configStr)
|
||||||
|
|| strcmp(file_get_contents($filepath), $configStr) != 0
|
||||||
|
) {
|
||||||
|
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 '.php';
|
||||||
|
}
|
||||||
|
}
|
120
application/config/ConfigPlugin.php
Normal file
120
application/config/ConfigPlugin.php
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin configuration helper functions.
|
||||||
|
*
|
||||||
|
* Note: no access to configuration files here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process plugin administration form data and save it in an array.
|
||||||
|
*
|
||||||
|
* @param array $formData Data sent by the plugin admin form.
|
||||||
|
*
|
||||||
|
* @return array New list of enabled plugin, ordered.
|
||||||
|
*
|
||||||
|
* @throws PluginConfigOrderException Plugins can't be sorted because their order is invalid.
|
||||||
|
*/
|
||||||
|
function save_plugin_config($formData)
|
||||||
|
{
|
||||||
|
// Make sure there are no duplicates in orders.
|
||||||
|
if (!validate_plugin_order($formData)) {
|
||||||
|
throw new PluginConfigOrderException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$plugins = array();
|
||||||
|
$newEnabledPlugins = array();
|
||||||
|
foreach ($formData as $key => $data) {
|
||||||
|
if (startsWith($key, 'order')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no order, it means a disabled plugin has been enabled.
|
||||||
|
if (isset($formData['order_' . $key])) {
|
||||||
|
$plugins[(int) $formData['order_' . $key]] = $key;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$newEnabledPlugins[] = $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New enabled plugins will be added at the end of order.
|
||||||
|
$plugins = array_merge($plugins, $newEnabledPlugins);
|
||||||
|
|
||||||
|
// Sort plugins by order.
|
||||||
|
if (!ksort($plugins)) {
|
||||||
|
throw new PluginConfigOrderException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$finalPlugins = array();
|
||||||
|
// Make plugins order continuous.
|
||||||
|
foreach ($plugins as $plugin) {
|
||||||
|
$finalPlugins[] = $plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $finalPlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate plugin array submitted.
|
||||||
|
* Will fail if there is duplicate orders value.
|
||||||
|
*
|
||||||
|
* @param array $formData Data from submitted form.
|
||||||
|
*
|
||||||
|
* @return bool true if ok, false otherwise.
|
||||||
|
*/
|
||||||
|
function validate_plugin_order($formData)
|
||||||
|
{
|
||||||
|
$orders = array();
|
||||||
|
foreach ($formData as $key => $value) {
|
||||||
|
// No duplicate order allowed.
|
||||||
|
if (in_array($value, $orders)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startsWith($key, 'order')) {
|
||||||
|
$orders[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affect plugin parameters values into plugins array.
|
||||||
|
*
|
||||||
|
* @param mixed $plugins Plugins array ($plugins[<plugin_name>]['parameters']['param_name'] = <value>.
|
||||||
|
* @param mixed $conf Plugins configuration.
|
||||||
|
*
|
||||||
|
* @return mixed Updated $plugins array.
|
||||||
|
*/
|
||||||
|
function load_plugin_parameter_values($plugins, $conf)
|
||||||
|
{
|
||||||
|
$out = $plugins;
|
||||||
|
foreach ($plugins as $name => $plugin) {
|
||||||
|
if (empty($plugin['parameters'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($plugin['parameters'] as $key => $param) {
|
||||||
|
if (!empty($conf[$key])) {
|
||||||
|
$out[$name]['parameters'][$key] = $conf[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception used if an error occur while saving plugin configuration.
|
||||||
|
*/
|
||||||
|
class PluginConfigOrderException extends Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Construct exception.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->message = 'An error occurred while trying to save plugins loading order.';
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
$GLOBALS['plugins']['READITYOUSELF_URL'] = 'http://someurl.com';
|
|
|
@ -8,34 +8,31 @@
|
||||||
// it seems kinda dead.
|
// it seems kinda dead.
|
||||||
// Not tested.
|
// Not tested.
|
||||||
|
|
||||||
// don't raise unnecessary warnings
|
$riyUrl = $conf->get('plugins.READITYOUSELF_URL');
|
||||||
if (is_file(PluginManager::$PLUGINS_PATH . '/readityourself/config.php')) {
|
if (empty($riyUrl)) {
|
||||||
include PluginManager::$PLUGINS_PATH . '/readityourself/config.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($GLOBALS['plugins']['READITYOUSELF_URL'])) {
|
|
||||||
$GLOBALS['plugin_errors'][] = 'Readityourself plugin error: '.
|
$GLOBALS['plugin_errors'][] = 'Readityourself plugin error: '.
|
||||||
'Please define "$GLOBALS[\'plugins\'][\'READITYOUSELF_URL\']" '.
|
'Please define the "READITYOUSELF_URL" setting in the plugin administration page.';
|
||||||
'in "plugins/readityourself/config.php" or in your Shaarli config.php file.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add readityourself icon to link_plugin when rendering linklist.
|
* Add readityourself icon to link_plugin when rendering linklist.
|
||||||
*
|
*
|
||||||
* @param mixed $data - linklist data.
|
* @param mixed $data Linklist data.
|
||||||
|
* @param ConfigManager $conf Configuration Manager instance.
|
||||||
*
|
*
|
||||||
* @return mixed - linklist data with readityourself plugin.
|
* @return mixed - linklist data with readityourself plugin.
|
||||||
*/
|
*/
|
||||||
function hook_readityourself_render_linklist($data)
|
function hook_readityourself_render_linklist($data, $conf)
|
||||||
{
|
{
|
||||||
if (!isset($GLOBALS['plugins']['READITYOUSELF_URL'])) {
|
$riyUrl = $conf->get('plugins.READITYOUSELF_URL');
|
||||||
|
if (empty($riyUrl)) {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
$readityourself_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/readityourself/readityourself.html');
|
$readityourself_html = file_get_contents(PluginManager::$PLUGINS_PATH . '/readityourself/readityourself.html');
|
||||||
|
|
||||||
foreach ($data['links'] as &$value) {
|
foreach ($data['links'] as &$value) {
|
||||||
$readityourself = sprintf($readityourself_html, $GLOBALS['plugins']['READITYOUSELF_URL'], $value['url'], PluginManager::$PLUGINS_PATH);
|
$readityourself = sprintf($readityourself_html, $riyUrl, $value['url'], PluginManager::$PLUGINS_PATH);
|
||||||
$value['link_plugin'][] = $readityourself;
|
$value['link_plugin'][] = $readityourself;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,31 +12,26 @@ The directory structure should look like:
|
||||||
└── plugins
|
└── plugins
|
||||||
└── wallabag
|
└── wallabag
|
||||||
├── README.md
|
├── README.md
|
||||||
├── config.php.dist
|
|
||||||
├── wallabag.html
|
├── wallabag.html
|
||||||
|
├── wallabag.meta
|
||||||
├── wallabag.php
|
├── wallabag.php
|
||||||
└── wallabag.png
|
├── wallabag.php
|
||||||
|
└── WallabagInstance.php
|
||||||
```
|
```
|
||||||
|
|
||||||
To enable the plugin, add `'wallabag'` to your list of enabled plugins in `data/options.php` (`PLUGINS` array).
|
To enable the plugin, you can either:
|
||||||
This should look like:
|
|
||||||
|
|
||||||
```
|
* enable it in the plugins administration page (`?do=pluginadmin`).
|
||||||
$GLOBALS['config']['PLUGINS'] = array('qrcode', 'any_other_plugin', 'wallabag')
|
* add `wallabag` to your list of enabled plugins in `data/config.json.php` (`general.enabled_plugins` section).
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
Copy `config.php.dist` into `config.php` and setup your instance.
|
Go to the plugin administration page, and edit the following settings (with the plugin enabled).
|
||||||
|
|
||||||
*Wallabag instance URL*
|
**WALLABAG_URL**: *Wallabag instance URL*
|
||||||
```
|
Example value: `http://v2.wallabag.org`
|
||||||
$GLOBALS['config']['WALLABAG_URL'] = 'http://v2.wallabag.org' ;
|
|
||||||
```
|
|
||||||
|
|
||||||
*Wallabag version*: either `1` (for 1.x) or `2` (for 2.x)
|
**WALLABAG_VERSION**: *Wallabag version*
|
||||||
```
|
Value: either `1` (for 1.x) or `2` (for 2.x)
|
||||||
$GLOBALS['config']['WALLABAG_VERSION'] = 2;
|
|
||||||
```
|
|
||||||
|
|
||||||
> Note: these settings can also be set in `data/config.php`.
|
> Note: these settings can also be set in `data/config.json.php`, in the plugins section.
|
|
@ -1,4 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
$GLOBALS['plugins']['WALLABAG_URL'] = 'https://demo.wallabag.org';
|
|
||||||
$GLOBALS['plugins']['WALLABAG_VERSION'] = 1;
|
|
|
@ -6,34 +6,29 @@
|
||||||
|
|
||||||
require_once 'WallabagInstance.php';
|
require_once 'WallabagInstance.php';
|
||||||
|
|
||||||
// don't raise unnecessary warnings
|
$wallabagUrl = $conf->get('plugins.WALLABAG_URL');
|
||||||
if (is_file(PluginManager::$PLUGINS_PATH . '/wallabag/config.php')) {
|
if (empty($wallabagUrl)) {
|
||||||
include PluginManager::$PLUGINS_PATH . '/wallabag/config.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($GLOBALS['plugins']['WALLABAG_URL'])) {
|
|
||||||
$GLOBALS['plugin_errors'][] = 'Wallabag plugin error: '.
|
$GLOBALS['plugin_errors'][] = 'Wallabag plugin error: '.
|
||||||
'Please define "$GLOBALS[\'plugins\'][\'WALLABAG_URL\']" '.
|
'Please define the "WALLABAG_URL" setting in the plugin administration page.';
|
||||||
'in "plugins/wallabag/config.php" or in your Shaarli config.php file.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add wallabag icon to link_plugin when rendering linklist.
|
* Add wallabag icon to link_plugin when rendering linklist.
|
||||||
*
|
*
|
||||||
* @param mixed $data - linklist data.
|
* @param mixed $data Linklist data.
|
||||||
|
* @param ConfigManager $conf Configuration Manager instance.
|
||||||
*
|
*
|
||||||
* @return mixed - linklist data with wallabag plugin.
|
* @return mixed - linklist data with wallabag plugin.
|
||||||
*/
|
*/
|
||||||
function hook_wallabag_render_linklist($data)
|
function hook_wallabag_render_linklist($data, $conf)
|
||||||
{
|
{
|
||||||
if (!isset($GLOBALS['plugins']['WALLABAG_URL'])) {
|
$wallabagUrl = $conf->get('plugins.WALLABAG_URL');
|
||||||
|
if (empty($wallabagUrl)) {
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
$version = isset($GLOBALS['plugins']['WALLABAG_VERSION'])
|
$version = $conf->get('plugins.WALLABAG_VERSION');
|
||||||
? $GLOBALS['plugins']['WALLABAG_VERSION']
|
$wallabagInstance = new WallabagInstance($wallabagUrl, $version);
|
||||||
: '';
|
|
||||||
$wallabagInstance = new WallabagInstance($GLOBALS['plugins']['WALLABAG_URL'], $version);
|
|
||||||
|
|
||||||
$wallabagHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/wallabag/wallabag.html');
|
$wallabagHtml = file_get_contents(PluginManager::$PLUGINS_PATH . '/wallabag/wallabag.html');
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* ApplicationUtils' tests
|
* ApplicationUtils' tests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
require_once 'application/config/ConfigManager.php';
|
||||||
require_once 'application/ApplicationUtils.php';
|
require_once 'application/ApplicationUtils.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,7 +60,7 @@ public function testGetLatestGitVersionCode()
|
||||||
$testTimeout
|
$testTimeout
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$this->assertRegexp(
|
$this->assertRegExp(
|
||||||
self::$versionPattern,
|
self::$versionPattern,
|
||||||
ApplicationUtils::getLatestGitVersionCode(
|
ApplicationUtils::getLatestGitVersionCode(
|
||||||
'https://raw.githubusercontent.com/shaarli/Shaarli/'
|
'https://raw.githubusercontent.com/shaarli/Shaarli/'
|
||||||
|
@ -275,21 +276,21 @@ public function testCheckSupportedPHPVersion52()
|
||||||
*/
|
*/
|
||||||
public function testCheckCurrentResourcePermissions()
|
public function testCheckCurrentResourcePermissions()
|
||||||
{
|
{
|
||||||
$config = array(
|
$conf = new ConfigManager('');
|
||||||
'CACHEDIR' => 'cache',
|
$conf->set('resource.thumbnails_cache', 'cache');
|
||||||
'CONFIG_FILE' => 'data/config.php',
|
$conf->set('resource.config', 'data/config.php');
|
||||||
'DATADIR' => 'data',
|
$conf->set('resource.data_dir', 'data');
|
||||||
'DATASTORE' => 'data/datastore.php',
|
$conf->set('resource.datastore', 'data/datastore.php');
|
||||||
'IPBANS_FILENAME' => 'data/ipbans.php',
|
$conf->set('resource.ban_file', 'data/ipbans.php');
|
||||||
'LOG_FILE' => 'data/log.txt',
|
$conf->set('resource.log', 'data/log.txt');
|
||||||
'PAGECACHE' => 'pagecache',
|
$conf->set('resource.page_cache', 'pagecache');
|
||||||
'RAINTPL_TMP' => 'tmp',
|
$conf->set('resource.raintpl_tmp', 'tmp');
|
||||||
'RAINTPL_TPL' => 'tpl',
|
$conf->set('resource.raintpl_tpl', 'tpl');
|
||||||
'UPDATECHECK_FILENAME' => 'data/lastupdatecheck.txt'
|
$conf->set('resource.update_check', 'data/lastupdatecheck.txt');
|
||||||
);
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
array(),
|
array(),
|
||||||
ApplicationUtils::checkResourcePermissions($config)
|
ApplicationUtils::checkResourcePermissions($conf)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,18 +299,17 @@ public function testCheckCurrentResourcePermissions()
|
||||||
*/
|
*/
|
||||||
public function testCheckCurrentResourcePermissionsErrors()
|
public function testCheckCurrentResourcePermissionsErrors()
|
||||||
{
|
{
|
||||||
$config = array(
|
$conf = new ConfigManager('');
|
||||||
'CACHEDIR' => 'null/cache',
|
$conf->set('resource.thumbnails_cache', 'null/cache');
|
||||||
'CONFIG_FILE' => 'null/data/config.php',
|
$conf->set('resource.config', 'null/data/config.php');
|
||||||
'DATADIR' => 'null/data',
|
$conf->set('resource.data_dir', 'null/data');
|
||||||
'DATASTORE' => 'null/data/store.php',
|
$conf->set('resource.datastore', 'null/data/store.php');
|
||||||
'IPBANS_FILENAME' => 'null/data/ipbans.php',
|
$conf->set('resource.ban_file', 'null/data/ipbans.php');
|
||||||
'LOG_FILE' => 'null/data/log.txt',
|
$conf->set('resource.log', 'null/data/log.txt');
|
||||||
'PAGECACHE' => 'null/pagecache',
|
$conf->set('resource.page_cache', 'null/pagecache');
|
||||||
'RAINTPL_TMP' => 'null/tmp',
|
$conf->set('resource.raintpl_tmp', 'null/tmp');
|
||||||
'RAINTPL_TPL' => 'null/tpl',
|
$conf->set('resource.raintpl_tpl', 'null/tpl');
|
||||||
'UPDATECHECK_FILENAME' => 'null/data/lastupdatecheck.txt'
|
$conf->set('resource.update_check', 'null/data/lastupdatecheck.txt');
|
||||||
);
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
array(
|
array(
|
||||||
'"null/tpl" directory is not readable',
|
'"null/tpl" directory is not readable',
|
||||||
|
@ -322,7 +322,7 @@ public function testCheckCurrentResourcePermissionsErrors()
|
||||||
'"null/tmp" directory is not readable',
|
'"null/tmp" directory is not readable',
|
||||||
'"null/tmp" directory is not writable'
|
'"null/tmp" directory is not writable'
|
||||||
),
|
),
|
||||||
ApplicationUtils::checkResourcePermissions($config)
|
ApplicationUtils::checkResourcePermissions($conf)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,244 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Config' tests
|
|
||||||
*/
|
|
||||||
|
|
||||||
require_once 'application/Config.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unitary tests for Shaarli config related functions
|
|
||||||
*/
|
|
||||||
class ConfigTest extends PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
// Configuration input set.
|
|
||||||
private static $configFields;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed before each test.
|
|
||||||
*/
|
|
||||||
public function setUp()
|
|
||||||
{
|
|
||||||
self::$configFields = array(
|
|
||||||
'login' => 'login',
|
|
||||||
'hash' => 'hash',
|
|
||||||
'salt' => 'salt',
|
|
||||||
'timezone' => 'Europe/Paris',
|
|
||||||
'title' => 'title',
|
|
||||||
'titleLink' => 'titleLink',
|
|
||||||
'redirector' => '',
|
|
||||||
'disablesessionprotection' => false,
|
|
||||||
'privateLinkByDefault' => false,
|
|
||||||
'config' => array(
|
|
||||||
'CONFIG_FILE' => 'tests/config.php',
|
|
||||||
'DATADIR' => 'tests',
|
|
||||||
'config1' => 'config1data',
|
|
||||||
'config2' => 'config2data',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed after each test.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function tearDown()
|
|
||||||
{
|
|
||||||
if (is_file(self::$configFields['config']['CONFIG_FILE'])) {
|
|
||||||
unlink(self::$configFields['config']['CONFIG_FILE']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test writeConfig function, valid use case, while being logged in.
|
|
||||||
*/
|
|
||||||
public function testWriteConfig()
|
|
||||||
{
|
|
||||||
writeConfig(self::$configFields, true);
|
|
||||||
|
|
||||||
include self::$configFields['config']['CONFIG_FILE'];
|
|
||||||
$this->assertEquals(self::$configFields['login'], $GLOBALS['login']);
|
|
||||||
$this->assertEquals(self::$configFields['hash'], $GLOBALS['hash']);
|
|
||||||
$this->assertEquals(self::$configFields['salt'], $GLOBALS['salt']);
|
|
||||||
$this->assertEquals(self::$configFields['timezone'], $GLOBALS['timezone']);
|
|
||||||
$this->assertEquals(self::$configFields['title'], $GLOBALS['title']);
|
|
||||||
$this->assertEquals(self::$configFields['titleLink'], $GLOBALS['titleLink']);
|
|
||||||
$this->assertEquals(self::$configFields['redirector'], $GLOBALS['redirector']);
|
|
||||||
$this->assertEquals(self::$configFields['disablesessionprotection'], $GLOBALS['disablesessionprotection']);
|
|
||||||
$this->assertEquals(self::$configFields['privateLinkByDefault'], $GLOBALS['privateLinkByDefault']);
|
|
||||||
$this->assertEquals(self::$configFields['config']['config1'], $GLOBALS['config']['config1']);
|
|
||||||
$this->assertEquals(self::$configFields['config']['config2'], $GLOBALS['config']['config2']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test writeConfig option while logged in:
|
|
||||||
* 1. init fields.
|
|
||||||
* 2. update fields, add new sub config, add new root config.
|
|
||||||
* 3. rewrite config.
|
|
||||||
* 4. check result.
|
|
||||||
*/
|
|
||||||
public function testWriteConfigFieldUpdate()
|
|
||||||
{
|
|
||||||
writeConfig(self::$configFields, true);
|
|
||||||
self::$configFields['title'] = 'ok';
|
|
||||||
self::$configFields['config']['config1'] = 'ok';
|
|
||||||
self::$configFields['config']['config_new'] = 'ok';
|
|
||||||
self::$configFields['new'] = 'should not be saved';
|
|
||||||
writeConfig(self::$configFields, true);
|
|
||||||
|
|
||||||
include self::$configFields['config']['CONFIG_FILE'];
|
|
||||||
$this->assertEquals('ok', $GLOBALS['title']);
|
|
||||||
$this->assertEquals('ok', $GLOBALS['config']['config1']);
|
|
||||||
$this->assertEquals('ok', $GLOBALS['config']['config_new']);
|
|
||||||
$this->assertFalse(isset($GLOBALS['new']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test writeConfig function with an empty array.
|
|
||||||
*
|
|
||||||
* @expectedException MissingFieldConfigException
|
|
||||||
*/
|
|
||||||
public function testWriteConfigEmpty()
|
|
||||||
{
|
|
||||||
writeConfig(array(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test writeConfig function with a missing mandatory field.
|
|
||||||
*
|
|
||||||
* @expectedException MissingFieldConfigException
|
|
||||||
*/
|
|
||||||
public function testWriteConfigMissingField()
|
|
||||||
{
|
|
||||||
unset(self::$configFields['login']);
|
|
||||||
writeConfig(self::$configFields, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test writeConfig function while being logged out, and there is no config file existing.
|
|
||||||
*/
|
|
||||||
public function testWriteConfigLoggedOutNoFile()
|
|
||||||
{
|
|
||||||
writeConfig(self::$configFields, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test writeConfig function while being logged out, and a config file already exists.
|
|
||||||
*
|
|
||||||
* @expectedException UnauthorizedConfigException
|
|
||||||
*/
|
|
||||||
public function testWriteConfigLoggedOutWithFile()
|
|
||||||
{
|
|
||||||
file_put_contents(self::$configFields['config']['CONFIG_FILE'], '');
|
|
||||||
writeConfig(self::$configFields, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test save_plugin_config with valid data.
|
|
||||||
*
|
|
||||||
* @throws PluginConfigOrderException
|
|
||||||
*/
|
|
||||||
public function testSavePluginConfigValid()
|
|
||||||
{
|
|
||||||
$data = array(
|
|
||||||
'order_plugin1' => 2, // no plugin related
|
|
||||||
'plugin2' => 0, // new - at the end
|
|
||||||
'plugin3' => 0, // 2nd
|
|
||||||
'order_plugin3' => 8,
|
|
||||||
'plugin4' => 0, // 1st
|
|
||||||
'order_plugin4' => 5,
|
|
||||||
);
|
|
||||||
|
|
||||||
$expected = array(
|
|
||||||
'plugin3',
|
|
||||||
'plugin4',
|
|
||||||
'plugin2',
|
|
||||||
);
|
|
||||||
|
|
||||||
$out = save_plugin_config($data);
|
|
||||||
$this->assertEquals($expected, $out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test save_plugin_config with invalid data.
|
|
||||||
*
|
|
||||||
* @expectedException PluginConfigOrderException
|
|
||||||
*/
|
|
||||||
public function testSavePluginConfigInvalid()
|
|
||||||
{
|
|
||||||
$data = array(
|
|
||||||
'plugin2' => 0,
|
|
||||||
'plugin3' => 0,
|
|
||||||
'order_plugin3' => 0,
|
|
||||||
'plugin4' => 0,
|
|
||||||
'order_plugin4' => 0,
|
|
||||||
);
|
|
||||||
|
|
||||||
save_plugin_config($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test save_plugin_config without data.
|
|
||||||
*/
|
|
||||||
public function testSavePluginConfigEmpty()
|
|
||||||
{
|
|
||||||
$this->assertEquals(array(), save_plugin_config(array()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test validate_plugin_order with valid data.
|
|
||||||
*/
|
|
||||||
public function testValidatePluginOrderValid()
|
|
||||||
{
|
|
||||||
$data = array(
|
|
||||||
'order_plugin1' => 2,
|
|
||||||
'plugin2' => 0,
|
|
||||||
'plugin3' => 0,
|
|
||||||
'order_plugin3' => 1,
|
|
||||||
'plugin4' => 0,
|
|
||||||
'order_plugin4' => 5,
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertTrue(validate_plugin_order($data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test validate_plugin_order with invalid data.
|
|
||||||
*/
|
|
||||||
public function testValidatePluginOrderInvalid()
|
|
||||||
{
|
|
||||||
$data = array(
|
|
||||||
'order_plugin1' => 2,
|
|
||||||
'order_plugin3' => 1,
|
|
||||||
'order_plugin4' => 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertFalse(validate_plugin_order($data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test load_plugin_parameter_values.
|
|
||||||
*/
|
|
||||||
public function testLoadPluginParameterValues()
|
|
||||||
{
|
|
||||||
$plugins = array(
|
|
||||||
'plugin_name' => array(
|
|
||||||
'parameters' => array(
|
|
||||||
'param1' => true,
|
|
||||||
'param2' => false,
|
|
||||||
'param3' => '',
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$parameters = array(
|
|
||||||
'param1' => 'value1',
|
|
||||||
'param2' => 'value2',
|
|
||||||
);
|
|
||||||
|
|
||||||
$result = load_plugin_parameter_values($plugins, $parameters);
|
|
||||||
$this->assertEquals('value1', $result['plugin_name']['parameters']['param1']);
|
|
||||||
$this->assertEquals('value2', $result['plugin_name']['parameters']['param2']);
|
|
||||||
$this->assertEquals('', $result['plugin_name']['parameters']['param3']);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -76,7 +76,7 @@ public function testRSSBuildData()
|
||||||
// Test headers (RSS)
|
// Test headers (RSS)
|
||||||
$this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
|
$this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
|
||||||
$this->assertEmpty($data['pubsubhub_url']);
|
$this->assertEmpty($data['pubsubhub_url']);
|
||||||
$this->assertEquals('Tue, 10 Mar 2015 11:46:51 +0100', $data['last_update']);
|
$this->assertRegExp('/Tue, 10 Mar 2015 11:46:51 \+\d{4}/', $data['last_update']);
|
||||||
$this->assertEquals(true, $data['show_dates']);
|
$this->assertEquals(true, $data['show_dates']);
|
||||||
$this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']);
|
$this->assertEquals('http://host.tld/index.php?do=feed', $data['self_link']);
|
||||||
$this->assertEquals('http://host.tld/', $data['index_url']);
|
$this->assertEquals('http://host.tld/', $data['index_url']);
|
||||||
|
@ -88,7 +88,7 @@ public function testRSSBuildData()
|
||||||
$this->assertEquals('20150310_114651', $link['linkdate']);
|
$this->assertEquals('20150310_114651', $link['linkdate']);
|
||||||
$this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
|
$this->assertEquals('http://host.tld/?WDWyig', $link['guid']);
|
||||||
$this->assertEquals('http://host.tld/?WDWyig', $link['url']);
|
$this->assertEquals('http://host.tld/?WDWyig', $link['url']);
|
||||||
$this->assertEquals('Tue, 10 Mar 2015 11:46:51 +0100', $link['iso_date']);
|
$this->assertRegExp('/Tue, 10 Mar 2015 11:46:51 \+\d{4}/', $link['iso_date']);
|
||||||
$this->assertContains('Stallman has a beard', $link['description']);
|
$this->assertContains('Stallman has a beard', $link['description']);
|
||||||
$this->assertContains('Permalink', $link['description']);
|
$this->assertContains('Permalink', $link['description']);
|
||||||
$this->assertContains('http://host.tld/?WDWyig', $link['description']);
|
$this->assertContains('http://host.tld/?WDWyig', $link['description']);
|
||||||
|
@ -113,7 +113,7 @@ public function testAtomBuildData()
|
||||||
$data = $feedBuilder->buildData();
|
$data = $feedBuilder->buildData();
|
||||||
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
|
$this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
|
||||||
$link = array_shift($data['links']);
|
$link = array_shift($data['links']);
|
||||||
$this->assertEquals('2015-03-10T11:46:51+01:00', $link['iso_date']);
|
$this->assertRegExp('/2015-03-10T11:46:51\+\d{2}:+\d{2}/', $link['iso_date']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -101,7 +101,7 @@ public function testConstructLoggedOut()
|
||||||
* Attempt to instantiate a LinkDB whereas the datastore is not writable
|
* Attempt to instantiate a LinkDB whereas the datastore is not writable
|
||||||
*
|
*
|
||||||
* @expectedException IOException
|
* @expectedException IOException
|
||||||
* @expectedExceptionMessageRegExp /Error accessing null/
|
* @expectedExceptionMessageRegExp /Error accessing\nnull/
|
||||||
*/
|
*/
|
||||||
public function testConstructDatastoreNotWriteable()
|
public function testConstructDatastoreNotWriteable()
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,17 @@ class PluginManagerTest extends PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
private static $pluginName = 'test';
|
private static $pluginName = 'test';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PluginManager $pluginManager Plugin Mananger instance.
|
||||||
|
*/
|
||||||
|
protected $pluginManager;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$conf = new ConfigManager('');
|
||||||
|
$this->pluginManager = new PluginManager($conf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test plugin loading and hook execution.
|
* Test plugin loading and hook execution.
|
||||||
*
|
*
|
||||||
|
@ -30,23 +41,21 @@ class PluginManagerTest extends PHPUnit_Framework_TestCase
|
||||||
*/
|
*/
|
||||||
public function testPlugin()
|
public function testPlugin()
|
||||||
{
|
{
|
||||||
$pluginManager = PluginManager::getInstance();
|
|
||||||
|
|
||||||
PluginManager::$PLUGINS_PATH = self::$pluginPath;
|
PluginManager::$PLUGINS_PATH = self::$pluginPath;
|
||||||
$pluginManager->load(array(self::$pluginName));
|
$this->pluginManager->load(array(self::$pluginName));
|
||||||
|
|
||||||
$this->assertTrue(function_exists('hook_test_random'));
|
$this->assertTrue(function_exists('hook_test_random'));
|
||||||
|
|
||||||
$data = array(0 => 'woot');
|
$data = array(0 => 'woot');
|
||||||
$pluginManager->executeHooks('random', $data);
|
$this->pluginManager->executeHooks('random', $data);
|
||||||
$this->assertEquals('woot', $data[1]);
|
$this->assertEquals('woot', $data[1]);
|
||||||
|
|
||||||
$data = array(0 => 'woot');
|
$data = array(0 => 'woot');
|
||||||
$pluginManager->executeHooks('random', $data, array('target' => 'test'));
|
$this->pluginManager->executeHooks('random', $data, array('target' => 'test'));
|
||||||
$this->assertEquals('page test', $data[1]);
|
$this->assertEquals('page test', $data[1]);
|
||||||
|
|
||||||
$data = array(0 => 'woot');
|
$data = array(0 => 'woot');
|
||||||
$pluginManager->executeHooks('random', $data, array('loggedin' => true));
|
$this->pluginManager->executeHooks('random', $data, array('loggedin' => true));
|
||||||
$this->assertEquals('loggedin', $data[1]);
|
$this->assertEquals('loggedin', $data[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,11 +66,8 @@ public function testPlugin()
|
||||||
*/
|
*/
|
||||||
public function testPluginNotFound()
|
public function testPluginNotFound()
|
||||||
{
|
{
|
||||||
$pluginManager = PluginManager::getInstance();
|
$this->pluginManager->load(array());
|
||||||
|
$this->pluginManager->load(array('nope', 'renope'));
|
||||||
$pluginManager->load(array());
|
|
||||||
|
|
||||||
$pluginManager->load(array('nope', 'renope'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,16 +75,14 @@ public function testPluginNotFound()
|
||||||
*/
|
*/
|
||||||
public function testGetPluginsMeta()
|
public function testGetPluginsMeta()
|
||||||
{
|
{
|
||||||
$pluginManager = PluginManager::getInstance();
|
|
||||||
|
|
||||||
PluginManager::$PLUGINS_PATH = self::$pluginPath;
|
PluginManager::$PLUGINS_PATH = self::$pluginPath;
|
||||||
$pluginManager->load(array(self::$pluginName));
|
$this->pluginManager->load(array(self::$pluginName));
|
||||||
|
|
||||||
$expectedParameters = array(
|
$expectedParameters = array(
|
||||||
'pop' => '',
|
'pop' => '',
|
||||||
'hip' => '',
|
'hip' => '',
|
||||||
);
|
);
|
||||||
$meta = $pluginManager->getPluginsMeta();
|
$meta = $this->pluginManager->getPluginsMeta();
|
||||||
$this->assertEquals('test plugin', $meta[self::$pluginName]['description']);
|
$this->assertEquals('test plugin', $meta[self::$pluginName]['description']);
|
||||||
$this->assertEquals($expectedParameters, $meta[self::$pluginName]['parameters']);
|
$this->assertEquals($expectedParameters, $meta[self::$pluginName]['parameters']);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ class DummyUpdater extends Updater
|
||||||
/**
|
/**
|
||||||
* Object constructor.
|
* Object constructor.
|
||||||
*
|
*
|
||||||
* @param array $doneUpdates Updates which are already done.
|
* @param array $doneUpdates Updates which are already done.
|
||||||
* @param array $config Shaarli's configuration array.
|
* @param LinkDB $linkDB LinkDB instance.
|
||||||
* @param LinkDB $linkDB LinkDB instance.
|
* @param ConfigManager $conf Configuration Manager instance.
|
||||||
* @param boolean $isLoggedIn True if the user is logged in.
|
* @param boolean $isLoggedIn True if the user is logged in.
|
||||||
*/
|
*/
|
||||||
public function __construct($doneUpdates, $config, $linkDB, $isLoggedIn)
|
public function __construct($doneUpdates, $linkDB, $conf, $isLoggedIn)
|
||||||
{
|
{
|
||||||
parent::__construct($doneUpdates, $config, $linkDB, $isLoggedIn);
|
parent::__construct($doneUpdates, $linkDB, $conf, $isLoggedIn);
|
||||||
|
|
||||||
// Retrieve all update methods.
|
// Retrieve all update methods.
|
||||||
// For unit test, only retrieve final methods,
|
// For unit test, only retrieve final methods,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
require_once 'application/config/ConfigManager.php';
|
||||||
require_once 'tests/Updater/DummyUpdater.php';
|
require_once 'tests/Updater/DummyUpdater.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,59 +9,27 @@
|
||||||
*/
|
*/
|
||||||
class UpdaterTest extends PHPUnit_Framework_TestCase
|
class UpdaterTest extends PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var array Configuration input set.
|
|
||||||
*/
|
|
||||||
private static $configFields;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Path to test datastore.
|
* @var string Path to test datastore.
|
||||||
*/
|
*/
|
||||||
protected static $testDatastore = 'sandbox/datastore.php';
|
protected static $testDatastore = 'sandbox/datastore.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string Config file path (without extension).
|
||||||
|
*/
|
||||||
|
protected static $configFile = 'tests/utils/config/configJson';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ConfigManager
|
||||||
|
*/
|
||||||
|
protected $conf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executed before each test.
|
* Executed before each test.
|
||||||
*/
|
*/
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
self::$configFields = array(
|
$this->conf = new ConfigManager(self::$configFile);
|
||||||
'login' => 'login',
|
|
||||||
'hash' => 'hash',
|
|
||||||
'salt' => 'salt',
|
|
||||||
'timezone' => 'Europe/Paris',
|
|
||||||
'title' => 'title',
|
|
||||||
'titleLink' => 'titleLink',
|
|
||||||
'redirector' => '',
|
|
||||||
'disablesessionprotection' => false,
|
|
||||||
'privateLinkByDefault' => false,
|
|
||||||
'config' => array(
|
|
||||||
'CONFIG_FILE' => 'tests/Updater/config.php',
|
|
||||||
'DATADIR' => 'tests/Updater',
|
|
||||||
'PAGECACHE' => 'sandbox/pagecache',
|
|
||||||
'config1' => 'config1data',
|
|
||||||
'config2' => 'config2data',
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed after each test.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function tearDown()
|
|
||||||
{
|
|
||||||
if (is_file(self::$configFields['config']['CONFIG_FILE'])) {
|
|
||||||
unlink(self::$configFields['config']['CONFIG_FILE']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_file(self::$configFields['config']['DATADIR'] . '/options.php')) {
|
|
||||||
unlink(self::$configFields['config']['DATADIR'] . '/options.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_file(self::$configFields['config']['DATADIR'] . '/updates.json')) {
|
|
||||||
unlink(self::$configFields['config']['DATADIR'] . '/updates.json');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,9 +38,10 @@ public function tearDown()
|
||||||
public function testReadEmptyUpdatesFile()
|
public function testReadEmptyUpdatesFile()
|
||||||
{
|
{
|
||||||
$this->assertEquals(array(), read_updates_file(''));
|
$this->assertEquals(array(), read_updates_file(''));
|
||||||
$updatesFile = self::$configFields['config']['DATADIR'] . '/updates.json';
|
$updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
|
||||||
touch($updatesFile);
|
touch($updatesFile);
|
||||||
$this->assertEquals(array(), read_updates_file($updatesFile));
|
$this->assertEquals(array(), read_updates_file($updatesFile));
|
||||||
|
unlink($updatesFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +49,7 @@ public function testReadEmptyUpdatesFile()
|
||||||
*/
|
*/
|
||||||
public function testReadWriteUpdatesFile()
|
public function testReadWriteUpdatesFile()
|
||||||
{
|
{
|
||||||
$updatesFile = self::$configFields['config']['DATADIR'] . '/updates.json';
|
$updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
|
||||||
$updatesMethods = array('m1', 'm2', 'm3');
|
$updatesMethods = array('m1', 'm2', 'm3');
|
||||||
|
|
||||||
write_updates_file($updatesFile, $updatesMethods);
|
write_updates_file($updatesFile, $updatesMethods);
|
||||||
|
@ -91,6 +61,7 @@ public function testReadWriteUpdatesFile()
|
||||||
write_updates_file($updatesFile, $updatesMethods);
|
write_updates_file($updatesFile, $updatesMethods);
|
||||||
$readMethods = read_updates_file($updatesFile);
|
$readMethods = read_updates_file($updatesFile);
|
||||||
$this->assertEquals($readMethods, $updatesMethods);
|
$this->assertEquals($readMethods, $updatesMethods);
|
||||||
|
unlink($updatesFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -112,10 +83,15 @@ public function testWriteEmptyUpdatesFile()
|
||||||
*/
|
*/
|
||||||
public function testWriteUpdatesFileNotWritable()
|
public function testWriteUpdatesFileNotWritable()
|
||||||
{
|
{
|
||||||
$updatesFile = self::$configFields['config']['DATADIR'] . '/updates.json';
|
$updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
|
||||||
touch($updatesFile);
|
touch($updatesFile);
|
||||||
chmod($updatesFile, 0444);
|
chmod($updatesFile, 0444);
|
||||||
@write_updates_file($updatesFile, array('test'));
|
try {
|
||||||
|
@write_updates_file($updatesFile, array('test'));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
unlink($updatesFile);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,10 +107,10 @@ public function testNoUpdates()
|
||||||
'updateMethodDummy3',
|
'updateMethodDummy3',
|
||||||
'updateMethodException',
|
'updateMethodException',
|
||||||
);
|
);
|
||||||
$updater = new DummyUpdater($updates, array(), array(), true);
|
$updater = new DummyUpdater($updates, array(), $this->conf, true);
|
||||||
$this->assertEquals(array(), $updater->update());
|
$this->assertEquals(array(), $updater->update());
|
||||||
|
|
||||||
$updater = new DummyUpdater(array(), array(), array(), false);
|
$updater = new DummyUpdater(array(), array(), $this->conf, false);
|
||||||
$this->assertEquals(array(), $updater->update());
|
$this->assertEquals(array(), $updater->update());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +125,7 @@ public function testUpdatesFirstTime()
|
||||||
'updateMethodDummy2',
|
'updateMethodDummy2',
|
||||||
'updateMethodDummy3',
|
'updateMethodDummy3',
|
||||||
);
|
);
|
||||||
$updater = new DummyUpdater($updates, array(), array(), true);
|
$updater = new DummyUpdater($updates, array(), $this->conf, true);
|
||||||
$this->assertEquals($expectedUpdates, $updater->update());
|
$this->assertEquals($expectedUpdates, $updater->update());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +141,7 @@ public function testOneUpdate()
|
||||||
);
|
);
|
||||||
$expectedUpdate = array('updateMethodDummy2');
|
$expectedUpdate = array('updateMethodDummy2');
|
||||||
|
|
||||||
$updater = new DummyUpdater($updates, array(), array(), true);
|
$updater = new DummyUpdater($updates, array(), $this->conf, true);
|
||||||
$this->assertEquals($expectedUpdate, $updater->update());
|
$this->assertEquals($expectedUpdate, $updater->update());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +158,7 @@ public function testUpdateFailed()
|
||||||
'updateMethodDummy3',
|
'updateMethodDummy3',
|
||||||
);
|
);
|
||||||
|
|
||||||
$updater = new DummyUpdater($updates, array(), array(), true);
|
$updater = new DummyUpdater($updates, array(), $this->conf, true);
|
||||||
$updater->update();
|
$updater->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,26 +171,28 @@ public function testUpdateFailed()
|
||||||
*/
|
*/
|
||||||
public function testUpdateMergeDeprecatedConfig()
|
public function testUpdateMergeDeprecatedConfig()
|
||||||
{
|
{
|
||||||
// init
|
$this->conf->setConfigFile('tests/utils/config/configPhp');
|
||||||
writeConfig(self::$configFields, true);
|
$this->conf->reset();
|
||||||
$configCopy = self::$configFields;
|
|
||||||
$invert = !$configCopy['privateLinkByDefault'];
|
|
||||||
$configCopy['privateLinkByDefault'] = $invert;
|
|
||||||
|
|
||||||
// Use writeConfig to create a options.php
|
$optionsFile = 'tests/Updater/options.php';
|
||||||
$configCopy['config']['CONFIG_FILE'] = 'tests/Updater/options.php';
|
$options = '<?php
|
||||||
writeConfig($configCopy, true);
|
$GLOBALS[\'privateLinkByDefault\'] = true;';
|
||||||
|
file_put_contents($optionsFile, $options);
|
||||||
|
|
||||||
$this->assertTrue(is_file($configCopy['config']['CONFIG_FILE']));
|
// tmp config file.
|
||||||
|
$this->conf->setConfigFile('tests/Updater/config');
|
||||||
|
|
||||||
// merge configs
|
// merge configs
|
||||||
$updater = new Updater(array(), self::$configFields, array(), true);
|
$updater = new Updater(array(), array(), $this->conf, true);
|
||||||
|
// This writes a new config file in tests/Updater/config.php
|
||||||
$updater->updateMethodMergeDeprecatedConfigFile();
|
$updater->updateMethodMergeDeprecatedConfigFile();
|
||||||
|
|
||||||
// make sure updated field is changed
|
// make sure updated field is changed
|
||||||
include self::$configFields['config']['CONFIG_FILE'];
|
$this->conf->reload();
|
||||||
$this->assertEquals($invert, $GLOBALS['privateLinkByDefault']);
|
$this->assertTrue($this->conf->get('privacy.default_private_links'));
|
||||||
$this->assertFalse(is_file($configCopy['config']['CONFIG_FILE']));
|
$this->assertFalse(is_file($optionsFile));
|
||||||
|
// Delete the generated file.
|
||||||
|
unlink($this->conf->getConfigFileExt());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -222,23 +200,67 @@ public function testUpdateMergeDeprecatedConfig()
|
||||||
*/
|
*/
|
||||||
public function testMergeDeprecatedConfigNoFile()
|
public function testMergeDeprecatedConfigNoFile()
|
||||||
{
|
{
|
||||||
writeConfig(self::$configFields, true);
|
$updater = new Updater(array(), array(), $this->conf, true);
|
||||||
|
|
||||||
$updater = new Updater(array(), self::$configFields, array(), true);
|
|
||||||
$updater->updateMethodMergeDeprecatedConfigFile();
|
$updater->updateMethodMergeDeprecatedConfigFile();
|
||||||
|
|
||||||
include self::$configFields['config']['CONFIG_FILE'];
|
$this->assertEquals('root', $this->conf->get('credentials.login'));
|
||||||
$this->assertEquals(self::$configFields['login'], $GLOBALS['login']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test renameDashTags update method.
|
||||||
|
*/
|
||||||
public function testRenameDashTags()
|
public function testRenameDashTags()
|
||||||
{
|
{
|
||||||
$refDB = new ReferenceLinkDB();
|
$refDB = new ReferenceLinkDB();
|
||||||
$refDB->write(self::$testDatastore);
|
$refDB->write(self::$testDatastore);
|
||||||
$linkDB = new LinkDB(self::$testDatastore, true, false);
|
$linkDB = new LinkDB(self::$testDatastore, true, false);
|
||||||
$this->assertEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
|
$this->assertEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
|
||||||
$updater = new Updater(array(), self::$configFields, $linkDB, true);
|
$updater = new Updater(array(), $linkDB, $this->conf, true);
|
||||||
$updater->updateMethodRenameDashTags();
|
$updater->updateMethodRenameDashTags();
|
||||||
$this->assertNotEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
|
$this->assertNotEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert old PHP config file to JSON config.
|
||||||
|
*/
|
||||||
|
public function testConfigToJson()
|
||||||
|
{
|
||||||
|
$configFile = 'tests/utils/config/configPhp';
|
||||||
|
$this->conf->setConfigFile($configFile);
|
||||||
|
$this->conf->reset();
|
||||||
|
|
||||||
|
// The ConfigIO is initialized with ConfigPhp.
|
||||||
|
$this->assertTrue($this->conf->getConfigIO() instanceof ConfigPhp);
|
||||||
|
|
||||||
|
$updater = new Updater(array(), array(), $this->conf, false);
|
||||||
|
$done = $updater->updateMethodConfigToJson();
|
||||||
|
$this->assertTrue($done);
|
||||||
|
|
||||||
|
// The ConfigIO has been updated to ConfigJson.
|
||||||
|
$this->assertTrue($this->conf->getConfigIO() instanceof ConfigJson);
|
||||||
|
$this->assertTrue(file_exists($this->conf->getConfigFileExt()));
|
||||||
|
|
||||||
|
// Check JSON config data.
|
||||||
|
$this->conf->reload();
|
||||||
|
$this->assertEquals('root', $this->conf->get('credentials.login'));
|
||||||
|
$this->assertEquals('lala', $this->conf->get('redirector.url'));
|
||||||
|
$this->assertEquals('data/datastore.php', $this->conf->get('resource.datastore'));
|
||||||
|
$this->assertEquals('1', $this->conf->get('plugins.WALLABAG_VERSION'));
|
||||||
|
|
||||||
|
rename($configFile . '.save.php', $configFile . '.php');
|
||||||
|
unlink($this->conf->getConfigFileExt());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch config conversion update with an existing JSON file => nothing to do.
|
||||||
|
*/
|
||||||
|
public function testConfigToJsonNothingToDo()
|
||||||
|
{
|
||||||
|
$filetime = filemtime($this->conf->getConfigFileExt());
|
||||||
|
$updater = new Updater(array(), array(), $this->conf, false);
|
||||||
|
$done = $updater->updateMethodConfigToJson();
|
||||||
|
$this->assertTrue($done);
|
||||||
|
$expected = filemtime($this->conf->getConfigFileExt());
|
||||||
|
$this->assertEquals($expected, $filetime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
133
tests/config/ConfigJsonTest.php
Normal file
133
tests/config/ConfigJsonTest.php
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'application/config/ConfigJson.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConfigJsonTest
|
||||||
|
*/
|
||||||
|
class ConfigJsonTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConfigJson
|
||||||
|
*/
|
||||||
|
protected $configIO;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->configIO = new ConfigJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a simple existing config file.
|
||||||
|
*/
|
||||||
|
public function testRead()
|
||||||
|
{
|
||||||
|
$conf = $this->configIO->read('tests/utils/config/configJson.json.php');
|
||||||
|
$this->assertEquals('root', $conf['credentials']['login']);
|
||||||
|
$this->assertEquals('lala', $conf['redirector']['url']);
|
||||||
|
$this->assertEquals('tests/utils/config/datastore.php', $conf['resource']['datastore']);
|
||||||
|
$this->assertEquals('1', $conf['plugins']['WALLABAG_VERSION']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a non existent config file -> empty array.
|
||||||
|
*/
|
||||||
|
public function testReadNonExistent()
|
||||||
|
{
|
||||||
|
$this->assertEquals(array(), $this->configIO->read('nope'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a non existent config file -> empty array.
|
||||||
|
*
|
||||||
|
* @expectedException Exception
|
||||||
|
* @expectedExceptionMessage An error occured while parsing JSON file: error code #4
|
||||||
|
*/
|
||||||
|
public function testReadInvalidJson()
|
||||||
|
{
|
||||||
|
$this->configIO->read('tests/utils/config/configInvalid.json.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a new config file.
|
||||||
|
*/
|
||||||
|
public function testWriteNew()
|
||||||
|
{
|
||||||
|
$dataFile = 'tests/utils/config/configWrite.json.php';
|
||||||
|
$data = array(
|
||||||
|
'credentials' => array(
|
||||||
|
'login' => 'root',
|
||||||
|
),
|
||||||
|
'resource' => array(
|
||||||
|
'datastore' => 'data/datastore.php',
|
||||||
|
),
|
||||||
|
'redirector' => array(
|
||||||
|
'url' => 'lala',
|
||||||
|
),
|
||||||
|
'plugins' => array(
|
||||||
|
'WALLABAG_VERSION' => '1',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->configIO->write($dataFile, $data);
|
||||||
|
// PHP 5.3 doesn't support json pretty print.
|
||||||
|
if (defined('JSON_PRETTY_PRINT')) {
|
||||||
|
$expected = '{
|
||||||
|
"credentials": {
|
||||||
|
"login": "root"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"datastore": "data\/datastore.php"
|
||||||
|
},
|
||||||
|
"redirector": {
|
||||||
|
"url": "lala"
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"WALLABAG_VERSION": "1"
|
||||||
|
}
|
||||||
|
}';
|
||||||
|
} else {
|
||||||
|
$expected = '{"credentials":{"login":"root"},"resource":{"datastore":"data\/datastore.php"},"redirector":{"url":"lala"},"plugins":{"WALLABAG_VERSION":"1"}}';
|
||||||
|
}
|
||||||
|
$expected = ConfigJson::getPhpHeaders() . $expected . ConfigJson::getPhpSuffix();
|
||||||
|
$this->assertEquals($expected, file_get_contents($dataFile));
|
||||||
|
unlink($dataFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrite an existing setting.
|
||||||
|
*/
|
||||||
|
public function testOverwrite()
|
||||||
|
{
|
||||||
|
$source = 'tests/utils/config/configJson.json.php';
|
||||||
|
$dest = 'tests/utils/config/configOverwrite.json.php';
|
||||||
|
copy($source, $dest);
|
||||||
|
$conf = $this->configIO->read($dest);
|
||||||
|
$conf['redirector']['url'] = 'blabla';
|
||||||
|
$this->configIO->write($dest, $conf);
|
||||||
|
$conf = $this->configIO->read($dest);
|
||||||
|
$this->assertEquals('blabla', $conf['redirector']['url']);
|
||||||
|
unlink($dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to invalid path.
|
||||||
|
*
|
||||||
|
* @expectedException IOException
|
||||||
|
*/
|
||||||
|
public function testWriteInvalidArray()
|
||||||
|
{
|
||||||
|
$conf = array('conf' => 'value');
|
||||||
|
@$this->configIO->write(array(), $conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to invalid path.
|
||||||
|
*
|
||||||
|
* @expectedException IOException
|
||||||
|
*/
|
||||||
|
public function testWriteInvalidBlank()
|
||||||
|
{
|
||||||
|
$conf = array('conf' => 'value');
|
||||||
|
@$this->configIO->write('', $conf);
|
||||||
|
}
|
||||||
|
}
|
172
tests/config/ConfigManagerTest.php
Normal file
172
tests/config/ConfigManagerTest.php
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for Class ConfigManagerTest
|
||||||
|
*
|
||||||
|
* Note: it only test the manager with ConfigJson,
|
||||||
|
* ConfigPhp is only a workaround to handle the transition to JSON type.
|
||||||
|
*/
|
||||||
|
class ConfigManagerTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConfigManager
|
||||||
|
*/
|
||||||
|
protected $conf;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->conf = new ConfigManager('tests/utils/config/configJson');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple config test:
|
||||||
|
* 1. Set settings.
|
||||||
|
* 2. Check settings value.
|
||||||
|
*/
|
||||||
|
public function testSetGet()
|
||||||
|
{
|
||||||
|
$this->conf->set('paramInt', 42);
|
||||||
|
$this->conf->set('paramString', 'value1');
|
||||||
|
$this->conf->set('paramBool', false);
|
||||||
|
$this->conf->set('paramArray', array('foo' => 'bar'));
|
||||||
|
$this->conf->set('paramNull', null);
|
||||||
|
|
||||||
|
$this->assertEquals(42, $this->conf->get('paramInt'));
|
||||||
|
$this->assertEquals('value1', $this->conf->get('paramString'));
|
||||||
|
$this->assertFalse($this->conf->get('paramBool'));
|
||||||
|
$this->assertEquals(array('foo' => 'bar'), $this->conf->get('paramArray'));
|
||||||
|
$this->assertEquals(null, $this->conf->get('paramNull'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set/write/get config test:
|
||||||
|
* 1. Set settings.
|
||||||
|
* 2. Write it to the config file.
|
||||||
|
* 3. Read the file.
|
||||||
|
* 4. Check settings value.
|
||||||
|
*/
|
||||||
|
public function testSetWriteGet()
|
||||||
|
{
|
||||||
|
$this->conf->set('paramInt', 42);
|
||||||
|
$this->conf->set('paramString', 'value1');
|
||||||
|
$this->conf->set('paramBool', false);
|
||||||
|
$this->conf->set('paramArray', array('foo' => 'bar'));
|
||||||
|
$this->conf->set('paramNull', null);
|
||||||
|
|
||||||
|
$this->conf->setConfigFile('tests/utils/config/configTmp');
|
||||||
|
$this->conf->write(true);
|
||||||
|
$this->conf->reload();
|
||||||
|
unlink($this->conf->getConfigFileExt());
|
||||||
|
|
||||||
|
$this->assertEquals(42, $this->conf->get('paramInt'));
|
||||||
|
$this->assertEquals('value1', $this->conf->get('paramString'));
|
||||||
|
$this->assertFalse($this->conf->get('paramBool'));
|
||||||
|
$this->assertEquals(array('foo' => 'bar'), $this->conf->get('paramArray'));
|
||||||
|
$this->assertEquals(null, $this->conf->get('paramNull'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test set/write/get with nested keys.
|
||||||
|
*/
|
||||||
|
public function testSetWriteGetNested()
|
||||||
|
{
|
||||||
|
$this->conf->set('foo.bar.key.stuff', 'testSetWriteGetNested');
|
||||||
|
|
||||||
|
$this->conf->setConfigFile('tests/utils/config/configTmp');
|
||||||
|
$this->conf->write(true);
|
||||||
|
$this->conf->reload();
|
||||||
|
unlink($this->conf->getConfigFileExt());
|
||||||
|
|
||||||
|
$this->assertEquals('testSetWriteGetNested', $this->conf->get('foo.bar.key.stuff'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set with an empty key.
|
||||||
|
*
|
||||||
|
* @expectedException Exception
|
||||||
|
* @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*#
|
||||||
|
*/
|
||||||
|
public function testSetEmptyKey()
|
||||||
|
{
|
||||||
|
$this->conf->set('', 'stuff');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set with an array key.
|
||||||
|
*
|
||||||
|
* @expectedException Exception
|
||||||
|
* @expectedExceptionMessageRegExp #^Invalid setting key parameter. String expected, got.*#
|
||||||
|
*/
|
||||||
|
public function testSetArrayKey()
|
||||||
|
{
|
||||||
|
$this->conf->set(array('foo' => 'bar'), 'stuff');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to write the config without mandatory parameter (e.g. 'login').
|
||||||
|
*
|
||||||
|
* @expectedException MissingFieldConfigException
|
||||||
|
*/
|
||||||
|
public function testWriteMissingParameter()
|
||||||
|
{
|
||||||
|
$this->conf->setConfigFile('tests/utils/config/configTmp');
|
||||||
|
$this->assertFalse(file_exists($this->conf->getConfigFileExt()));
|
||||||
|
$this->conf->reload();
|
||||||
|
|
||||||
|
$this->conf->write(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to get non existent config keys.
|
||||||
|
*/
|
||||||
|
public function testGetNonExistent()
|
||||||
|
{
|
||||||
|
$this->assertEquals('', $this->conf->get('nope.test'));
|
||||||
|
$this->assertEquals('default', $this->conf->get('nope.test', 'default'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the 'exists' method with existent values.
|
||||||
|
*/
|
||||||
|
public function testExistsOk()
|
||||||
|
{
|
||||||
|
$this->assertTrue($this->conf->exists('credentials.login'));
|
||||||
|
$this->assertTrue($this->conf->exists('config.foo'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the 'exists' method with non existent or invalid values.
|
||||||
|
*/
|
||||||
|
public function testExistsKo()
|
||||||
|
{
|
||||||
|
$this->assertFalse($this->conf->exists('nope'));
|
||||||
|
$this->assertFalse($this->conf->exists('nope.nope'));
|
||||||
|
$this->assertFalse($this->conf->exists(''));
|
||||||
|
$this->assertFalse($this->conf->exists(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the ConfigManager instance.
|
||||||
|
*/
|
||||||
|
public function testReset()
|
||||||
|
{
|
||||||
|
$confIO = $this->conf->getConfigIO();
|
||||||
|
$this->conf->reset();
|
||||||
|
$this->assertFalse($confIO === $this->conf->getConfigIO());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload the config from file.
|
||||||
|
*/
|
||||||
|
public function testReload()
|
||||||
|
{
|
||||||
|
$this->conf->setConfigFile('tests/utils/config/configTmp');
|
||||||
|
$newConf = ConfigJson::getPhpHeaders() . '{ "key": "value" }';
|
||||||
|
file_put_contents($this->conf->getConfigFileExt(), $newConf);
|
||||||
|
$this->conf->reload();
|
||||||
|
unlink($this->conf->getConfigFileExt());
|
||||||
|
// Previous conf no longer exists, and new values have been loaded.
|
||||||
|
$this->assertFalse($this->conf->exists('credentials.login'));
|
||||||
|
$this->assertEquals('value', $this->conf->get('key'));
|
||||||
|
}
|
||||||
|
}
|
82
tests/config/ConfigPhpTest.php
Normal file
82
tests/config/ConfigPhpTest.php
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'application/config/ConfigPhp.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConfigPhpTest
|
||||||
|
*/
|
||||||
|
class ConfigPhpTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var ConfigPhp
|
||||||
|
*/
|
||||||
|
protected $configIO;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->configIO = new ConfigPhp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a simple existing config file.
|
||||||
|
*/
|
||||||
|
public function testRead()
|
||||||
|
{
|
||||||
|
$conf = $this->configIO->read('tests/utils/config/configPhp.php');
|
||||||
|
$this->assertEquals('root', $conf['login']);
|
||||||
|
$this->assertEquals('lala', $conf['redirector']);
|
||||||
|
$this->assertEquals('data/datastore.php', $conf['config']['DATASTORE']);
|
||||||
|
$this->assertEquals('1', $conf['plugins']['WALLABAG_VERSION']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a non existent config file -> empty array.
|
||||||
|
*/
|
||||||
|
public function testReadNonExistent()
|
||||||
|
{
|
||||||
|
$this->assertEquals(array(), $this->configIO->read('nope'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a new config file.
|
||||||
|
*/
|
||||||
|
public function testWriteNew()
|
||||||
|
{
|
||||||
|
$dataFile = 'tests/utils/config/configWrite.php';
|
||||||
|
$data = array(
|
||||||
|
'login' => 'root',
|
||||||
|
'redirector' => 'lala',
|
||||||
|
'config' => array(
|
||||||
|
'DATASTORE' => 'data/datastore.php',
|
||||||
|
),
|
||||||
|
'plugins' => array(
|
||||||
|
'WALLABAG_VERSION' => '1',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->configIO->write($dataFile, $data);
|
||||||
|
$expected = '<?php
|
||||||
|
$GLOBALS[\'login\'] = \'root\';
|
||||||
|
$GLOBALS[\'redirector\'] = \'lala\';
|
||||||
|
$GLOBALS[\'config\'][\'DATASTORE\'] = \'data/datastore.php\';
|
||||||
|
$GLOBALS[\'plugins\'][\'WALLABAG_VERSION\'] = \'1\';
|
||||||
|
';
|
||||||
|
$this->assertEquals($expected, file_get_contents($dataFile));
|
||||||
|
unlink($dataFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrite an existing setting.
|
||||||
|
*/
|
||||||
|
public function testOverwrite()
|
||||||
|
{
|
||||||
|
$source = 'tests/utils/config/configPhp.php';
|
||||||
|
$dest = 'tests/utils/config/configOverwrite.php';
|
||||||
|
copy($source, $dest);
|
||||||
|
$conf = $this->configIO->read($dest);
|
||||||
|
$conf['redirector'] = 'blabla';
|
||||||
|
$this->configIO->write($dest, $conf);
|
||||||
|
$conf = $this->configIO->read($dest);
|
||||||
|
$this->assertEquals('blabla', $conf['redirector']);
|
||||||
|
unlink($dest);
|
||||||
|
}
|
||||||
|
}
|
121
tests/config/ConfigPluginTest.php
Normal file
121
tests/config/ConfigPluginTest.php
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Config' tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once 'application/config/ConfigPlugin.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unitary tests for Shaarli config related functions
|
||||||
|
*/
|
||||||
|
class ConfigPluginTest extends PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Test save_plugin_config with valid data.
|
||||||
|
*
|
||||||
|
* @throws PluginConfigOrderException
|
||||||
|
*/
|
||||||
|
public function testSavePluginConfigValid()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
'order_plugin1' => 2, // no plugin related
|
||||||
|
'plugin2' => 0, // new - at the end
|
||||||
|
'plugin3' => 0, // 2nd
|
||||||
|
'order_plugin3' => 8,
|
||||||
|
'plugin4' => 0, // 1st
|
||||||
|
'order_plugin4' => 5,
|
||||||
|
);
|
||||||
|
|
||||||
|
$expected = array(
|
||||||
|
'plugin3',
|
||||||
|
'plugin4',
|
||||||
|
'plugin2',
|
||||||
|
);
|
||||||
|
|
||||||
|
$out = save_plugin_config($data);
|
||||||
|
$this->assertEquals($expected, $out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test save_plugin_config with invalid data.
|
||||||
|
*
|
||||||
|
* @expectedException PluginConfigOrderException
|
||||||
|
*/
|
||||||
|
public function testSavePluginConfigInvalid()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
'plugin2' => 0,
|
||||||
|
'plugin3' => 0,
|
||||||
|
'order_plugin3' => 0,
|
||||||
|
'plugin4' => 0,
|
||||||
|
'order_plugin4' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
save_plugin_config($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test save_plugin_config without data.
|
||||||
|
*/
|
||||||
|
public function testSavePluginConfigEmpty()
|
||||||
|
{
|
||||||
|
$this->assertEquals(array(), save_plugin_config(array()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test validate_plugin_order with valid data.
|
||||||
|
*/
|
||||||
|
public function testValidatePluginOrderValid()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
'order_plugin1' => 2,
|
||||||
|
'plugin2' => 0,
|
||||||
|
'plugin3' => 0,
|
||||||
|
'order_plugin3' => 1,
|
||||||
|
'plugin4' => 0,
|
||||||
|
'order_plugin4' => 5,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertTrue(validate_plugin_order($data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test validate_plugin_order with invalid data.
|
||||||
|
*/
|
||||||
|
public function testValidatePluginOrderInvalid()
|
||||||
|
{
|
||||||
|
$data = array(
|
||||||
|
'order_plugin1' => 2,
|
||||||
|
'order_plugin3' => 1,
|
||||||
|
'order_plugin4' => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertFalse(validate_plugin_order($data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test load_plugin_parameter_values.
|
||||||
|
*/
|
||||||
|
public function testLoadPluginParameterValues()
|
||||||
|
{
|
||||||
|
$plugins = array(
|
||||||
|
'plugin_name' => array(
|
||||||
|
'parameters' => array(
|
||||||
|
'param1' => true,
|
||||||
|
'param2' => false,
|
||||||
|
'param3' => '',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$parameters = array(
|
||||||
|
'param1' => 'value1',
|
||||||
|
'param2' => 'value2',
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = load_plugin_parameter_values($plugins, $parameters);
|
||||||
|
$this->assertEquals('value1', $result['plugin_name']['parameters']['param1']);
|
||||||
|
$this->assertEquals('value2', $result['plugin_name']['parameters']['param2']);
|
||||||
|
$this->assertEquals('', $result['plugin_name']['parameters']['param3']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,8 @@
|
||||||
* PluginReadityourselfTest.php.php
|
* PluginReadityourselfTest.php.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// FIXME! add an init method.
|
||||||
|
$conf = new ConfigManager('');
|
||||||
require_once 'plugins/readityourself/readityourself.php';
|
require_once 'plugins/readityourself/readityourself.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +27,8 @@ function setUp()
|
||||||
*/
|
*/
|
||||||
function testReadityourselfLinklist()
|
function testReadityourselfLinklist()
|
||||||
{
|
{
|
||||||
$GLOBALS['plugins']['READITYOUSELF_URL'] = 'value';
|
$conf = new ConfigManager('');
|
||||||
|
$conf->set('plugins.READITYOUSELF_URL', 'value');
|
||||||
$str = 'http://randomstr.com/test';
|
$str = 'http://randomstr.com/test';
|
||||||
$data = array(
|
$data = array(
|
||||||
'title' => $str,
|
'title' => $str,
|
||||||
|
@ -36,7 +39,7 @@ function testReadityourselfLinklist()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$data = hook_readityourself_render_linklist($data);
|
$data = hook_readityourself_render_linklist($data, $conf);
|
||||||
$link = $data['links'][0];
|
$link = $data['links'][0];
|
||||||
// data shouldn't be altered
|
// data shouldn't be altered
|
||||||
$this->assertEquals($str, $data['title']);
|
$this->assertEquals($str, $data['title']);
|
||||||
|
@ -52,7 +55,8 @@ function testReadityourselfLinklist()
|
||||||
*/
|
*/
|
||||||
function testReadityourselfLinklistWithoutConfig()
|
function testReadityourselfLinklistWithoutConfig()
|
||||||
{
|
{
|
||||||
unset($GLOBALS['plugins']['READITYOUSELF_URL']);
|
$conf = new ConfigManager('');
|
||||||
|
$conf->set('plugins.READITYOUSELF_URL', null);
|
||||||
$str = 'http://randomstr.com/test';
|
$str = 'http://randomstr.com/test';
|
||||||
$data = array(
|
$data = array(
|
||||||
'title' => $str,
|
'title' => $str,
|
||||||
|
@ -63,7 +67,7 @@ function testReadityourselfLinklistWithoutConfig()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$data = hook_readityourself_render_linklist($data);
|
$data = hook_readityourself_render_linklist($data, $conf);
|
||||||
$link = $data['links'][0];
|
$link = $data['links'][0];
|
||||||
// data shouldn't be altered
|
// data shouldn't be altered
|
||||||
$this->assertEquals($str, $data['title']);
|
$this->assertEquals($str, $data['title']);
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
* PluginWallabagTest.php.php
|
* PluginWallabagTest.php.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// FIXME! add an init method.
|
||||||
|
$conf = new ConfigManager('');
|
||||||
require_once 'plugins/wallabag/wallabag.php';
|
require_once 'plugins/wallabag/wallabag.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +27,8 @@ function setUp()
|
||||||
*/
|
*/
|
||||||
function testWallabagLinklist()
|
function testWallabagLinklist()
|
||||||
{
|
{
|
||||||
$GLOBALS['plugins']['WALLABAG_URL'] = 'value';
|
$conf = new ConfigManager('');
|
||||||
|
$conf->set('plugins.WALLABAG_URL', 'value');
|
||||||
$str = 'http://randomstr.com/test';
|
$str = 'http://randomstr.com/test';
|
||||||
$data = array(
|
$data = array(
|
||||||
'title' => $str,
|
'title' => $str,
|
||||||
|
@ -36,7 +39,7 @@ function testWallabagLinklist()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$data = hook_wallabag_render_linklist($data);
|
$data = hook_wallabag_render_linklist($data, $conf);
|
||||||
$link = $data['links'][0];
|
$link = $data['links'][0];
|
||||||
// data shouldn't be altered
|
// data shouldn't be altered
|
||||||
$this->assertEquals($str, $data['title']);
|
$this->assertEquals($str, $data['title']);
|
||||||
|
@ -45,7 +48,6 @@ function testWallabagLinklist()
|
||||||
// plugin data
|
// plugin data
|
||||||
$this->assertEquals(1, count($link['link_plugin']));
|
$this->assertEquals(1, count($link['link_plugin']));
|
||||||
$this->assertNotFalse(strpos($link['link_plugin'][0], urlencode($str)));
|
$this->assertNotFalse(strpos($link['link_plugin'][0], urlencode($str)));
|
||||||
$this->assertNotFalse(strpos($link['link_plugin'][0], $GLOBALS['plugins']['WALLABAG_URL']));
|
$this->assertNotFalse(strpos($link['link_plugin'][0], $conf->get('plugins.WALLABAG_URL')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
tests/utils/config/configInvalid.json.php
Normal file
5
tests/utils/config/configInvalid.json.php
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?php /*
|
||||||
|
{
|
||||||
|
bad: bad,
|
||||||
|
}
|
||||||
|
*/ ?>
|
34
tests/utils/config/configJson.json.php
Normal file
34
tests/utils/config/configJson.json.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php /*
|
||||||
|
{
|
||||||
|
"credentials": {
|
||||||
|
"login":"root",
|
||||||
|
"hash":"hash",
|
||||||
|
"salt":"salt"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"session_protection_disabled":false
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"timezone":"Europe\/Paris",
|
||||||
|
"title": "Shaarli",
|
||||||
|
"header_link": "?"
|
||||||
|
},
|
||||||
|
"privacy": {
|
||||||
|
"default_private_links":true
|
||||||
|
},
|
||||||
|
"redirector": {
|
||||||
|
"url":"lala"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"foo": "bar"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"datastore": "tests\/utils\/config\/datastore.php",
|
||||||
|
"data_dir": "tests\/utils\/config"
|
||||||
|
},
|
||||||
|
"plugins": {
|
||||||
|
"WALLABAG_VERSION": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/ ?>
|
||||||
|
|
14
tests/utils/config/configPhp.php
Normal file
14
tests/utils/config/configPhp.php
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
$GLOBALS['login'] = 'root';
|
||||||
|
$GLOBALS['hash'] = 'hash';
|
||||||
|
$GLOBALS['salt'] = 'salt';
|
||||||
|
$GLOBALS['timezone'] = 'Europe/Paris';
|
||||||
|
$GLOBALS['title'] = 'title';
|
||||||
|
$GLOBALS['titleLink'] = 'titleLink';
|
||||||
|
$GLOBALS['redirector'] = 'lala';
|
||||||
|
$GLOBALS['disablesessionprotection'] = false;
|
||||||
|
$GLOBALS['privateLinkByDefault'] = false;
|
||||||
|
$GLOBALS['config']['DATADIR'] = 'tests/Updater';
|
||||||
|
$GLOBALS['config']['PAGECACHE'] = 'sandbox/pagecache';
|
||||||
|
$GLOBALS['config']['DATASTORE'] = 'data/datastore.php';
|
||||||
|
$GLOBALS['plugins']['WALLABAG_VERSION'] = '1';
|
|
@ -3,48 +3,90 @@
|
||||||
<head>{include="includes"}</head>
|
<head>{include="includes"}</head>
|
||||||
<body onload="document.configform.title.focus();">
|
<body onload="document.configform.title.focus();">
|
||||||
<div id="pageheader">
|
<div id="pageheader">
|
||||||
{include="page.header"}
|
{include="page.header"}
|
||||||
{$timezone_js}
|
{$timezone_js}
|
||||||
<form method="POST" action="#" name="configform" id="configform">
|
<form method="POST" action="#" name="configform" id="configform">
|
||||||
<input type="hidden" name="token" value="{$token}">
|
<input type="hidden" name="token" value="{$token}">
|
||||||
<table id="configuration_table">
|
<table id="configuration_table">
|
||||||
|
|
||||||
<tr><td><b>Page title:</b></td><td><input type="text" name="title" id="title" size="50" value="{$title}"></td></tr>
|
<tr>
|
||||||
|
<td><b>Page title:</b></td>
|
||||||
|
<td><input type="text" name="title" id="title" size="50" value="{$title}"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr><td><b>Title link:</b></td><td><input type="text" name="titleLink" id="titleLink" size="50" value="{$titleLink}"><br/><label for="titleLink">(default value is: ?)</label></td></tr>
|
<tr>
|
||||||
<tr><td><b>Timezone:</b></td><td>{$timezone_form}</td></tr>
|
<td><b>Title link:</b></td>
|
||||||
|
<td><input type="text" name="titleLink" id="titleLink" size="50" value="{$titleLink}"><br/><label
|
||||||
|
for="titleLink">(default value is: ?)</label></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Timezone:</b></td>
|
||||||
|
<td>{$timezone_form}</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr><td><b>Redirector</b></td><td><input type="text" name="redirector" id="redirector" size="50" value="{$redirector}"><br>(e.g. <i>http://anonym.to/?</i> will mask the HTTP_REFERER)</td></tr>
|
<tr>
|
||||||
|
<td><b>Redirector</b></td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="redirector" id="redirector" size="50" value="{$redirector}"><br>
|
||||||
|
(e.g. <i>http://anonym.to/?</i> will mask the HTTP_REFERER)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr><td><b>Security:</b></td><td><input type="checkbox" name="disablesessionprotection" id="disablesessionprotection" {if="!empty($GLOBALS['disablesessionprotection'])"}checked{/if}><label for="disablesessionprotection"> Disable session cookie hijacking protection (Check this if you get disconnected often or if your IP address changes often.)</label></td></tr>
|
<tr>
|
||||||
|
<td><b>Security:</b></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="disablesessionprotection" id="disablesessionprotection"
|
||||||
|
{if="$private_links_default"}checked{/if}>
|
||||||
|
<label
|
||||||
|
for="disablesessionprotection"> Disable session cookie hijacking protection (Check this if you get
|
||||||
|
disconnected often or if your IP address changes often.)</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr><td valign="top"><b>New link:</b></td><td>
|
<tr>
|
||||||
<input type="checkbox" name="privateLinkByDefault" id="privateLinkByDefault" {if="!empty($GLOBALS['privateLinkByDefault'])"}checked{/if}/><label for="privateLinkByDefault"> All new links are private by default</label></td>
|
<td valign="top"><b>New link:</b></td>
|
||||||
</tr>
|
<td>
|
||||||
<tr>
|
<input type="checkbox" name="privateLinkByDefault" id="privateLinkByDefault"
|
||||||
<td valign="top"><b>RSS direct links</b></td>
|
{if="$private_links_default"}checked{/if}/>
|
||||||
<td>
|
<label for="privateLinkByDefault">
|
||||||
<input type="checkbox" name="enableRssPermalinks" id="enableRssPermalinks" {if="!empty($GLOBALS['config']['ENABLE_RSS_PERMALINKS'])"}checked{/if}/>
|
All new links are private by default
|
||||||
<label for="enableRssPermalinks">
|
</label>
|
||||||
Disable it to use permalinks in RSS feed instead of direct links to your shaared links. Currently <b>{if="$GLOBALS['config']['ENABLE_RSS_PERMALINKS']"}enabled{else}disabled{/if}.</b>
|
</td>
|
||||||
</label>
|
</tr>
|
||||||
</td>
|
<tr>
|
||||||
</tr>
|
<td valign="top"><b>RSS direct links</b></td>
|
||||||
<tr>
|
<td>
|
||||||
<td valign="top"><b>Hide public links</b></td>
|
<input type="checkbox" name="enableRssPermalinks" id="enableRssPermalinks"
|
||||||
<td>
|
{if="$enable_rss_permalinks"}checked{/if}/>
|
||||||
<input type="checkbox" name="hidePublicLinks" id="hidePublicLinks" {if="!empty($GLOBALS['config']['HIDE_PUBLIC_LINKS'])"}checked{/if}/><label for="hidePublicLinks">
|
<label for="enableRssPermalinks">
|
||||||
Do not show any links if the user is not logged in.</label>
|
Disable it to use permalinks in RSS feed instead of direct links to your shaared links. Currently <b>
|
||||||
</td>
|
{if="$enable_rss_permalinks"}enabled{else}disabled{/if}.</b>
|
||||||
</tr>
|
</label>
|
||||||
<tr><td valign="top"><b>Update:</b></td><td>
|
</td>
|
||||||
<input type="checkbox" name="updateCheck" id="updateCheck" {if="!empty($GLOBALS['config']['ENABLE_UPDATECHECK'])"}checked{/if}/>
|
</tr>
|
||||||
<label for="updateCheck"> Notify me when a new release is ready</label></td>
|
<tr>
|
||||||
</tr>
|
<td valign="top"><b>Hide public links</b></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="hidePublicLinks" id="hidePublicLinks"
|
||||||
|
{if="$hide_public_links"}checked{/if}/>
|
||||||
|
<label for="hidePublicLinks"> Do not show any links if the user is not logged in.</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top"><b>Update:</b></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="updateCheck" id="updateCheck"
|
||||||
|
{if="$enable_update_check"}checked{/if}/>
|
||||||
|
<label for="updateCheck"> Notify me when a new release is ready</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr><td></td><td class="right"><input type="submit" name="Save" value="Save config" class="bigbutton"></td></tr>
|
<tr>
|
||||||
</table>
|
<td></td>
|
||||||
</form>
|
<td class="right"><input type="submit" name="Save" value="Save config" class="bigbutton"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{include="page.footer"}
|
{include="page.footer"}
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
<img src="../images/squiggle2.png" width="25" height="26" title="permalink" alt="permalink">
|
<img src="../images/squiggle2.png" width="25" height="26" title="permalink" alt="permalink">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{if="!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()"}
|
{if="!$hide_timestamps || isLoggedIn()"}
|
||||||
<div class="dailyEntryLinkdate">
|
<div class="dailyEntryLinkdate">
|
||||||
<a href="?{$link.linkdate|smallHash}">{function="strftime('%c', $link.timestamp)"}</a>
|
<a href="?{$link.linkdate|smallHash}">{function="strftime('%c', $link.timestamp)"}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
{loop="links"}
|
{loop="links"}
|
||||||
<h3><a href="{$value.url}">{$value.title}</a></h3>
|
<h3><a href="{$value.url}">{$value.title}</a></h3>
|
||||||
<small>{if="!$GLOBALS['config']['HIDE_TIMESTAMPS']"}{function="strftime('%c', $value.timestamp)"} - {/if}{if="$value.tags"}{$value.tags}{/if}<br>
|
<small>{if="!$hide_timestamps"}{function="strftime('%c', $value.timestamp)"} - {/if}{if="$value.tags"}{$value.tags}{/if}<br>
|
||||||
{$value.url}</small><br>
|
{$value.url}</small><br>
|
||||||
{if="$value.thumbnail"}{$value.thumbnail}{/if}<br>
|
{if="$value.thumbnail"}{$value.thumbnail}{/if}<br>
|
||||||
{if="$value.description"}{$value.formatedDescription}{/if}
|
{if="$value.description"}{$value.formatedDescription}{/if}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
{$value}
|
{$value}
|
||||||
{/loop}
|
{/loop}
|
||||||
|
|
||||||
{if="($link_is_new && $GLOBALS['privateLinkByDefault']==true) || $link.private == true"}
|
{if="($link_is_new && $default_private_links) || $link.private == true"}
|
||||||
<input type="checkbox" checked="checked" name="lf_private" id="lf_private">
|
<input type="checkbox" checked="checked" name="lf_private" id="lf_private">
|
||||||
<label for="lf_private"><i>Private</i></label><br>
|
<label for="lf_private"><i>Private</i></label><br>
|
||||||
{else}
|
{else}
|
||||||
|
@ -43,12 +43,10 @@
|
||||||
{if="$source !== 'firefoxsocialapi'"}
|
{if="$source !== 'firefoxsocialapi'"}
|
||||||
{include="page.footer"}
|
{include="page.footer"}
|
||||||
{/if}
|
{/if}
|
||||||
{if="($GLOBALS['config']['OPEN_SHAARLI'] || isLoggedIn())"}
|
|
||||||
<script src="inc/awesomplete.min.js#"></script>
|
<script src="inc/awesomplete.min.js#"></script>
|
||||||
<script src="inc/awesomplete-multiple-tags.js#"></script>
|
<script src="inc/awesomplete-multiple-tags.js#"></script>
|
||||||
<script>
|
<script>
|
||||||
awesompleteUniqueTag('#lf_tags');
|
awesompleteUniqueTag('#lf_tags');
|
||||||
</script>
|
</script>
|
||||||
{/if}
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
</span>
|
</span>
|
||||||
<br>
|
<br>
|
||||||
{if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if}
|
{if="$value.description"}<div class="linkdescription">{$value.description}</div>{/if}
|
||||||
{if="!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()"}
|
{if="!$hide_timestamps || isLoggedIn()"}
|
||||||
<span class="linkdate" title="Permalink"><a href="?{$value.linkdate|smallHash}">{function="strftime('%c', $value.timestamp)"} - permalink</a> - </span>
|
<span class="linkdate" title="Permalink"><a href="?{$value.linkdate|smallHash}">{function="strftime('%c', $value.timestamp)"} - permalink</a> - </span>
|
||||||
{else}
|
{else}
|
||||||
<span class="linkdate" title="Short link here"><a href="?{$value.shorturl}">permalink</a> - </span>
|
<span class="linkdate" title="Short link here"><a href="?{$value.shorturl}">permalink</a> - </span>
|
||||||
|
|
|
@ -21,14 +21,14 @@
|
||||||
<li><a href="?do=logout">Logout</a></li>
|
<li><a href="?do=logout">Logout</a></li>
|
||||||
<li><a href="?do=tools">Tools</a></li>
|
<li><a href="?do=tools">Tools</a></li>
|
||||||
<li><a href="?do=addlink">Add link</a></li>
|
<li><a href="?do=addlink">Add link</a></li>
|
||||||
{elseif="$GLOBALS['config']['OPEN_SHAARLI']"}
|
{elseif="$openshaarli"}
|
||||||
<li><a href="?do=tools">Tools</a></li>
|
<li><a href="?do=tools">Tools</a></li>
|
||||||
<li><a href="?do=addlink">Add link</a></li>
|
<li><a href="?do=addlink">Add link</a></li>
|
||||||
{else}
|
{else}
|
||||||
<li><a href="?do=login">Login</a></li>
|
<li><a href="?do=login">Login</a></li>
|
||||||
{/if}
|
{/if}
|
||||||
<li><a href="{$feedurl}?do=rss{$searchcrits}" class="nomobile">RSS Feed</a></li>
|
<li><a href="{$feedurl}?do=rss{$searchcrits}" class="nomobile">RSS Feed</a></li>
|
||||||
{if="$GLOBALS['config']['SHOW_ATOM']"}
|
{if="$showatom"}
|
||||||
<li><a href="{$feedurl}?do=atom{$searchcrits}" class="nomobile">ATOM Feed</a></li>
|
<li><a href="{$feedurl}?do=atom{$searchcrits}" class="nomobile">ATOM Feed</a></li>
|
||||||
{/if}
|
{/if}
|
||||||
<li><a href="?do=tagcloud">Tag cloud</a></li>
|
<li><a href="?do=tagcloud">Tag cloud</a></li>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<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>
|
||||||
{if="!$GLOBALS['config']['OPEN_SHAARLI']"}<a href="?do=changepasswd"><b>Change password</b><span>: Change your password.</span></a>
|
{if="$openshaarli"}<a href="?do=changepasswd"><b>Change password</b><span>: Change your password.</span></a>
|
||||||
<br><br>{/if}
|
<br><br>{/if}
|
||||||
<a href="?do=changetag"><b>Rename/delete tags</b><span>: Rename or delete a tag in all links</span></a>
|
<a href="?do=changetag"><b>Rename/delete tags</b><span>: Rename or delete a tag in all links</span></a>
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
Loading…
Reference in a new issue