I am building a config class for PHP which initially loads all given config files. To add files, users should be able to provide either a single file or a directory where files can be JSON or PHP.
Below is what I have so far, but it seems sluggish and inefficient to me. Is there a more elegant way to give users a wide choice of input? Should I split up the individual input cases into several private (or public?) methods? Are there any problems with this code apart from performance?
/**
* add function.
* merges the config data with another array
*
* @access public
* @param string|array $input the data to add
* @return void
*/
public function add($input)
{
// if we got a string, it can be either JSON, a filename or a folder path.
if (is_string($input)) {
// if we got a directory, add each file separately again (except . and ..).
if (is_dir($input)) {
if (! is_readable($input)) throw new \RuntimeException('Directory "' . $input . '" is not readable.');
// add each file in a directory to the config
foreach (array_diff(scandir($input), array('..', '.')) as $file) {
$this->add(rtrim($input, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $file);
}
return;
}
// if we got a filename, decide how to handle it based on the extension, then add its parsed content again
if (is_file($input)) {
if (! is_readable($input)) throw new \RuntimeException('File "' . $input . '" is not readable.');
switch(pathinfo($input, PATHINFO_EXTENSION)) {
case 'php':
$content = require($input);
break;
case 'json':
$content = $this->parseJSON(file_get_contents($input));
break;
}
$this->add($content);
return;
}
// string input is generally treated as JSON
$this->add($this->parseJSON($input));
return;
}
// if the input is an array, it must be plain config data, ready to merge in.
if (is_array($input)) {
$this->data = array_replace_recursive($this->data, $input);
return;
}
// if we have no match, throw an exception (this happens if neither a string nor an array was given).
throw new \RuntimeException('Provided data could not be parsed ("' . substr($input, 0, 20) . '...").');
return;
}
To give a little context to the file extension switch: I used it to be able to implement more file extensions later on. I also thought about creating a parser interface for each type to be more expandable, that would prohibit further use of a single class file tho.
PHP config files consist of the following:
<?php return array(
'foo' => 'bar'
);