From f7895c75a1a1b484eb2641dea304f8be1a4534fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=A0?= Date: Sun, 5 Aug 2018 20:01:59 +0200 Subject: [PATCH] Add abstract config --- src/AbstractConfig.php | 266 ++++++++++++++++++++++++++++++++++++++++ src/Config.php | 37 ++++++ src/ConfigInterface.php | 39 ++++++ src/Record.php | 91 ++++++++++++++ 4 files changed, 433 insertions(+) create mode 100644 src/AbstractConfig.php create mode 100644 src/Config.php create mode 100644 src/ConfigInterface.php create mode 100644 src/Record.php diff --git a/src/AbstractConfig.php b/src/AbstractConfig.php new file mode 100644 index 0000000..3f05526 --- /dev/null +++ b/src/AbstractConfig.php @@ -0,0 +1,266 @@ + + * + * @license MIT + * + * @package ConfigWriter + */ +abstract class AbstractConfig implements ConfigInterface, ArrayAccess +{ + /** + * Stores the configuration data. + * + * @var array; + */ + public $data = []; + + /** + * Stores the configuration comment. + * + * @var mixed|null + */ + public $comment = null; + + /** + * Constructs the configuration. + * + * @param array $data Configuration data (optional) + * @param string $comment Configuration comment (optional) + */ + public function __construct($data = [], $comment = null) + { + $ritit = new RecursiveIteratorIterator( + new RecursiveArrayIterator( + $data, + RecursiveArrayIterator::CHILD_ARRAYS_ONLY + ) + ); + + foreach ($ritit as $leafValue) { + $keys = []; + + foreach (range(0, $ritit->getDepth()) as $depth) { + $keys[] = $ritit->getSubIterator($depth)->key(); + } + + $this->set(join('.', $keys), $leafValue); + } + + $this->data = self::stringToRecord($this->data); + $this->comment = $comment; + } + + /** + * Changes string to config record. + * + * @param array $arr Array with configuration + * + * @return array Converted array with configuration + */ + public static function stringToRecord($arr) + { + $result = []; + + foreach ($arr as $key => $value) { + if ($value instanceof Record) { + if (is_array($value->value)) { + $result[$key] = new Record( + self::stringToRecord($value->value), + $value->comment + ); + } else { + $result[$key] = new Record( + $value->value, + $value->comment + ); + } + } elseif ($value instanceof static) { + $result[$key] = $value; + } else { + if (is_array($value)) { + $result[$key] = new Record( + self::stringToRecord($value) + ); + } else { + $result[$key] = new Record( + $value + ); + } + } + } + + return $result; + } + + /** + * Changes config record to string. + * + * @param array $arr Array with configuration + * + * @return array Converted array with configuration + */ + public static function recordToString($arr) + { + $result = []; + + foreach ($arr as $key => $value) { + if ($value instanceof Record) { + if (is_array($value->value)) { + $result[$key] = self::recordToString($value->value); + } else { + $result[$key] = $value->value; + } + } elseif ($value instanceof static) { + $result = array_merge($result, self::recordToString($value->data)); + } else { + if (is_array($value)) { + $result[$key] = self::recordToString($value); + } else { + $result[$key] = $value; + } + } + } + + return $result; + } + + /** + * Function for setting configuration values, using + * either simple or nested keys. + * + * @param string $key Record's key + * @param mixed $value Record's value + * + * @return mixed Added record + */ + protected function set($key, $value) + { + $segs = explode('.', $key); + $root = &$this->data; + $cacheKey = ''; + + // Look for the key, creating nested keys if needed + while ($part = array_shift($segs)) { + if ($cacheKey !== '') { + $cacheKey .= '.'; + } + $cacheKey .= $part; + + if (!isset($root[$part]) && count($segs)) { + $root[$part] = []; + } + $root = &$root[$part]; + } + + // Assign value at target node + $root = $value; + + return $value; + } + + /** + * ConfigInterface methods. + */ + + /** + * {@inheritDoc} + */ + public function addRecord($key, $value = null, $comment = null) + { + $record = $this->set( + $key, + new Record($value, $comment) + ); + + $this->data = self::stringToRecord($this->data); + + return $record; + } + + /** + * {@inheritDoc} + */ + public function addSection($key, $data = [], $comment = null) + { + $section = $this->set( + $key, + new static( + $data, + $comment + ) + ); + + $this->data = self::stringToRecord($this->data); + + return $section; + } + + /** + * ArrayAccess methods. + */ + + /** + * Gets a value using the offset as a key. + * + * @param string $offset + * + * @return mixed + */ + public function &offsetGet($offset) + { + return $this->data[$offset]; + } + + /** + * Checks if a key exists. + * + * @param string $offset + * + * @return bool + */ + public function offsetExists($offset) + { + return isset($this->data[$offset]); + } + + /** + * Sets a value using the offset as a key. + * + * @param string $offset + * @param mixed $value + * + * @return void + */ + public function offsetSet($offset, $value) + { + if ($value instanceof Record || $value instanceof ConfigInterface) { + $this->set($offset, $value); + } else { + $this->addRecord($offset, $value); + } + } + + /** + * Deletes a key and its value + * + * @param string $offset + * + * @return void + */ + public function offsetUnset($offset) + { + $this->set($offset, null); + } +} diff --git a/src/Config.php b/src/Config.php new file mode 100644 index 0000000..c7cafc4 --- /dev/null +++ b/src/Config.php @@ -0,0 +1,37 @@ + + * + * @license MIT + * + * @package ConfigWriter + */ +class Config extends AbstractConfig +{ + /** + * Writes configuration to string. + * + * TODO: Documentation + */ + public function toString($format) + { + // TODO: Return configuration as a string. + } + + /** + * Writes configuration to file. + * + * TODO: Documentation + */ + public function toFile($filename, $format) + { + // TODO: Write configuration to file using method `toString()`. + } +} diff --git a/src/ConfigInterface.php b/src/ConfigInterface.php new file mode 100644 index 0000000..d6dfcd6 --- /dev/null +++ b/src/ConfigInterface.php @@ -0,0 +1,39 @@ + + * + * @license MIT + * + * @package ConfigWriter + */ +interface ConfigInterface +{ + /** + * Adds configuration record. + * + * @param string $key Record's key + * @param mixed|null $value Record's value (optional) + * @param mixed|null $comment Record's comment (optional) + * + * @return Record Added record + */ + public function addRecord($key, $value = null, $comment = null); + + /** + * Adds configuration section. + * + * @param string $key Section's key + * @param array $data Section's data (optional) + * @param mixed|null $comment Section's comment (optional) + * + * @return ConfigInterface Added section + */ + public function addSection($key, $data = [], $comment = null); +} diff --git a/src/Record.php b/src/Record.php new file mode 100644 index 0000000..fb3ac54 --- /dev/null +++ b/src/Record.php @@ -0,0 +1,91 @@ + + * + * @license MIT + * + * @package ConfigWriter + */ +class Record implements ArrayAccess +{ + /** + * @var mixed|null Record's value. + */ + public $value; + + /** + * @var mixed|null Record's comment. + */ + public $comment; + + /** + * Constructor for record class. + * + * It stores record's key, value and comment. + * + * @param mixed|null $value Record's value (optional) + * @param mixed|null $comment Record's comment (optional) + */ + public function __construct($value = null, $comment = null) + { + $this->value = $value; + $this->comment = $comment; + } + + /** + * Gets a value using the offset as a key. + * + * @param string $offset + * + * @return mixed + */ + public function &offsetGet($offset) + { + return $this->value[$offset]; + } + /** + * Checks if a key exists. + * + * @param string $offset + * + * @return bool + */ + public function offsetExists($offset) + { + return isset($this->value[$offset]); + } + /** + * Sets a value using the offset as a key. + * + * @param string $offset + * @param mixed $value + * + * @return void + */ + public function offsetSet($offset, $value) + { + $this->value[$offset] = $value; + } + /** + * Deletes a key and its value + * + * @param string $offset + * + * @return void + */ + public function offsetUnset($offset) + { + $this->value[$offset] = null; + } +}