diff --git a/src/Processor.php b/src/Processor.php index 996260c..1e289ec 100644 --- a/src/Processor.php +++ b/src/Processor.php @@ -18,9 +18,6 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config; /** diff --git a/src/Processor/Constant.php b/src/Processor/Constant.php index 5821e5a..da32f56 100644 --- a/src/Processor/Constant.php +++ b/src/Processor/Constant.php @@ -18,9 +18,6 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Processor; use Zend\Config\Config, diff --git a/src/Processor/Filter.php b/src/Processor/Filter.php index e27b1d2..402b053 100644 --- a/src/Processor/Filter.php +++ b/src/Processor/Filter.php @@ -18,9 +18,6 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Processor; use Zend\Config\Config, diff --git a/src/Processor/Queue.php b/src/Processor/Queue.php index 8cb3029..7b91d90 100644 --- a/src/Processor/Queue.php +++ b/src/Processor/Queue.php @@ -18,9 +18,6 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Processor; use Zend\Config\Config, diff --git a/src/Processor/Token.php b/src/Processor/Token.php index 0264941..44041a4 100644 --- a/src/Processor/Token.php +++ b/src/Processor/Token.php @@ -18,9 +18,6 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Processor; use Zend\Config\Config, @@ -200,7 +197,7 @@ protected function buildMap() foreach ($this->tokens as $token => $value) { $this->map[$this->prefix . $token . $this->suffix] = $value; } - } + } } /** @@ -228,7 +225,7 @@ public function process(Config $config) if ($val instanceof Config) { $this->process($val); } else { - $config->$key = str_replace($keys,$values,$val); + $config->$key = str_replace($keys, $values, $val); } } @@ -248,6 +245,6 @@ public function processValue($value) } $keys = array_keys($this->map); $values = array_values($this->map); - return str_replace($keys,$values,$value); + return str_replace($keys, $values, $value); } } \ No newline at end of file diff --git a/src/Processor/Translator.php b/src/Processor/Translator.php index 74c1080..1549bfb 100644 --- a/src/Processor/Translator.php +++ b/src/Processor/Translator.php @@ -18,9 +18,6 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Processor; use Zend\Config\Config, @@ -108,22 +105,22 @@ public function process(Config $config) if ($val instanceof Config) { $this->process($val); } else { - $config->$key = $this->translator->translate($val,$this->locale); + $config->$key = $this->translator->translate($val, $this->locale); } } return $config; } - /** - * Process a single value - * - * @param $value - * @return mixed - */ - public function processValue($value) - { - return $this->translator->translate($value,$this->locale); - } + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function processValue($value) + { + return $this->translator->translate($value, $this->locale); + } } diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php index a5ce4cb..949bef0 100644 --- a/src/Reader/Ini.php +++ b/src/Reader/Ini.php @@ -141,7 +141,7 @@ protected function process(array $data) if (is_array($value)) { $config[$section] = $this->processSection($value); } else { - $config[$section] = $value; + $this->processKey($section, $value, $config); } } diff --git a/src/Reader/Json.php b/src/Reader/Json.php new file mode 100644 index 0000000..b559a88 --- /dev/null +++ b/src/Reader/Json.php @@ -0,0 +1,113 @@ +directory = dirname($filename); + + try { + $config = JsonFormat::decode(file_get_contents($filename), JsonFormat::TYPE_ARRAY); + } catch (\Zend\Json\Exception\RuntimeException $e) { + throw new Exception\RuntimeException($e->getMessage()); + } + + return $this->process($config); + } + + /** + * fromString(): defined by Reader interface. + * + * @see Reader::fromString() + * @param string $string + * @return array + */ + public function fromString($string) + { + if (empty($string)) { + return array(); + } + $this->directory = null; + + try { + $config = JsonFormat::decode($string, JsonFormat::TYPE_ARRAY); + } catch (\Zend\Json\Exception\RuntimeException $e) { + throw new Exception\RuntimeException($e->getMessage()); + } + + return $this->process($config); + } + /** + * Process the array for @include + * + * @param array $data + * @return array + */ + protected function process(array $data) { + foreach ($data as $key => $value) { + if (is_array($value)) { + $data[$key] = $this->process($value); + } + if (trim($key)==='@include') { + if ($this->directory === null) { + throw new Exception\RuntimeException('Cannot process @include statement for a json string'); + } + $reader = clone $this; + unset($data[$key]); + $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value)); + } + } + return $data; + } +} \ No newline at end of file diff --git a/src/Reader/Yaml.php b/src/Reader/Yaml.php new file mode 100644 index 0000000..d8aa081 --- /dev/null +++ b/src/Reader/Yaml.php @@ -0,0 +1,160 @@ +setYamlDecoder($yamlDecoder); + } else { + if (function_exists('yaml_parse')) { + $this->setYamlDecoder('yaml_parse'); + } + } + } + /** + * Get callback for decoding YAML + * + * @return callable + */ + public function getYamlDecoder() + { + return $this->yamlDecoder; + } + /** + * Set callback for decoding YAML + * + * @param callable $yamlDecoder the decoder to set + * @return Yaml + */ + public function setYamlDecoder($yamlDecoder) + { + if (!is_callable($yamlDecoder)) { + throw new Exception\InvalidArgumentException('Invalid parameter to setYamlDecoder() - must be callable'); + } + $this->yamlDecoder = $yamlDecoder; + return $this; + } + /** + * fromFile(): defined by Reader interface. + * + * @see Reader::fromFile() + * @param string $filename + * @return array + */ + public function fromFile($filename) + { + if (!file_exists($filename)) { + throw new Exception\RuntimeException("The file $filename doesn't exists."); + } + if (null === $this->getYamlDecoder()) { + throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder"); + } + + $this->directory = dirname($filename); + + $config = call_user_func($this->getYamlDecoder(), file_get_contents($filename)); + if (null === $config) { + throw new Exception\RuntimeException("Error parsing YAML data"); + } + + return $this->process($config); + } + + /** + * fromString(): defined by Reader interface. + * + * @see Reader::fromString() + * @param string $string + * @return array + */ + public function fromString($string) + { + if (null === $this->getYamlDecoder()) { + throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder"); + } + if (empty($string)) { + return array(); + } + + $this->directory = null; + + $config = call_user_func($this->getYamlDecoder(), $string); + if (null === $config) { + throw new Exception\RuntimeException("Error parsing YAML data"); + } + + return $this->process($config); + } + /** + * Process the array for @include + * + * @param array $data + * @return array + */ + protected function process(array $data) { + foreach ($data as $key => $value) { + if (is_array($value)) { + $data[$key] = $this->process($value); + } + if (trim($key)==='@include') { + if ($this->directory === null) { + throw new Exception\RuntimeException('Cannot process @include statement for a json string'); + } + $reader = clone $this; + unset($data[$key]); + $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value)); + } + } + return $data; + } +} \ No newline at end of file diff --git a/src/Writer/Json.php b/src/Writer/Json.php new file mode 100644 index 0000000..5020f5b --- /dev/null +++ b/src/Writer/Json.php @@ -0,0 +1,43 @@ +setYamlEncoder($yamlEncoder); + } else { + if (function_exists('yaml_parse')) { + $this->setYamlEncoder('yaml_parse'); + } + } + } + /** + * Get callback for decoding YAML + * + * @return callable + */ + public function getYamlEncoder() + { + return $this->yamlEncoder; + } + /** + * Set callback for decoding YAML + * + * @param callable $yamlEncoder the decoder to set + * @return Yaml + */ + public function setYamlEncoder($yamlEncoder) + { + if (!is_callable($yamlEncoder)) { + throw new Exception\InvalidArgumentException('Invalid parameter to setYamlEncoder() - must be callable'); + } + $this->yamlEncoder = $yamlEncoder; + return $this; + } + /** + * processConfig(): defined by AbstractWriter. + * + * @param array $config + * @return string + */ + public function processConfig(array $config) + { + if (null === $this->getYamlEncoder()) { + throw new Exception\RuntimeException("You didn't specify a Yaml callback encoder"); + } + + $config = call_user_func($this->getYamlEncoder(), $config); + if (null === $config) { + throw new Exception\RuntimeException("Error generating YAML data"); + } + + return $config; + } +} diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php index a3e07e8..4c13cdc 100644 --- a/test/Reader/AbstractReaderTestCase.php +++ b/test/Reader/AbstractReaderTestCase.php @@ -57,7 +57,7 @@ public function testMissingFile() public function testFromFile() { $config = $this->reader->fromFile($this->getTestAssetPath('include-base')); - $this->assertEquals('foo', $config['base']['foo']); + $this->assertEquals('foo', $config['foo']); } public function testFromEmptyString() diff --git a/test/Reader/JsonTest.php b/test/Reader/JsonTest.php new file mode 100644 index 0000000..7ae3702 --- /dev/null +++ b/test/Reader/JsonTest.php @@ -0,0 +1,83 @@ +reader = new Json(); + } + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) + { + return __DIR__ . '/TestAssets/Json/' . $name . '.json'; + } + + public function testInvalidJsonFile() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayJson = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testIncludeAsElement() + { + $arrayJson = $this->reader->fromFile($this->getTestAssetPath('include-base_nested')); + $this->assertEquals($arrayJson['bar']['foo'], 'foo'); + } + + public function testFromString() + { + $json = '{ "test" : "foo", "bar" : [ "baz", "foo" ] }'; + + $arrayJson = $this->reader->fromString($json); + + $this->assertEquals($arrayJson['test'], 'foo'); + $this->assertEquals($arrayJson['bar'][0], 'baz'); + $this->assertEquals($arrayJson['bar'][1], 'foo'); + } + + public function testInvalidString() + { + $json = '{"foo":"bar"'; + + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayIni = $this->reader->fromString($json); + } + +} diff --git a/test/Reader/TestAssets/Ini/include-base.ini b/test/Reader/TestAssets/Ini/include-base.ini index d81f5c3..a4e9480 100644 --- a/test/Reader/TestAssets/Ini/include-base.ini +++ b/test/Reader/TestAssets/Ini/include-base.ini @@ -1,2 +1 @@ -[base] @include = 'include-target.ini' diff --git a/test/Reader/TestAssets/Json/include-base.json b/test/Reader/TestAssets/Json/include-base.json new file mode 100644 index 0000000..ee3af2e --- /dev/null +++ b/test/Reader/TestAssets/Json/include-base.json @@ -0,0 +1,3 @@ +{ + "@include" : "include-target.json" +} \ No newline at end of file diff --git a/test/Reader/TestAssets/Json/include-base_nested.json b/test/Reader/TestAssets/Json/include-base_nested.json new file mode 100644 index 0000000..7ee7b59 --- /dev/null +++ b/test/Reader/TestAssets/Json/include-base_nested.json @@ -0,0 +1,3 @@ +{ + "bar" : { "@include" : "include-target.json" } +} \ No newline at end of file diff --git a/test/Reader/TestAssets/Json/include-target.json b/test/Reader/TestAssets/Json/include-target.json new file mode 100644 index 0000000..67e4d41 --- /dev/null +++ b/test/Reader/TestAssets/Json/include-target.json @@ -0,0 +1,3 @@ +{ + "foo" : "foo" +} diff --git a/test/Reader/TestAssets/Json/invalid.json b/test/Reader/TestAssets/Json/invalid.json new file mode 100644 index 0000000..3e1b208 --- /dev/null +++ b/test/Reader/TestAssets/Json/invalid.json @@ -0,0 +1,3 @@ +{ + "test": "test" + diff --git a/test/Reader/TestAssets/Xml/include-base.xml b/test/Reader/TestAssets/Xml/include-base.xml index b2862b5..3c52f34 100644 --- a/test/Reader/TestAssets/Xml/include-base.xml +++ b/test/Reader/TestAssets/Xml/include-base.xml @@ -1,6 +1,4 @@ - - - + \ No newline at end of file diff --git a/test/Reader/TestAssets/Yaml/include-base.yaml b/test/Reader/TestAssets/Yaml/include-base.yaml new file mode 100644 index 0000000..4f891f2 --- /dev/null +++ b/test/Reader/TestAssets/Yaml/include-base.yaml @@ -0,0 +1 @@ +@include: include-target.yaml \ No newline at end of file diff --git a/test/Reader/TestAssets/Yaml/include-target.yaml b/test/Reader/TestAssets/Yaml/include-target.yaml new file mode 100644 index 0000000..d867783 --- /dev/null +++ b/test/Reader/TestAssets/Yaml/include-target.yaml @@ -0,0 +1 @@ +foo: foo \ No newline at end of file diff --git a/test/Reader/YamlTest.php b/test/Reader/YamlTest.php new file mode 100644 index 0000000..ea8087f --- /dev/null +++ b/test/Reader/YamlTest.php @@ -0,0 +1,104 @@ +markTestSkipped('Yaml test for Zend\Config skipped'); + } + + if (constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE')) { + require_once constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE'); + } + + $yamlReader = explode('::', constant('TESTS_ZEND_CONFIG_READER_YAML_CALLBACK')); + if (isset($yamlReader[1])) { + $this->reader = new YamlReader(array($yamlReader[0], $yamlReader[1])); + } else { + $this->reader = new YamlReader(array($yamlReader[0])); + } + } + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) + { + return __DIR__ . '/TestAssets/Yaml/' . $name . '.yaml'; + } + + public function testInvalidIniFile() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayIni = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testFromString() + { + $yaml = <<reader->fromString($yaml); + $this->assertEquals($arrayYaml['test'], 'foo'); + $this->assertEquals($arrayYaml['bar'][0], 'baz'); + $this->assertEquals($arrayYaml['bar'][1], 'foo'); + } + + public function testFromStringWithSection() + { + $yaml = <<reader->fromString($yaml); + $this->assertEquals($arrayYaml['all']['test'], 'foo'); + $this->assertEquals($arrayYaml['all']['bar'][0], 'baz'); + $this->assertEquals($arrayYaml['all']['bar'][1], 'foo'); + } +} diff --git a/test/Writer/JsonTest.php b/test/Writer/JsonTest.php new file mode 100644 index 0000000..ed89f00 --- /dev/null +++ b/test/Writer/JsonTest.php @@ -0,0 +1,70 @@ +reader = new JsonReader(); + $this->writer = new JsonWriter(); + } + + + + public function testNoSection() + { + $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('foo', $config['test']); + $this->assertEquals('bar', $config['test2']['test3']); + } + + public function testWriteAndReadOriginalFile() + { + $config = $this->reader->fromFile(__DIR__ . '/files/allsections.json'); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('multi', $config['all']['one']['two']['three']); + + } +} diff --git a/test/Writer/YamlTest.php b/test/Writer/YamlTest.php new file mode 100644 index 0000000..73e9a40 --- /dev/null +++ b/test/Writer/YamlTest.php @@ -0,0 +1,87 @@ +markTestSkipped('Yaml test for Zend\Config skipped'); + } + + if (constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE')) { + require_once constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE'); + } + + $yamlReader = explode('::', constant('TESTS_ZEND_CONFIG_READER_YAML_CALLBACK')); + if (isset($yamlReader[1])) { + $this->reader = new YamlReader(array($yamlReader[0], $yamlReader[1])); + } else { + $this->reader = new YamlReader(array($yamlReader[0])); + } + + $yamlWriter = explode('::', constant('TESTS_ZEND_CONFIG_WRITER_YAML_CALLBACK')); + if (isset($yamlWriter[1])) { + $this->writer = new YamlWriter(array($yamlWriter[0], $yamlWriter[1])); + } else { + $this->writer = new YamlWriter(array($yamlWriter[0])); + } + } + + public function testNoSection() + { + $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('foo', $config['test']); + $this->assertEquals('bar', $config['test2']['test3']); + } + + public function testWriteAndReadOriginalFile() + { + $config = $this->reader->fromFile(__DIR__ . '/files/allsections.yaml'); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('multi', $config['all']['one']['two']['three']); + + } +} diff --git a/test/Writer/files/allsections.json b/test/Writer/files/allsections.json new file mode 100644 index 0000000..d47bd4e --- /dev/null +++ b/test/Writer/files/allsections.json @@ -0,0 +1,45 @@ +{ +"all" : { + "hostname" : "all", + "name" : "thisname", + "db" : { + "host" : "127.0.0.1", + "user" : "username", + "pass" : "password", + "name" : "live" + }, + "one" : { + "two" : { + "three" : "multi" + } + } +}, +"staging" : { + "hostname" : "staging", + "db" : { + "name" : "dbstaging" + }, + "debug" : "false" +}, +"debug" : { + "hostname" : "debug", + "debug" : "true", + "values" : { + "changed" : "yes" + }, + "db" : { + "name" : "dbdebug" + }, + "special" : { + "no" : "no", + "null" : "null", + "false" : "false" + } +}, +"other_staging" : { + "only_in" : "otherStaging", + "db" : { + "pass" : "anotherpwd" + } +} +} \ No newline at end of file diff --git a/test/Writer/files/allsections.yaml b/test/Writer/files/allsections.yaml new file mode 100644 index 0000000..1dafe98 --- /dev/null +++ b/test/Writer/files/allsections.yaml @@ -0,0 +1,35 @@ +all: +# this is a comment + hostname: all + name: thisname + db: + host: 127.0.0.1 + user: username + pass: password + name: live + one: + two: + three: multi + +staging: + hostname: staging + db: + name: dbstaging + debug: + _extends: all +debug: + hostname: debug + debug: 1 + values: + changed: 1 + db: + name: dbdebug + special: + no: + null: + false: + _extends: all +other_staging: + only_in: otherStaging + db: + pass: anotherpwd