Navigation Menu

Skip to content

Commit

Permalink
moved php parser to it's own file
Browse files Browse the repository at this point in the history
  • Loading branch information
splitbrain committed May 11, 2018
1 parent c6639e6 commit e063bab
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 81 deletions.
101 changes: 101 additions & 0 deletions lib/plugins/config/core/ConfigParser.php
@@ -0,0 +1,101 @@
<?php

namespace dokuwiki\plugin\config\core;

/**
* A naive PHP file parser
*
* This parses our very simple config file in PHP format. We use this instead of simply including
* the file, because we want to keep expressions such as 24*60*60 as is.
*
* @author Chris Smith <chris@jalakai.co.uk>
*/
class ConfigParser {
/** @var string variable to parse from the file */
protected $varname;
/** @var string the key to mark sub arrays */
protected $keymarker;

/**
* ConfigParser constructor.
*
* @param string $varname variable to parse from the file
* @param string $keymarker the key to mark sub arrays
*/
public function __construct($varname = 'conf', $keymarker = '____') {
$this->varname = $varname;
$this->keymarker = $keymarker;
}

/**
* Parse the given PHP file into an array
*
* When the given files does not exist, this returns an empty array
*
* @param string $file
* @return array
*/
public function parse($file) {
if(!file_exists($file)) return array();

$config = array();
$contents = @php_strip_whitespace($file);
$pattern = '/\$' . $this->varname . '\[[\'"]([^=]+)[\'"]\] ?= ?(.*?);(?=[^;]*(?:\$' . $this->varname . '|$))/s';
$matches = array();
preg_match_all($pattern, $contents, $matches, PREG_SET_ORDER);

for($i = 0; $i < count($matches); $i++) {
$value = $matches[$i][2];

// merge multi-dimensional array indices using the keymarker
$key = preg_replace('/.\]\[./', $this->keymarker, $matches[$i][1]);

// handle arrays
if(preg_match('/^array ?\((.*)\)/', $value, $match)) {
$arr = explode(',', $match[1]);

// remove quotes from quoted strings & unescape escaped data
$len = count($arr);
for($j = 0; $j < $len; $j++) {
$arr[$j] = trim($arr[$j]);
$arr[$j] = $this->readValue($arr[$j]);
}

$value = $arr;
} else {
$value = $this->readValue($value);
}

$config[$key] = $value;
}

return $config;
}

/**
* Convert php string into value
*
* @param string $value
* @return bool|string
*/
protected function readValue($value) {
$removequotes_pattern = '/^(\'|")(.*)(?<!\\\\)\1$/s';
$unescape_pairs = array(
'\\\\' => '\\',
'\\\'' => '\'',
'\\"' => '"'
);

if($value == 'true') {
$value = true;
} elseif($value == 'false') {
$value = false;
} else {
// remove quotes from quoted strings & unescape escaped data
$value = preg_replace($removequotes_pattern, '$2', $value);
$value = strtr($value, $unescape_pairs);
}
return $value;
}

}
91 changes: 10 additions & 81 deletions lib/plugins/config/core/Configuration.php
Expand Up @@ -18,6 +18,11 @@ class Configuration {
protected $_name = 'conf'; // name of the config variable found in the files (overridden by $config['varname'])
protected $_format = 'php'; // format of the config file, supported formats - php (overridden by $config['format'])
protected $_heading = ''; // heading string written at top of config file - don't include comment indicators

/** @var ConfigParser */
protected $parser;


protected $_loaded = false; // set to true after configuration files are loaded
protected $_metadata = array();// holds metadata describing the settings
/** @var Setting[] */
Expand Down Expand Up @@ -56,6 +61,8 @@ public function __construct($datafile) {
$this->_local_files = $config_cascade['main']['local'];
$this->_protected_files = $config_cascade['main']['protected'];

$this->parser = new ConfigParser($this->_name, Configuration::KEYMARKER);

$this->locked = $this->_is_locked();
$this->_metadata = array_merge($meta, $this->get_plugintpl_metadata($conf['template']));
$this->retrieve_settings();
Expand Down Expand Up @@ -185,90 +192,12 @@ public function touch_settings() {
protected function _read_config_group($files) {
$config = array();
foreach($files as $file) {
$config = array_merge($config, $this->_read_config($file));
$config = array_merge($config, $this->parser->parse($file));
}

return $config;
}

/**
* Return an array of config settings
*
* @param string $file file path
* @return array config settings
*/
protected function _read_config($file) {

if(!$file) return array();

$config = array();

if($this->_format == 'php') {

if(file_exists($file)) {
$contents = @php_strip_whitespace($file);
} else {
$contents = '';
}
$pattern = '/\$' . $this->_name . '\[[\'"]([^=]+)[\'"]\] ?= ?(.*?);(?=[^;]*(?:\$' . $this->_name . '|$))/s';
$matches = array();
preg_match_all($pattern, $contents, $matches, PREG_SET_ORDER);

for($i = 0; $i < count($matches); $i++) {
$value = $matches[$i][2];

// correct issues with the incoming data
// FIXME ... for now merge multi-dimensional array indices using ____
$key = preg_replace('/.\]\[./', Configuration::KEYMARKER, $matches[$i][1]);

// handle arrays
if(preg_match('/^array ?\((.*)\)/', $value, $match)) {
$arr = explode(',', $match[1]);

// remove quotes from quoted strings & unescape escaped data
$len = count($arr);
for($j = 0; $j < $len; $j++) {
$arr[$j] = trim($arr[$j]);
$arr[$j] = $this->_readValue($arr[$j]);
}

$value = $arr;
} else {
$value = $this->_readValue($value);
}

$config[$key] = $value;
}
}

return $config;
}

/**
* Convert php string into value
*
* @param string $value
* @return bool|string
*/
protected function _readValue($value) {
$removequotes_pattern = '/^(\'|")(.*)(?<!\\\\)\1$/s';
$unescape_pairs = array(
'\\\\' => '\\',
'\\\'' => '\'',
'\\"' => '"'
);

if($value == 'true') {
$value = true;
} elseif($value == 'false') {
$value = false;
} else {
// remove quotes from quoted strings & unescape escaped data
$value = preg_replace($removequotes_pattern, '$2', $value);
$value = strtr($value, $unescape_pairs);
}
return $value;
}

/**
* Returns header of rewritten settings file
Expand Down Expand Up @@ -430,7 +359,7 @@ protected function get_plugintpl_default($tpl) {
foreach($this->get_plugin_list() as $plugin) {
$plugin_dir = plugin_directory($plugin);
if(file_exists(DOKU_PLUGIN . $plugin_dir . $file)) {
$conf = $this->_read_config(DOKU_PLUGIN . $plugin_dir . $file);
$conf = $this->parser->parse(DOKU_PLUGIN . $plugin_dir . $file);
foreach($conf as $key => $value) {
$default['plugin' . Configuration::KEYMARKER . $plugin . Configuration::KEYMARKER . $key] = $value;
}
Expand All @@ -439,7 +368,7 @@ protected function get_plugintpl_default($tpl) {

// the same for the active template
if(file_exists(tpl_incdir() . $file)) {
$conf = $this->_read_config(tpl_incdir() . $file);
$conf = $this->parser->parse(tpl_incdir() . $file);
foreach($conf as $key => $value) {
$default['tpl' . Configuration::KEYMARKER . $tpl . Configuration::KEYMARKER . $key] = $value;
}
Expand Down

0 comments on commit e063bab

Please sign in to comment.