From 369d955e812073ff879d7f76907080f6dcc44300 Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Thu, 3 Nov 2011 00:04:01 +0100 Subject: [PATCH 01/18] Zend\Config\Reader\Xml and tests --- src/Config.php | 22 +++--- src/Reader/Xml.php | 12 ++-- src/SectionedConfig.php | 26 ++++--- test/Reader/AbstractReaderTestCase.php | 72 +++++++++++++++++++ test/Reader/TestAssets/Xml/constants.xml | 7 ++ test/Reader/TestAssets/Xml/include-base.xml | 7 ++ test/Reader/TestAssets/Xml/include-target.xml | 2 + .../TestAssets/Xml/non-existent-constant.xml | 6 ++ test/Reader/XmlTest.php | 57 +++------------ test/Reader/_files/allsections.ini | 26 ------- test/Reader/_files/allsections.json | 1 - test/Reader/_files/allsections.xml | 35 --------- test/Reader/_files/allsections.yaml | 35 --------- test/Reader/_files/array.xml | 31 -------- test/Reader/_files/array.yaml | 22 ------ test/Reader/_files/badindentation.yaml | 6 -- test/Reader/_files/booleans.yaml | 29 -------- test/Reader/_files/circular.ini | 8 --- test/Reader/_files/circular.json | 1 - test/Reader/_files/circular.xml | 12 ---- test/Reader/_files/circular.yaml | 9 --- test/Reader/_files/config.ini | 50 ------------- test/Reader/_files/config.json | 1 - test/Reader/_files/config.xml | 36 ---------- test/Reader/_files/config.yaml | 38 ---------- test/Reader/_files/constants.yaml | 3 - test/Reader/_files/invalid.ini | 3 - test/Reader/_files/invalid.json | 1 - test/Reader/_files/invalid.xml | 12 ---- test/Reader/_files/invalid.yaml | 2 - test/Reader/_files/multipleinheritance.ini | 8 --- test/Reader/_files/multipleinheritance.json | 1 - test/Reader/_files/nested.json | 54 -------------- test/Reader/_files/nosections.ini | 5 -- test/Reader/_files/nosections.json | 1 - test/Reader/_files/onetoplevelstring.xml | 4 -- test/Reader/_files/separator.ini | 8 --- test/Reader/_files/shortparamsone.xml | 20 ------ test/Reader/_files/shortparamstwo.xml | 31 -------- test/Reader/_files/toplevelstring.xml | 11 --- test/Reader/_files/zf2843.ini | 3 - test/Reader/_files/zf5800.ini | 11 --- test/Reader/_files/zf6508.ini | 3 - test/Reader/_files/zf8159.ini | 4 -- 44 files changed, 139 insertions(+), 597 deletions(-) create mode 100644 test/Reader/AbstractReaderTestCase.php create mode 100644 test/Reader/TestAssets/Xml/constants.xml create mode 100644 test/Reader/TestAssets/Xml/include-base.xml create mode 100644 test/Reader/TestAssets/Xml/include-target.xml create mode 100644 test/Reader/TestAssets/Xml/non-existent-constant.xml delete mode 100644 test/Reader/_files/allsections.ini delete mode 100644 test/Reader/_files/allsections.json delete mode 100644 test/Reader/_files/allsections.xml delete mode 100755 test/Reader/_files/allsections.yaml delete mode 100644 test/Reader/_files/array.xml delete mode 100755 test/Reader/_files/array.yaml delete mode 100644 test/Reader/_files/badindentation.yaml delete mode 100644 test/Reader/_files/booleans.yaml delete mode 100644 test/Reader/_files/circular.ini delete mode 100644 test/Reader/_files/circular.json delete mode 100644 test/Reader/_files/circular.xml delete mode 100755 test/Reader/_files/circular.yaml delete mode 100644 test/Reader/_files/config.ini delete mode 100644 test/Reader/_files/config.json delete mode 100644 test/Reader/_files/config.xml delete mode 100755 test/Reader/_files/config.yaml delete mode 100644 test/Reader/_files/constants.yaml delete mode 100644 test/Reader/_files/invalid.ini delete mode 100644 test/Reader/_files/invalid.json delete mode 100644 test/Reader/_files/invalid.xml delete mode 100755 test/Reader/_files/invalid.yaml delete mode 100644 test/Reader/_files/multipleinheritance.ini delete mode 100644 test/Reader/_files/multipleinheritance.json delete mode 100644 test/Reader/_files/nested.json delete mode 100644 test/Reader/_files/nosections.ini delete mode 100644 test/Reader/_files/nosections.json delete mode 100644 test/Reader/_files/onetoplevelstring.xml delete mode 100644 test/Reader/_files/separator.ini delete mode 100644 test/Reader/_files/shortparamsone.xml delete mode 100644 test/Reader/_files/shortparamstwo.xml delete mode 100644 test/Reader/_files/toplevelstring.xml delete mode 100644 test/Reader/_files/zf2843.ini delete mode 100644 test/Reader/_files/zf5800.ini delete mode 100644 test/Reader/_files/zf6508.ini delete mode 100644 test/Reader/_files/zf8159.ini diff --git a/src/Config.php b/src/Config.php index 93ddc5b..91dd273 100644 --- a/src/Config.php +++ b/src/Config.php @@ -23,13 +23,17 @@ */ namespace Zend\Config; +use \Countable, + \Iterator, + \ArrayAccess; + /** * @category Zend * @package Zend_Config * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Config implements \Countable, \Iterator, \ArrayAccess +class Config implements Countable, Iterator, ArrayAccess { /** * Whether modifications to configuration data are allowed. @@ -339,7 +343,7 @@ public function offsetUnset($offset) } /** - * Merge another Zend_Config with this one. + * Merge another Config with this one. * * The items in $merge will override the same named items in the current * config. @@ -351,16 +355,16 @@ public function merge(self $merge) { foreach ($merge as $key => $item) { if (array_key_exists($key, $this->data)) { - if ($item instanceof self && $this->$key instanceof self) { - $this->$key = $this->$key->merge(new self($item->toArray(), $this->allowModifications)); + if ($item instanceof self && $this->data[$key] instanceof self) { + $this->data[$key] = $this->data[$key]->merge(new self($item->toArray(), $this->allowModifications)); } else { - $this->$key = $item; + $this->data[$key] = $item; } } else { if ($item instanceof self) { - $this->$key = new self($item->toArray(), $this->allowModifications); + $this->data[$key] = new self($item->toArray(), $this->allowModifications); } else { - $this->$key = $item; + $this->data[$key] = $item; } } } @@ -371,7 +375,7 @@ public function merge(self $merge) /** * Prevent any more modifications being made to this instance. * - * Useful after merge() has been used to merge multiple Zend_Config objects + * Useful after merge() has been used to merge multiple Config objects * into one object which should then not be modified again. * * @return void @@ -388,7 +392,7 @@ public function setReadOnly() } /** - * Returns if this Config object is read only or not. + * Returns whether this Config object is read only or not. * * @return boolean */ diff --git a/src/Reader/Xml.php b/src/Reader/Xml.php index 6c50775..6e57826 100644 --- a/src/Reader/Xml.php +++ b/src/Reader/Xml.php @@ -68,7 +68,7 @@ class Xml extends AbstractReader protected function processFile($filename) { $this->reader = new XMLReader(); - $this->reader->open($filename); + $this->reader->open($filename, null, LIBXML_XINCLUDE); return $this->process(); } @@ -83,7 +83,7 @@ protected function processFile($filename) protected function processString($data) { $this->reader = new XMLReader(); - $this->reader->xml($data); + $this->reader->xml($data, null, LIBXML_XINCLUDE); return $this->process(); } @@ -128,11 +128,11 @@ protected function processNextElement() if ($this->reader->namespaceURI === self::XML_NAMESPACE) { switch ($this->reader->localName) { case 'const': - if (!isset($attributes['zf']['name'])) { - throw new Exception\RuntimeException('Misssing "name" attribute in "const" node'); + if (!isset($attributes['default']['name'])) { + throw new Exception\RuntimeException('Misssing "name" attribute in "zf:const" node'); } - $constantName = $attributes['zf']['name']; + $constantName = $attributes['default']['name']; if (!defined($constantName)) { throw new Exception\RuntimeException(sprintf('Constant with name "%s" was not defined', $constantName)); @@ -142,7 +142,7 @@ protected function processNextElement() break; default: - throw new Exception\RuntimeException(sprintf('Unknown node with name "%s" found', $name)); + throw new Exception\RuntimeException(sprintf('Unknown zf:node with name "%s" found', $name)); } } else { if (isset($attributes['zf']['value'])) { diff --git a/src/SectionedConfig.php b/src/SectionedConfig.php index e7018df..a2af239 100644 --- a/src/SectionedConfig.php +++ b/src/SectionedConfig.php @@ -32,7 +32,7 @@ class SectionedConfig extends Config { /** - * Contains which config file sections were loaded. + * Contains which config sections were loaded. * * This is null if all sections were loaded, a string name if one section is * loaded and an array of string names if multiple sections were loaded. @@ -61,6 +61,7 @@ public function getSectionName() if (is_array($this->loadedSection) && count($this->_loadedSection) === 1) { $this->loadedSection = $this->loadedSection[0]; } + return $this->loadedSection; } @@ -71,7 +72,7 @@ public function getSectionName() */ public function areAllSectionsLoaded() { - return $this->_loadedSection === null; + return $this->loadedSection === null; } /** @@ -93,10 +94,10 @@ public function getExtends() */ public function setExtend($extendingSection, $extendedSection = null) { - if ($extendedSection === null && isset($this->_extends[$extendingSection])) { - unset($this->_extends[$extendingSection]); + if ($extendedSection === null && isset($this->extends[$extendingSection])) { + unset($this->extends[$extendingSection]); } else if ($extendedSection !== null) { - $this->_extends[$extendingSection] = $extendedSection; + $this->extends[$extendingSection] = $extendedSection; } } @@ -111,15 +112,18 @@ public function setExtend($extendingSection, $extendedSection = null) */ protected function assertValidExtend($extendingSection, $extendedSection) { - // detect circular section inheritance - $extendedSectionCurrent = $extendedSection; - while (array_key_exists($extendedSectionCurrent, $this->_extends)) { - if ($this->_extends[$extendedSectionCurrent] == $extendingSection) { + // Detect circular section inheritance + $currentExtendedSection = $extendedSection; + + while (array_key_exists($currentExtendedSection, $this->extends)) { + if ($this->extends[$currentExtendedSection] == $extendingSection) { throw new Exception\RuntimeException('Illegal circular inheritance detected'); } - $extendedSectionCurrent = $this->_extends[$extendedSectionCurrent]; + + $currentExtendedSection = $this->_extends[$currentExtendedSection]; } - // remember that this section extends another section + + // Remember that this section extends another section $this->_extends[$extendingSection] = $extendedSection; } } diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php new file mode 100644 index 0000000..294ebf0 --- /dev/null +++ b/test/Reader/AbstractReaderTestCase.php @@ -0,0 +1,72 @@ +reader->readFile($this->getTestAssetPath('include-base')); + $this->assertEquals('foo', $config->base->foo); + } + + public function testConstants() + { + if (!defined('ZEND_CONFIG_TEST_CONSTANT')) { + define('ZEND_CONFIG_TEST_CONSTANT', 'test'); + } + + $config = $this->reader->readFile($this->getTestAssetPath('constants')); + + $this->assertEquals('foo-test-bar-test', $config->base->foo); + $this->assertEquals('ZEND_CONFIG_TEST_CONSTANT', $config->base->bar->const->name); + } + + public function testNonExistentConstant() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Constant with name "ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT" was not defined'); + $config = $this->reader->readFile($this->getTestAssetPath('non-existent-constant')); + } +} diff --git a/test/Reader/TestAssets/Xml/constants.xml b/test/Reader/TestAssets/Xml/constants.xml new file mode 100644 index 0000000..8384ad0 --- /dev/null +++ b/test/Reader/TestAssets/Xml/constants.xml @@ -0,0 +1,7 @@ + + + + foo--bar- + + + \ No newline at end of file diff --git a/test/Reader/TestAssets/Xml/include-base.xml b/test/Reader/TestAssets/Xml/include-base.xml new file mode 100644 index 0000000..e77f119 --- /dev/null +++ b/test/Reader/TestAssets/Xml/include-base.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/test/Reader/TestAssets/Xml/include-target.xml b/test/Reader/TestAssets/Xml/include-target.xml new file mode 100644 index 0000000..866fe2a --- /dev/null +++ b/test/Reader/TestAssets/Xml/include-target.xml @@ -0,0 +1,2 @@ + +foo \ No newline at end of file diff --git a/test/Reader/TestAssets/Xml/non-existent-constant.xml b/test/Reader/TestAssets/Xml/non-existent-constant.xml new file mode 100644 index 0000000..e35d626 --- /dev/null +++ b/test/Reader/TestAssets/Xml/non-existent-constant.xml @@ -0,0 +1,6 @@ + + + + foo- + + \ No newline at end of file diff --git a/test/Reader/XmlTest.php b/test/Reader/XmlTest.php index 6c29965..f9d10a9 100644 --- a/test/Reader/XmlTest.php +++ b/test/Reader/XmlTest.php @@ -23,6 +23,7 @@ use \Zend\Config\Reader\Xml; + /** * @category Zend * @package Zend_Config @@ -31,57 +32,21 @@ * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ -class XmlTest extends \PHPUnit_Framework_TestCase +class XmlTest extends AbstractReaderTestCase { - /** - * @var Xml - */ - protected $reader; - - protected $_xmlFileConfig; - protected $_xmlFileAllSectionsConfig; - protected $_xmlFileCircularConfig; - protected $_xmlFileInvalid; - public function setUp() { $this->reader = new Xml(); } - - public function testConstants() - { - if (!defined('ZEND_CONFIG_XML_TEST_CONSTANT')) { - define('ZEND_CONFIG_XML_TEST_CONSTANT', 'test'); - } - - $string = << - - - foo--bar- - - - -EOT; - - $config = $this->reader->readString($string)->all; - - $this->assertEquals('foo-test-bar-test', $config->foo); - $this->assertEquals('ZEND_CONFIG_XML_TEST_CONSTANT', $config->bar->const->name); - } - - public function testNonExistentConstant() + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) { - $string = << - - - foo- - - -EOT; - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Constant with name "ZEND_CONFIG_XML_TEST_NON_EXISTENT_CONSTANT" was not defined'); - $config = $this->reader->readString($string); + return __DIR__ . '/TestAssets/Xml/' . $name . '.xml'; } } diff --git a/test/Reader/_files/allsections.ini b/test/Reader/_files/allsections.ini deleted file mode 100644 index a080611..0000000 --- a/test/Reader/_files/allsections.ini +++ /dev/null @@ -1,26 +0,0 @@ -[all] -hostname = all -name = thisname -db.host = 127.0.0.1 -db.user = username -db.pass = password -db.name = live -one.two.three = multi - -[staging : all] -hostname = staging -db.name = dbstaging -debug = false - -[debug:all] -hostname = debug -debug = true -values.changed = yes -db.name = dbdebug -special.no = no -special.null = null -special.false = false - -[other_staging] -only_in = otherStaging -db.pass = anotherpwd diff --git a/test/Reader/_files/allsections.json b/test/Reader/_files/allsections.json deleted file mode 100644 index 8b25955..0000000 --- a/test/Reader/_files/allsections.json +++ /dev/null @@ -1 +0,0 @@ -{"all":{"hostname":"all","name":"thisname","db":{"host":"127.0.0.1","user":"username","pass":"password","name":"live"},"one":{"two":{"three":"multi"}}},"staging":{"_extends":"all","db":{"name":"dbstaging"},"debug":false},"debug":{"_extends":"all","db":{"name":"dbdebug"},"debug":true,"values":{"changed":true},"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/Reader/_files/allsections.xml b/test/Reader/_files/allsections.xml deleted file mode 100644 index 1abb816..0000000 --- a/test/Reader/_files/allsections.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - all - thisname - - 127.0.0.1 - username - password - live - - - - multi - - - - - - staging - - dbstaging - - false - - - - otherStaging - - anotherpwd - - - - - \ No newline at end of file diff --git a/test/Reader/_files/allsections.yaml b/test/Reader/_files/allsections.yaml deleted file mode 100755 index 1dafe98..0000000 --- a/test/Reader/_files/allsections.yaml +++ /dev/null @@ -1,35 +0,0 @@ -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 diff --git a/test/Reader/_files/array.xml b/test/Reader/_files/array.xml deleted file mode 100644 index 9a98105..0000000 --- a/test/Reader/_files/array.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - 2a - 2b - - - - 5 - - 4 - - 5 - - - - - 1 - 1 - - - 2 - 2 - - - 3 - 3 - - - - diff --git a/test/Reader/_files/array.yaml b/test/Reader/_files/array.yaml deleted file mode 100755 index 31eaaf8..0000000 --- a/test/Reader/_files/array.yaml +++ /dev/null @@ -1,22 +0,0 @@ -one: - two: - - 2a - - 2b -three: - four: - - - five: 5 - - 4 - - - five: 5 -six: - seven: - - - eight: 1 - nine: 1 - - - eight: 2 - nine: 2 - - - eight: 3 - nine: 3 diff --git a/test/Reader/_files/badindentation.yaml b/test/Reader/_files/badindentation.yaml deleted file mode 100644 index 12e09a2..0000000 --- a/test/Reader/_files/badindentation.yaml +++ /dev/null @@ -1,6 +0,0 @@ -all: - hostname: all - name: thisname - foo: - bar - baz diff --git a/test/Reader/_files/booleans.yaml b/test/Reader/_files/booleans.yaml deleted file mode 100644 index 67a9277..0000000 --- a/test/Reader/_files/booleans.yaml +++ /dev/null @@ -1,29 +0,0 @@ -production: - usingLowerCasedYes: yes - usingTitleCasedYes: Yes - usingCapitalYes: YES - usingLowerY: y - usingUpperY: Y - - usingLowerCasedNo: no - usingTitleCasedNo: No - usingCapitalNo: NO - usingLowerN: n - usingUpperN: N - - usingLowerCasedTrue: true - usingTitleCasedTrue: True - usingCapitalTrue: TRUE - - usingLowerCasedFalse: false - usingTitleCasedFalse: False - usingCapitalFalse: FALSE - - usingLowerCasedOn: on - usingTitleCasedOn: On - usingCapitalOn: ON - - usingLowerCasedOff: off - usingTitleCasedOff: Off - usingCapitalOff: OFF - diff --git a/test/Reader/_files/circular.ini b/test/Reader/_files/circular.ini deleted file mode 100644 index 582fc6a..0000000 --- a/test/Reader/_files/circular.ini +++ /dev/null @@ -1,8 +0,0 @@ -[A : C] -someKey = value_A - -[B : A] -someKey = value_B - -[C : B] -someKey = value_C diff --git a/test/Reader/_files/circular.json b/test/Reader/_files/circular.json deleted file mode 100644 index 8c2f248..0000000 --- a/test/Reader/_files/circular.json +++ /dev/null @@ -1 +0,0 @@ -{"A":{"_extends":"C","someKey":"value_A"},"B":{"_extends":"A","someKey":"value_B"},"C":{"_extends":"B","someKey":"value_C"}} \ No newline at end of file diff --git a/test/Reader/_files/circular.xml b/test/Reader/_files/circular.xml deleted file mode 100644 index 5180525..0000000 --- a/test/Reader/_files/circular.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - value_A - - - value_B - - - value_C - - \ No newline at end of file diff --git a/test/Reader/_files/circular.yaml b/test/Reader/_files/circular.yaml deleted file mode 100755 index f6c760e..0000000 --- a/test/Reader/_files/circular.yaml +++ /dev/null @@ -1,9 +0,0 @@ -A: - someKey: value_A - _extends: C -B: - someKey: value_B - _extends: A -C: - someKey: value_C - _extends: B diff --git a/test/Reader/_files/config.ini b/test/Reader/_files/config.ini deleted file mode 100644 index d88bb23..0000000 --- a/test/Reader/_files/config.ini +++ /dev/null @@ -1,50 +0,0 @@ -[all] -hostname = all -name = thisname -db.host = 127.0.0.1 -db.user = username -db.pass = password -db.name = live -one.two.three = multi - -[staging: all] -hostname = staging -db.name = dbstaging -debug = false - -[debug:all] -hostname = debug -debug = true -values.changed = yes -db.name = dbdebug -special.no = no -special.null = null -special.false = false - -[other_staging: staging] -only_in = otherStaging -db.pass = anotherpwd - - -; invalid keys -[leadingdot] -.test = dot-test - -[onedot] -. = dot-test - -[twodots] -... = dot-test - -[threedots] -... = dot-test - -[trailingdot] -test. = dot-test - -[extendserror:nonexistent] -testing =123 - -[zf426] -db = one -db.name = two diff --git a/test/Reader/_files/config.json b/test/Reader/_files/config.json deleted file mode 100644 index ebeb16c..0000000 --- a/test/Reader/_files/config.json +++ /dev/null @@ -1 +0,0 @@ -{"all":{"hostname":"all","name":"thisname","db":{"host":"127.0.0.1","user":"username","pass":"password","name":"live"},"one":{"two":{"three":"multi"}}},"staging":{"_extends":"all","hostname":"staging","db":{"name":"dbstaging"},"debug":false},"debug":{"_extends":"all","db":{"name":"dbdebug"},"debug":true,"values":{"changed":true},"special":{"no":"no","null":null,"false":false}},"other_staging":{"_extends":"staging","only_in":"otherStaging","db":{"pass":"anotherpwd"}},"extendserror":{"_extends":"nonexistent","testing":123}} diff --git a/test/Reader/_files/config.xml b/test/Reader/_files/config.xml deleted file mode 100644 index 517bef8..0000000 --- a/test/Reader/_files/config.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - all - thisname - - 127.0.0.1 - username - password - live - - - - multi - - - - - - staging - - dbstaging - - false - - - - otherStaging - - anotherpwd - - - - - - \ No newline at end of file diff --git a/test/Reader/_files/config.yaml b/test/Reader/_files/config.yaml deleted file mode 100755 index 3fa7d37..0000000 --- a/test/Reader/_files/config.yaml +++ /dev/null @@ -1,38 +0,0 @@ -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: - _extends: all -debug: - hostname: debug - debug: 1 - values: - changed: 1 - db: - name: dbdebug - special: - no: - null: - false: - zero: 0 - _extends: all -other_staging: - only_in: otherStaging - db: - pass: anotherpwd - _extends: staging -extendserror: - testing: 123 - _extends: notexistent diff --git a/test/Reader/_files/constants.yaml b/test/Reader/_files/constants.yaml deleted file mode 100644 index 2dbf595..0000000 --- a/test/Reader/_files/constants.yaml +++ /dev/null @@ -1,3 +0,0 @@ -production: - env: ZEND_CONFIG_YAML_ENV - path: ZEND_CONFIG_YAML_ENV_PATH/test/this diff --git a/test/Reader/_files/invalid.ini b/test/Reader/_files/invalid.ini deleted file mode 100644 index bc90cb1..0000000 --- a/test/Reader/_files/invalid.ini +++ /dev/null @@ -1,3 +0,0 @@ -[default] -#deprecated comment -foo = /("bar) diff --git a/test/Reader/_files/invalid.json b/test/Reader/_files/invalid.json deleted file mode 100644 index 613fa3a..0000000 --- a/test/Reader/_files/invalid.json +++ /dev/null @@ -1 +0,0 @@ -{"default":{"foo":/("bar)}} diff --git a/test/Reader/_files/invalid.xml b/test/Reader/_files/invalid.xml deleted file mode 100644 index ad5f224..0000000 --- a/test/Reader/_files/invalid.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - InvalidValue &undefined; - - - value_B - - - value_C - - \ No newline at end of file diff --git a/test/Reader/_files/invalid.yaml b/test/Reader/_files/invalid.yaml deleted file mode 100755 index 1308c3b..0000000 --- a/test/Reader/_files/invalid.yaml +++ /dev/null @@ -1,2 +0,0 @@ -yaml: - what? \ No newline at end of file diff --git a/test/Reader/_files/multipleinheritance.ini b/test/Reader/_files/multipleinheritance.ini deleted file mode 100644 index 0b51005..0000000 --- a/test/Reader/_files/multipleinheritance.ini +++ /dev/null @@ -1,8 +0,0 @@ -[one] -one = 1 - -[two] -two = 2 - -[multiinherit: one: two] -three=3 diff --git a/test/Reader/_files/multipleinheritance.json b/test/Reader/_files/multipleinheritance.json deleted file mode 100644 index d51fde3..0000000 --- a/test/Reader/_files/multipleinheritance.json +++ /dev/null @@ -1 +0,0 @@ -{"one":{"one":1},"two":{"two":2},"multiinherit":{"_extends":["one","two"]}} \ No newline at end of file diff --git a/test/Reader/_files/nested.json b/test/Reader/_files/nested.json deleted file mode 100644 index 11835d8..0000000 --- a/test/Reader/_files/nested.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "testing": { - "definitions": [ - { - "class": "Zend\\Di\\TestAsset\\Struct", - "params": { - "param1": "foo", - "param2": "bar" - }, - "param_map": { - "param1": 0, - "param2": 1 - } - }, - { - "class": "Zend\\Di\\TestAsset\\DummyParams", - "constructor_callback": { - "class": "Zend\\Di\\TestAsset\\StaticFactory", - "method": "factory" - }, - "params": { - "struct": { "__reference": "struct" }, - "params": {"foo": "bar"} - }, - "param_map": { - "struct": 0, - "params": 1 - } - }, - { - "class": "Zend\\Di\\TestAsset\\InjectedMethod", - "methods": [ - { - "name": "setObject", - "args": [ { "__reference": "params" } ] - } - ] - }, - { - "class": "Zend\\Di\\TestAsset\\InspectedClass", - "params": { - "baz": "BAZ", - "foo": "FOO" - } - } - ], - "aliases": { - "struct": "Zend\\Di\\TestAsset\\Struct", - "params": "Zend\\Di\\TestAsset\\DummyParams", - "injected": "Zend\\Di\\TestAsset\\InjectedMethod", - "inspected": "Zend\\Di\\TestAsset\\InspectedClass" - } - } -} diff --git a/test/Reader/_files/nosections.ini b/test/Reader/_files/nosections.ini deleted file mode 100644 index 7b4ed43..0000000 --- a/test/Reader/_files/nosections.ini +++ /dev/null @@ -1,5 +0,0 @@ - -hostname = all -one.two = two -one.three.four = 4 -one.three.five = 5 diff --git a/test/Reader/_files/nosections.json b/test/Reader/_files/nosections.json deleted file mode 100644 index ac25dc3..0000000 --- a/test/Reader/_files/nosections.json +++ /dev/null @@ -1 +0,0 @@ -{"hostname":"all","one":{"two":"two","three":{"four":4,"five":5}}} \ No newline at end of file diff --git a/test/Reader/_files/onetoplevelstring.xml b/test/Reader/_files/onetoplevelstring.xml deleted file mode 100644 index 04be370..0000000 --- a/test/Reader/_files/onetoplevelstring.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - one - \ No newline at end of file diff --git a/test/Reader/_files/separator.ini b/test/Reader/_files/separator.ini deleted file mode 100644 index 94323af..0000000 --- a/test/Reader/_files/separator.ini +++ /dev/null @@ -1,8 +0,0 @@ -[all] -hostname = all -name = thisname -db:host = 127.0.0.1 -db:user = username -db:pass = password -db:name = live -one:two:three = multi \ No newline at end of file diff --git a/test/Reader/_files/shortparamsone.xml b/test/Reader/_files/shortparamsone.xml deleted file mode 100644 index bee0f20..0000000 --- a/test/Reader/_files/shortparamsone.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/Reader/_files/shortparamstwo.xml b/test/Reader/_files/shortparamstwo.xml deleted file mode 100644 index 1eb1074..0000000 --- a/test/Reader/_files/shortparamstwo.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/Reader/_files/toplevelstring.xml b/test/Reader/_files/toplevelstring.xml deleted file mode 100644 index 59e2587..0000000 --- a/test/Reader/_files/toplevelstring.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - one - - three - - five - - - - \ No newline at end of file diff --git a/test/Reader/_files/zf2843.ini b/test/Reader/_files/zf2843.ini deleted file mode 100644 index ac510ea..0000000 --- a/test/Reader/_files/zf2843.ini +++ /dev/null @@ -1,3 +0,0 @@ -abc = def -ghi = jkl -abc=123 diff --git a/test/Reader/_files/zf5800.ini b/test/Reader/_files/zf5800.ini deleted file mode 100644 index 30fb918..0000000 --- a/test/Reader/_files/zf5800.ini +++ /dev/null @@ -1,11 +0,0 @@ - -[rec] -receiver.mail = user1@company.com -receiver.name = "User name" -receiver.html = 1 - -[dev: rec] -receiver.0.mail = "nice.guy@company.com" -receiver.0.name = "Nice Guy" -receiver.1.mail = "fred@company.com" -receiver.1.html = 2 diff --git a/test/Reader/_files/zf6508.ini b/test/Reader/_files/zf6508.ini deleted file mode 100644 index 66aae35..0000000 --- a/test/Reader/_files/zf6508.ini +++ /dev/null @@ -1,3 +0,0 @@ -[all] -1001 = Error Message for 1001 -1002 = Error Message for 1002 diff --git a/test/Reader/_files/zf8159.ini b/test/Reader/_files/zf8159.ini deleted file mode 100644 index 2cec0b3..0000000 --- a/test/Reader/_files/zf8159.ini +++ /dev/null @@ -1,4 +0,0 @@ -[first] -user.login.elements.username.type = "text" -[second] -user.login.elements.password.type = "password" \ No newline at end of file From 9ec9c4ee4618511c30a1408831b3d46a3b57e617 Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Thu, 3 Nov 2011 00:18:35 +0100 Subject: [PATCH 02/18] Added support to XML reader --- src/Reader/Xml.php | 19 +++++++++++++++++++ test/Reader/AbstractReaderTestCase.php | 18 +++++++++++++++++- test/Reader/TestAssets/Xml/current-dir.xml | 6 ++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test/Reader/TestAssets/Xml/current-dir.xml diff --git a/src/Reader/Xml.php b/src/Reader/Xml.php index 6e57826..763b440 100644 --- a/src/Reader/Xml.php +++ b/src/Reader/Xml.php @@ -48,6 +48,13 @@ class Xml extends AbstractReader */ protected $reader; + /** + * Filename of the file to process. + * + * @var string + */ + protected $filename; + /** * Nodes to handle as plain text. * @@ -70,6 +77,8 @@ protected function processFile($filename) $this->reader = new XMLReader(); $this->reader->open($filename, null, LIBXML_XINCLUDE); + $this->filename = $filename; + return $this->process(); } @@ -85,6 +94,8 @@ protected function processString($data) $this->reader = new XMLReader(); $this->reader->xml($data, null, LIBXML_XINCLUDE); + $this->filename = null; + return $this->process(); } @@ -140,6 +151,14 @@ protected function processNextElement() $text .= constant($constantName); break; + + case 'dir': + if ($this->filename !== null) { + $text .= dirname($this->filename); + } else { + $text .= __DIR__; + } + break; default: throw new Exception\RuntimeException(sprintf('Unknown zf:node with name "%s" found', $name)); diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php index 294ebf0..f71be8d 100644 --- a/test/Reader/AbstractReaderTestCase.php +++ b/test/Reader/AbstractReaderTestCase.php @@ -22,7 +22,8 @@ namespace ZendTest\Config\Reader; use \PHPUnit_Framework_TestCase as TestCase, - \Zend\Config\Reader\Reader; + \Zend\Config\Reader\Reader, + \ReflectionClass; /** * @category Zend @@ -51,6 +52,21 @@ public function testInclude() $config = $this->reader->readFile($this->getTestAssetPath('include-base')); $this->assertEquals('foo', $config->base->foo); } + + public function testCurrentDirInFile() + { + $config = $this->reader->readFile($this->getTestAssetPath('current-dir')); + + $this->assertEquals(dirname($this->getTestAssetPath('current-dir')), $config->base->foo); + } + + public function testCurrentDirInString() + { + $config = $this->reader->readString(file_get_contents($this->getTestAssetPath('current-dir'))); + $reflectionClass = new ReflectionClass($this->reader); + + $this->assertEquals(dirname($reflectionClass->getFileName()), $config->base->foo); + } public function testConstants() { diff --git a/test/Reader/TestAssets/Xml/current-dir.xml b/test/Reader/TestAssets/Xml/current-dir.xml new file mode 100644 index 0000000..29326ac --- /dev/null +++ b/test/Reader/TestAssets/Xml/current-dir.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 0ea18a87b7485a6506bf2fd789570684c4c87adb Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Thu, 3 Nov 2011 00:26:55 +0100 Subject: [PATCH 03/18] Added storing of extends in sectioned config --- src/Reader/AbstractReader.php | 26 +++++++++++---- src/SectionedConfig.php | 60 ----------------------------------- 2 files changed, 19 insertions(+), 67 deletions(-) diff --git a/src/Reader/AbstractReader.php b/src/Reader/AbstractReader.php index 628d6c6..5f647ea 100644 --- a/src/Reader/AbstractReader.php +++ b/src/Reader/AbstractReader.php @@ -65,10 +65,16 @@ abstract class AbstractReader implements Reader public function readFile($filename) { $this->extends = array(); + + $config = new SectionedConfig( + $this->processAllExtends($this->processFile($filename)) + ); - $data = $this->processAllExtends($this->processFile($filename)); + foreach (($this->extends ?: $this->processedExtends) as $extendingSection => $extendedSection) { + $config->setExtend($extendingSection, $extendedSection); + } - return new SectionedConfig($data); + return $config; } /** @@ -81,9 +87,15 @@ public function readString($string) { $this->extends = array(); - $data = $this->processAllExtends($this->processString($string)); + $config = new SectionedConfig( + $this->processAllExtends($this->processString($string)) + ); - return new SectionedConfig($data); + foreach (($this->extends ?: $this->processedExtends) as $extendingSection => $extendedSection) { + $config->setExtend($extendingSection, $extendedSection); + } + + return $config; } /** @@ -109,14 +121,14 @@ abstract protected function processString($string); */ protected function processAllExtends(array $data) { + $this->processedExtends = array(); + if (!$this->shouldProcessExtends()) { return $data; } // Check for circular extends - $this->processedExtends = array(); - $extends = $this->extends; - $processedExtends = array(); + $extends = $this->extends; foreach ($extends as $extendingSection => $extendedSection) { if (!isset($data[$extendedSection])) { diff --git a/src/SectionedConfig.php b/src/SectionedConfig.php index a2af239..75b4d3e 100644 --- a/src/SectionedConfig.php +++ b/src/SectionedConfig.php @@ -31,16 +31,6 @@ */ class SectionedConfig extends Config { - /** - * Contains which config sections were loaded. - * - * This is null if all sections were loaded, a string name if one section is - * loaded and an array of string names if multiple sections were loaded. - * - * @var mixed - */ - protected $loadedSection; - /** * This is used to track section inheritance. * @@ -51,30 +41,6 @@ class SectionedConfig extends Config */ protected $extends = array(); - /** - * Returns the section name(s) loaded. - * - * @return mixed - */ - public function getSectionName() - { - if (is_array($this->loadedSection) && count($this->_loadedSection) === 1) { - $this->loadedSection = $this->loadedSection[0]; - } - - return $this->loadedSection; - } - - /** - * Returns true if all sections were loaded - * - * @return boolean - */ - public function areAllSectionsLoaded() - { - return $this->loadedSection === null; - } - /** * Get the current extends. * @@ -100,30 +66,4 @@ public function setExtend($extendingSection, $extendedSection = null) $this->extends[$extendingSection] = $extendedSection; } } - - /** - * Throws an exception if $extendingSection may not extend $extendedSection, - * and tracks the section extension if it is valid. - * - * @param string $extendingSection - * @param string $extendedSection - * @throws \Zend\Config\Exception - * @return void - */ - protected function assertValidExtend($extendingSection, $extendedSection) - { - // Detect circular section inheritance - $currentExtendedSection = $extendedSection; - - while (array_key_exists($currentExtendedSection, $this->extends)) { - if ($this->extends[$currentExtendedSection] == $extendingSection) { - throw new Exception\RuntimeException('Illegal circular inheritance detected'); - } - - $currentExtendedSection = $this->_extends[$currentExtendedSection]; - } - - // Remember that this section extends another section - $this->_extends[$extendingSection] = $extendedSection; - } } From 7e2a66965e672242e2d47bd3bbcaed85405ef4a7 Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Thu, 3 Nov 2011 04:08:13 +0100 Subject: [PATCH 04/18] Added INI reader --- src/Reader/Ini.php | 176 ++++++++++++++++++ src/Reader/Xml.php | 35 ++-- test/Reader/AbstractReaderTestCase.php | 6 - test/Reader/IniTest.php | 58 ++++++ test/Reader/TestAssets/Ini/constants.ini | 3 + test/Reader/TestAssets/Ini/current-dir.ini | 2 + test/Reader/TestAssets/Ini/include-base.ini | 2 + test/Reader/TestAssets/Ini/include-target.ini | 1 + .../TestAssets/Ini/non-existent-constant.ini | 2 + test/Reader/XmlTest.php | 7 + 10 files changed, 266 insertions(+), 26 deletions(-) create mode 100644 src/Reader/Ini.php create mode 100644 test/Reader/IniTest.php create mode 100644 test/Reader/TestAssets/Ini/constants.ini create mode 100644 test/Reader/TestAssets/Ini/current-dir.ini create mode 100644 test/Reader/TestAssets/Ini/include-base.ini create mode 100644 test/Reader/TestAssets/Ini/include-target.ini create mode 100644 test/Reader/TestAssets/Ini/non-existent-constant.ini diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php new file mode 100644 index 0000000..79e7cc0 --- /dev/null +++ b/src/Reader/Ini.php @@ -0,0 +1,176 @@ +directory = dirname($filename); + + return $this->process(parse_ini_file($filename, true)); + } + + /** + * processString(): defined by AbstractReader. + * + * @see AbstractReader::processString() + * @param string $string + * @return array + */ + protected function processString($string) + { + $this->directory = __DIR__; + + return $this->process(parse_ini_string($string, true)); + } + + /** + * Process data from the parsed ini file. + * + * @param array $data + * @return array + */ + protected function process(array $data) + { + $this->extends = array(); + $config = array(); + + foreach ($data as $key => $value) { + $pieces = explode($this->sectionSeparator, $key); + $section = trim($pieces[0]); + + switch (count($pieces)) { + case 2: + $this->extends[$section] = trim($pieces[1]); + // Break intentionally omitted. + + case 1: + if (is_array($value)) { + $config[$section] = $this->processSection($value); + } else { + $config[$section] = $value; + } + break; + + default: + throw new Exception\RuntimeException(sprintf('Section "%s" may not extend multiple sexctions', $section)); + } + } + + return $config; + } + + /** + * Process a section. + * + * @param array $section + * @return array + */ + protected function processSection(array $section) + { + $config = array(); + + foreach ($section as $key => $value) { + $this->processKey($key, $value, $config); + } + + return $config; + } + + /** + * Process a key. + * + * @param string $key + * @param string $value + * @param array $config + * @return array + */ + protected function processKey($key, $value, array &$config) + { + if (strpos($key, $this->nestSeparator) !== false) { + $pieces = explode($this->nestSeparator, $key, 2); + + if (!strlen($pieces[0]) || !strlen($pieces[1])) { + throw new Exception\RuntimeException(sprintf('Invalid key "%s"', $key)); + } elseif (!isset($config[$pieces[0]])) { + if ($pieces[0] === '0' && !empty($config)) { + $config = array($pieces[0] => $config); + } else { + $config[$pieces[0]] = array(); + } + } elseif (!is_array($config[$pieces[0]])) { + throw new Exception\RuntimeException(sprintf('Cannot create sub-key for "%s", as key already exists', $pieces[0])); + } + + $this->processKey($pieces[1], $value, $config[$pieces[0]]); + } else { + if ($key === '@include') { + $reader = clone $this; + $include = $reader->readFile($this->directory . '/' . $value)->toArray(); + $config = array_replace_recursive($config, $include); + } else { + $config[$key] = str_replace('{DIR}', $this->directory, $value); + } + } + } +} diff --git a/src/Reader/Xml.php b/src/Reader/Xml.php index 763b440..df5123f 100644 --- a/src/Reader/Xml.php +++ b/src/Reader/Xml.php @@ -49,11 +49,11 @@ class Xml extends AbstractReader protected $reader; /** - * Filename of the file to process. + * Directory of the file to process. * * @var string */ - protected $filename; + protected $directory; /** * Nodes to handle as plain text. @@ -66,35 +66,35 @@ class Xml extends AbstractReader ); /** - * processFile(): defined by Reader interface. + * processFile(): defined by AbstractReader. * - * @see Reader::processFile() + * @see AbstractReader::processFile() * @param string $filename - * @return Config + * @return array */ protected function processFile($filename) { $this->reader = new XMLReader(); $this->reader->open($filename, null, LIBXML_XINCLUDE); - $this->filename = $filename; + $this->directory = dirname($filename); return $this->process(); } /** - * processString(): defined by Reader interface. + * processString(): defined by AbstractReader. * - * @see Reader::processString() - * @param string $data - * @return Config + * @see AbstractReader::processString() + * @param string $string + * @return array */ - protected function processString($data) + protected function processString($string) { $this->reader = new XMLReader(); - $this->reader->xml($data, null, LIBXML_XINCLUDE); + $this->reader->xml($string, null, LIBXML_XINCLUDE); - $this->filename = null; + $this->directory = __DIR__; return $this->process(); } @@ -102,12 +102,11 @@ protected function processString($data) /** * Process data from the created XMLReader. * - * @return Config + * @return array */ protected function process() { $this->extends = array(); - $this->depth = 0; return $this->processNextElement(); } @@ -153,11 +152,7 @@ protected function processNextElement() break; case 'dir': - if ($this->filename !== null) { - $text .= dirname($this->filename); - } else { - $text .= __DIR__; - } + $text .= $this->directory; break; default: diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php index f71be8d..65af19e 100644 --- a/test/Reader/AbstractReaderTestCase.php +++ b/test/Reader/AbstractReaderTestCase.php @@ -79,10 +79,4 @@ public function testConstants() $this->assertEquals('foo-test-bar-test', $config->base->foo); $this->assertEquals('ZEND_CONFIG_TEST_CONSTANT', $config->base->bar->const->name); } - - public function testNonExistentConstant() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Constant with name "ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT" was not defined'); - $config = $this->reader->readFile($this->getTestAssetPath('non-existent-constant')); - } } diff --git a/test/Reader/IniTest.php b/test/Reader/IniTest.php new file mode 100644 index 0000000..6bf6859 --- /dev/null +++ b/test/Reader/IniTest.php @@ -0,0 +1,58 @@ +reader = new Ini(); + } + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) + { + return __DIR__ . '/TestAssets/Ini/' . $name . '.ini'; + } + + public function testNonExistentConstant() + { + $config = $this->reader->readFile($this->getTestAssetPath('non-existent-constant')); + + $this->assertEquals('foo-ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT', $config->base->foo); + } +} diff --git a/test/Reader/TestAssets/Ini/constants.ini b/test/Reader/TestAssets/Ini/constants.ini new file mode 100644 index 0000000..a11988b --- /dev/null +++ b/test/Reader/TestAssets/Ini/constants.ini @@ -0,0 +1,3 @@ +[base] +foo = 'foo-'ZEND_CONFIG_TEST_CONSTANT'-bar-'ZEND_CONFIG_TEST_CONSTANT +bar.const.name = 'ZEND_CONFIG_TEST_CONSTANT' diff --git a/test/Reader/TestAssets/Ini/current-dir.ini b/test/Reader/TestAssets/Ini/current-dir.ini new file mode 100644 index 0000000..4b8b897 --- /dev/null +++ b/test/Reader/TestAssets/Ini/current-dir.ini @@ -0,0 +1,2 @@ +[base] +foo = '{DIR}' diff --git a/test/Reader/TestAssets/Ini/include-base.ini b/test/Reader/TestAssets/Ini/include-base.ini new file mode 100644 index 0000000..d81f5c3 --- /dev/null +++ b/test/Reader/TestAssets/Ini/include-base.ini @@ -0,0 +1,2 @@ +[base] +@include = 'include-target.ini' diff --git a/test/Reader/TestAssets/Ini/include-target.ini b/test/Reader/TestAssets/Ini/include-target.ini new file mode 100644 index 0000000..7d854c9 --- /dev/null +++ b/test/Reader/TestAssets/Ini/include-target.ini @@ -0,0 +1 @@ +foo = 'foo' diff --git a/test/Reader/TestAssets/Ini/non-existent-constant.ini b/test/Reader/TestAssets/Ini/non-existent-constant.ini new file mode 100644 index 0000000..2abc0e1 --- /dev/null +++ b/test/Reader/TestAssets/Ini/non-existent-constant.ini @@ -0,0 +1,2 @@ +[base] +foo = 'foo-'ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT diff --git a/test/Reader/XmlTest.php b/test/Reader/XmlTest.php index f9d10a9..042cf2e 100644 --- a/test/Reader/XmlTest.php +++ b/test/Reader/XmlTest.php @@ -49,4 +49,11 @@ protected function getTestAssetPath($name) { return __DIR__ . '/TestAssets/Xml/' . $name . '.xml'; } + + public function testNonExistentConstant() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Constant with name "ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT" was not defined'); + $config = $this->reader->readFile($this->getTestAssetPath('non-existent-constant')); + var_dump($config); + } } From ef4f4bd3d93b479eb4bfc2edba1770222d7f29be Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Thu, 3 Nov 2011 04:10:31 +0100 Subject: [PATCH 05/18] Added getters and setters for nest/section separator --- src/Reader/Ini.php | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php index 79e7cc0..2bcea56 100644 --- a/src/Reader/Ini.php +++ b/src/Reader/Ini.php @@ -56,6 +56,50 @@ class Ini extends AbstractReader */ protected $directory; + /** + * Set nest separator. + * + * @param stirng $separator + * @return self + */ + public function setNestSeparator($separator) + { + $this->nestSeparator = $separator; + return $this; + } + + /** + * Get nest separator. + * + * @return string + */ + public function getNestSeparator() + { + return $this->nestSeparator; + } + + /** + * Set section separator. + * + * @param string $separator + * @return self + */ + public function setSectionSeparator($separator) + { + $this->sectionSeparator = $separator; + return $this; + } + + /** + * Get section separator. + * + * @return string + */ + public function getSectionSeparator() + { + return $this->sectionSeparator; + } + /** * processFile(): defined by AbstractReader. * From f4d62dc6063b6a8944951ea5ac8fa879b896d670 Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Sun, 18 Dec 2011 17:58:57 +0100 Subject: [PATCH 06/18] Some refactoring on the writers --- src/Config.php | 69 ++++---- src/Exception.php | 19 +-- src/Exception/InvalidArgumentException.php | 24 +++ src/Exception/RuntimeException.php | 24 +++ src/Reader.php | 46 ++++++ src/Reader/AbstractReader.php | 100 +++++------- src/Reader/Ini.php | 85 +++++----- src/Reader/Xml.php | 87 +++++------ src/SectionedConfig.php | 69 -------- src/Writer.php | 48 ++++++ src/Writer/AbstractFileWriter.php | 136 ---------------- src/Writer/AbstractWriter.php | 88 ++++------- src/Writer/ArrayWriter.php | 55 ------- src/Writer/Ini.php | 147 +++++++++--------- src/Writer/Json.php | 100 ------------ .../Reader.php => Writer/PhpArray.php} | 34 ++-- src/Writer/Xml.php | 94 +++++------ src/Writer/Yaml.php | 138 ---------------- 18 files changed, 472 insertions(+), 891 deletions(-) create mode 100644 src/Reader.php delete mode 100644 src/SectionedConfig.php create mode 100644 src/Writer.php delete mode 100644 src/Writer/AbstractFileWriter.php delete mode 100644 src/Writer/ArrayWriter.php delete mode 100644 src/Writer/Json.php rename src/{Reader/Reader.php => Writer/PhpArray.php} (68%) delete mode 100644 src/Writer/Yaml.php diff --git a/src/Config.php b/src/Config.php index 91dd273..8d93941 100644 --- a/src/Config.php +++ b/src/Config.php @@ -12,26 +12,23 @@ * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * - * @category Zend - * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @category Zend + * @package Zend_Config + * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config; -use \Countable, - \Iterator, - \ArrayAccess; +use Countable, + Iterator, + ArrayAccess; /** - * @category Zend - * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @category Zend + * @package Zend_Config + * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License */ class Config implements Countable, Iterator, ArrayAccess { @@ -93,7 +90,7 @@ public function __construct(array $array, $allowModifications = false) } else { $this->data[$key] = $value; } - + $this->count++; } } @@ -110,7 +107,7 @@ public function get($name, $default = null) if (array_key_exists($name, $this->data)) { return $this->data[$name]; } - + return $default; } @@ -127,7 +124,7 @@ public function __get($name) /** * Set a value in the config. - * + * * Only allow setting of a property if $allowModifications was set to true * on construction. Otherwise, throw an exception. * @@ -143,7 +140,7 @@ public function __set($name, $value) } else { $this->data[$name] = $value; } - + $this->count++; } else { throw new Exception\RuntimeException('Config is read only'); @@ -159,7 +156,7 @@ public function __set($name, $value) public function __clone() { $array = array(); - + foreach ($this->data as $key => $value) { if ($value instanceof self) { $array[$key] = clone $value; @@ -167,7 +164,7 @@ public function __clone() $array[$key] = $value; } } - + $this->data = $array; } @@ -180,7 +177,7 @@ public function toArray() { $array = array(); $data = $this->data; - + foreach ($data as $key => $value) { if ($value instanceof self) { $array[$key] = $value->toArray(); @@ -188,7 +185,7 @@ public function toArray() $array[$key] = $value; } } - + return $array; } @@ -215,14 +212,14 @@ public function __unset($name) throw new Exception\InvalidArgumentException('Config is read only'); } elseif (isset($this->data[$name])) { unset($this->data[$name]); - $this->count--; + $this->count--; $this->skipNextIteration = true; } } /** * count(): defined by Countable interface. - * + * * @see Countable::count() * @return integer */ @@ -266,7 +263,7 @@ public function next() $this->skipNextIteration = false; return; } - + next($this->data); } @@ -295,7 +292,7 @@ public function valid() /** * offsetExists(): defined by ArrayAccess interface. - * + * * @see ArrayAccess::offsetExists() * @param mixed $offset * @return boolean @@ -304,10 +301,10 @@ public function offsetExists($offset) { return $this->__isset($offset); } - + /** * offsetGet(): defined by ArrayAccess interface. - * + * * @see ArrayAccess::offsetGet() * @param mixed $offset * @return mixed @@ -316,10 +313,10 @@ public function offsetGet($offset) { return $this->__get($offset); } - + /** * offsetSet(): defined by ArrayAccess interface. - * + * * @see ArrayAccess::offsetSet() * @param mixed $offset * @param mixed $value @@ -329,10 +326,10 @@ public function offsetSet($offset, $value) { $this->__set($offset, $value); } - + /** * offsetUnset(): defined by ArrayAccess interface. - * + * * @see ArrayAccess::offsetUnset() * @param mixed $offset * @return void @@ -341,10 +338,10 @@ public function offsetUnset($offset) { $this->__unset($offset); } - + /** * Merge another Config with this one. - * + * * The items in $merge will override the same named items in the current * config. * @@ -374,7 +371,7 @@ public function merge(self $merge) /** * Prevent any more modifications being made to this instance. - * + * * Useful after merge() has been used to merge multiple Config objects * into one object which should then not be modified again. * @@ -383,7 +380,7 @@ public function merge(self $merge) public function setReadOnly() { $this->allowModifications = false; - + foreach ($this->data as $key => $value) { if ($value instanceof self) { $value->setReadOnly(); diff --git a/src/Exception.php b/src/Exception.php index 3e10647..f5878d3 100644 --- a/src/Exception.php +++ b/src/Exception.php @@ -12,22 +12,19 @@ * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * - * @category Zend - * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @category Zend + * @package Zend_Config + * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config; /** - * @category Zend - * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @category Zend + * @package Zend_Config + * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License */ interface Exception {} diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index e5f5616..8900ee2 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -1,7 +1,31 @@ extends = array(); - $config = new SectionedConfig( - $this->processAllExtends($this->processFile($filename)) - ); - - foreach (($this->extends ?: $this->processedExtends) as $extendingSection => $extendedSection) { - $config->setExtend($extendingSection, $extendedSection); - } - - return $config; + return $this->processAllExtends($this->processFile($filename)); } - + /** - * Read a string and create a config object. - * + * readString(): defined by Reader interface. + * + * @see Reader::readString() * @param string $string - * @return Config + * @return array */ public function readString($string) { $this->extends = array(); - - $config = new SectionedConfig( - $this->processAllExtends($this->processString($string)) - ); - foreach (($this->extends ?: $this->processedExtends) as $extendingSection => $extendedSection) { - $config->setExtend($extendingSection, $extendedSection); - } - - return $config; + return $this->processAllExtends($this->processString($string)); } - + /** * Process a file. - * + * * @param string $filename * @return array */ abstract protected function processFile($filename); - + /** * Process a string. - * + * * @param string $string * @return array */ abstract protected function processString($string); - + /** * Process all extends directives. - * + * * @return array */ protected function processAllExtends(array $data) { $this->processedExtends = array(); - + if (!$this->shouldProcessExtends()) { return $data; } - + // Check for circular extends $extends = $this->extends; - + foreach ($extends as $extendingSection => $extendedSection) { if (!isset($data[$extendedSection])) { throw new Exception\RuntimeException(sprintf('Missing extended section "%s"', $extendedSection)); @@ -138,19 +122,19 @@ protected function processAllExtends(array $data) } elseif (!isset($this->extends[$extendingSection])) { continue; } - + $this->processExtend($data, $extendingSection, $extendedSection); } - + return $data; } - + /** * Process a single extend directive. - * + * * The $data array is always passed by references, so modifications on it * won't require a copy of it (since it is always modified) on every call. - * + * * @param array $data * @param string $extendingSection * @param string $extendedSection @@ -161,9 +145,9 @@ protected function processExtend(array &$data, $extendingSection, $extendedSecti if (isset($this->processedExtends[$extendingSection])) { throw new Exception\RuntimeException('Illegal circular inheritance detected'); } - + $this->processedExtends[$extendingSection] = $extendedSection; - + if (isset($this->extends[$extendedSection])) { $this->processExtends($data, $extendedSection, $this->extends[$extendedSection]); } @@ -172,13 +156,13 @@ protected function processExtend(array &$data, $extendingSection, $extendedSecti $data[$extendedSection], $data[$extendingSection] ); - + unset($this->extends[$extendingSection]); } - + /** * Set whether to process extends. - * + * * @param boolean $flag * @return self */ @@ -187,10 +171,10 @@ public function setProcessExtendsFlag($flag) $this->processExtends = (boolean) $flag; return $this; } - + /** * Check whether to process extends. - * + * * @return boolean */ public function shouldProcessExtends() diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php index 2bcea56..6b110c0 100644 --- a/src/Reader/Ini.php +++ b/src/Reader/Ini.php @@ -12,53 +12,52 @@ * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * - * @category Zend - * @package Zend_Config + * @category Zend + * @package Zend_Config + * @subpackage Reader * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Reader; -use \Zend\Config\Exception; +use Zend\Config\Exception; /** * XML config reader. * - * @category Zend - * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @category Zend + * @package Zend_Config + * @subpackage Reader + * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License */ class Ini extends AbstractReader { /** * Separator for nesting levels of configuration data identifiers. - * + * * @var string */ protected $nestSeparator = '.'; - + /** * Separator for parent section names. - * + * * @var string */ protected $sectionSeparator = ':'; /** * Directory of the file to process. - * + * * @var string */ protected $directory; /** * Set nest separator. - * + * * @param stirng $separator * @return self */ @@ -67,20 +66,20 @@ public function setNestSeparator($separator) $this->nestSeparator = $separator; return $this; } - + /** * Get nest separator. - * + * * @return string */ public function getNestSeparator() { return $this->nestSeparator; } - + /** * Set section separator. - * + * * @param string $separator * @return self */ @@ -89,20 +88,20 @@ public function setSectionSeparator($separator) $this->sectionSeparator = $separator; return $this; } - + /** * Get section separator. - * + * * @return string */ public function getSectionSeparator() { return $this->sectionSeparator; } - + /** * processFile(): defined by AbstractReader. - * + * * @see AbstractReader::processFile() * @param string $filename * @return array @@ -110,13 +109,13 @@ public function getSectionSeparator() protected function processFile($filename) { $this->directory = dirname($filename); - + return $this->process(parse_ini_file($filename, true)); } - + /** * processString(): defined by AbstractReader. - * + * * @see AbstractReader::processString() * @param string $string * @return array @@ -124,13 +123,13 @@ protected function processFile($filename) protected function processString($string) { $this->directory = __DIR__; - + return $this->process(parse_ini_string($string, true)); } - + /** * Process data from the parsed ini file. - * + * * @param array $data * @return array */ @@ -142,12 +141,12 @@ protected function process(array $data) foreach ($data as $key => $value) { $pieces = explode($this->sectionSeparator, $key); $section = trim($pieces[0]); - + switch (count($pieces)) { case 2: $this->extends[$section] = trim($pieces[1]); // Break intentionally omitted. - + case 1: if (is_array($value)) { $config[$section] = $this->processSection($value); @@ -155,35 +154,35 @@ protected function process(array $data) $config[$section] = $value; } break; - + default: throw new Exception\RuntimeException(sprintf('Section "%s" may not extend multiple sexctions', $section)); } } - + return $config; } - + /** * Process a section. - * - * @param array $section + * + * @param array $section * @return array */ protected function processSection(array $section) { $config = array(); - + foreach ($section as $key => $value) { $this->processKey($key, $value, $config); } - + return $config; } - + /** * Process a key. - * + * * @param string $key * @param string $value * @param array $config @@ -193,7 +192,7 @@ protected function processKey($key, $value, array &$config) { if (strpos($key, $this->nestSeparator) !== false) { $pieces = explode($this->nestSeparator, $key, 2); - + if (!strlen($pieces[0]) || !strlen($pieces[1])) { throw new Exception\RuntimeException(sprintf('Invalid key "%s"', $key)); } elseif (!isset($config[$pieces[0]])) { @@ -205,7 +204,7 @@ protected function processKey($key, $value, array &$config) } elseif (!is_array($config[$pieces[0]])) { throw new Exception\RuntimeException(sprintf('Cannot create sub-key for "%s", as key already exists', $pieces[0])); } - + $this->processKey($pieces[1], $value, $config[$pieces[0]]); } else { if ($key === '@include') { diff --git a/src/Reader/Xml.php b/src/Reader/Xml.php index df5123f..8f1fc71 100644 --- a/src/Reader/Xml.php +++ b/src/Reader/Xml.php @@ -12,27 +12,26 @@ * obtain it through the world-wide-web, please send an email * to license@zend.com so we can send you a copy immediately. * - * @category Zend - * @package Zend_Config + * @category Zend + * @package Zend_Config + * @subpackage Reader * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Reader; -use \XMLReader, - \Zend\Config\Exception; +use XMLReader, + Zend\Config\Exception; /** * XML config reader. * - * @category Zend - * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @category Zend + * @package Zend_Config + * @subpackage Reader + * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License */ class Xml extends AbstractReader { @@ -43,21 +42,21 @@ class Xml extends AbstractReader /** * XML Reader instance. - * + * * @var XMLReader */ protected $reader; /** * Directory of the file to process. - * + * * @var string */ protected $directory; - + /** * Nodes to handle as plain text. - * + * * @var array */ protected $textNodes = array( @@ -67,7 +66,7 @@ class Xml extends AbstractReader /** * processFile(): defined by AbstractReader. - * + * * @see AbstractReader::processFile() * @param string $filename * @return array @@ -76,15 +75,15 @@ protected function processFile($filename) { $this->reader = new XMLReader(); $this->reader->open($filename, null, LIBXML_XINCLUDE); - + $this->directory = dirname($filename); - + return $this->process(); } - + /** * processString(): defined by AbstractReader. - * + * * @see AbstractReader::processString() * @param string $string * @return array @@ -95,25 +94,25 @@ protected function processString($string) $this->reader->xml($string, null, LIBXML_XINCLUDE); $this->directory = __DIR__; - + return $this->process(); } - + /** * Process data from the created XMLReader. - * + * * @return array */ protected function process() { $this->extends = array(); - + return $this->processNextElement(); } - + /** * Process the next inner element. - * + * * @return mixed */ protected function processNextElement() @@ -122,7 +121,7 @@ protected function processNextElement() $text = ''; while ($this->reader->read()) { - if ($this->reader->nodeType === XMLReader::ELEMENT) { + if ($this->reader->nodeType === XMLReader::ELEMENT) { if ($this->reader->depth === 0) { return $this->processNextElement(); } @@ -134,27 +133,27 @@ protected function processNextElement() if ($depth === 1 && isset($attributes['zf']['extends'])) { $this->extends[$name] = $attributes['zf']['extends']; } - + if ($this->reader->namespaceURI === self::XML_NAMESPACE) { switch ($this->reader->localName) { case 'const': if (!isset($attributes['default']['name'])) { throw new Exception\RuntimeException('Misssing "name" attribute in "zf:const" node'); } - + $constantName = $attributes['default']['name']; - + if (!defined($constantName)) { throw new Exception\RuntimeException(sprintf('Constant with name "%s" was not defined', $constantName)); } - + $text .= constant($constantName); break; - + case 'dir': $text .= $this->directory; break; - + default: throw new Exception\RuntimeException(sprintf('Unknown zf:node with name "%s" found', $name)); } @@ -167,20 +166,20 @@ protected function processNextElement() } else { $child = $this->processNextElement(); } - + if ($attributes['default']) { if (!is_array($child)) { $child = array(); } - + $child = array_merge($child, $attributes['default']); } - + if (isset($children[$name])) { if (!is_array($children[$name]) || !$children[$name]) { $children[$name] = array($children[$name]); } - + $children[$name][] = $child; } else { $children[$name] = $child; @@ -199,25 +198,25 @@ protected function processNextElement() /** * Get all attributes on the current node. - * + * * @return array */ protected function getAttributes() { $attributes = array('default' => array(), 'zf' => array()); - - if ($this->reader->hasAttributes) { + + if ($this->reader->hasAttributes) { while ($this->reader->moveToNextAttribute()) { if ($this->reader->namespaceURI === self::XML_NAMESPACE) { $attributes['zf'][$this->reader->localName] = $this->reader->value; } else { - $attributes['default'][$this->reader->localName] = $this->reader->value; + $attributes['default'][$this->reader->localName] = $this->reader->value; } } - + $this->reader->moveToElement(); } - + return $attributes; } } diff --git a/src/SectionedConfig.php b/src/SectionedConfig.php deleted file mode 100644 index 75b4d3e..0000000 --- a/src/SectionedConfig.php +++ /dev/null @@ -1,69 +0,0 @@ -extends; - } - - /** - * Set an extend for Zend\Config\Writer. - * - * @param string $extendingSection - * @param string $extendedSection - * @return void - */ - public function setExtend($extendingSection, $extendedSection = null) - { - if ($extendedSection === null && isset($this->extends[$extendingSection])) { - unset($this->extends[$extendingSection]); - } else if ($extendedSection !== null) { - $this->extends[$extendingSection] = $extendedSection; - } - } -} diff --git a/src/Writer.php b/src/Writer.php new file mode 100644 index 0000000..e8c3e6e --- /dev/null +++ b/src/Writer.php @@ -0,0 +1,48 @@ +_filename = $filename; - - return $this; - } - - /** - * Set wether to exclusively lock the file or not - * - * @param boolean $exclusiveLock - * @return \Zend\Config\Writer\AbstractFileWriter - */ - public function setExclusiveLock($exclusiveLock) - { - $this->_exclusiveLock = $exclusiveLock; - - return $this; - } - - /** - * Write configuration to file. - * - * @param string $filename - * @param \Zend\Config\Config $config - * @param bool $exclusiveLock - * @return void - */ - public function write($filename = null, Config\Config $config = null, $exclusiveLock = null) - { - if ($filename !== null) { - $this->setFilename($filename); - } - - if ($config !== null) { - $this->setConfig($config); - } - - if ($exclusiveLock !== null) { - $this->setExclusiveLock($exclusiveLock); - } - - if ($this->_filename === null) { - throw new Config\Exception\InvalidArgumentException('No filename was set'); - } - - if ($this->_config === null) { - throw new Config\Exception\InvalidArgumentException('No config was set'); - } - - $configString = $this->render(); - - $flags = 0; - - if ($this->_exclusiveLock) { - $flags |= LOCK_EX; - } - - $result = @file_put_contents($this->_filename, $configString, $flags); - - if ($result === false) { - throw new Config\Exception\RuntimeException('Could not write to file "' . $this->_filename . '"'); - } - } - - /** - * Render a Zend_Config into a config file string. - * - * @since 1.10 - * @todo For 2.0 this should be redone into an abstract method. - * @return string - */ - public function render() - { - return ""; - } -} diff --git a/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php index 3613413..7022178 100644 --- a/src/Writer/AbstractWriter.php +++ b/src/Writer/AbstractWriter.php @@ -18,88 +18,66 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ namespace Zend\Config\Writer; +use Zend\Config\Writer, + Zend\Config\Exception, + Zend\Stdlib\IteratorToArray; + /** * @category Zend * @package Zend_Config * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -abstract class AbstractWriter +abstract class AbstractWriter implements Writer { /** - * Option keys to skip when calling setOptions() - * - * @var array - */ - protected $_skipOptions = array( - 'options' - ); - - /** - * Config object to write - * - * @var \Zend\Config\Config - */ - protected $_config = null; - - /** - * Create a new adapter - * - * $options can only be passed as array or be omitted + * writeFile(): defined by Writer interface. * - * @param null|array $options + * @see Writer::writeFile() + * @param string $filename + * @param mixed $config + * @param boolean $exclusiveLock + * @return void */ - public function __construct(array $options = null) + public function writeFile($filename, $config, $exclusiveLock = true) { - if (is_array($options)) { - $this->setOptions($options); + if (!is_writable($filename)) { + throw new Exception\RuntimeException(sprintf('File "%s" is not writable', $filename)); } - } - /** - * Set options via a Zend_Config instance - * - * @param \Zend\Config\Config $config - * @return \Zend\Config\Writer\Writer - */ - public function setConfig(\Zend\Config\Config $config) - { - $this->_config = $config; + $flags = 0; - return $this; + if ($exclusiveLock) { + $flags |= LOCK_EX; + } + + file_put_contents($filename, $this->writeString($config), $exclusiveLock); } /** - * Set options via an array + * writeString(): defined by Writer interface. * - * @param array $options - * @return \Zend\Config\Writer\Writer + * @see Writer::writeFile() + * @param mixed $config + * @return void */ - public function setOptions(array $options) + public function writeString($config) { - foreach ($options as $key => $value) { - if (in_array(strtolower($key), $this->_skipOptions)) { - continue; - } - - $method = 'set' . ucfirst($key); - if (method_exists($this, $method)) { - $this->$method($value); - } + if ($config instanceof Traversable) { + $config = IteratorToArray::convert($config); + } elseif (!is_array($config)) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable config'); } - return $this; + return $this->processConfig($config); } /** - * Write a Zend_Config object to it's target + * Process an array configuration. * - * @return void + * @return string */ - abstract public function write(); + abstract protected function processConfig(array $config); } diff --git a/src/Writer/ArrayWriter.php b/src/Writer/ArrayWriter.php deleted file mode 100644 index eada599..0000000 --- a/src/Writer/ArrayWriter.php +++ /dev/null @@ -1,55 +0,0 @@ -_config->toArray(); - $sectionName = $this->_config->getSectionName(); - - if (is_string($sectionName)) { - $data = array($sectionName => $data); - } - - $arrayString = "_nestSeparator = $separator; - + $this->nestSeparator = $separator; return $this; } + /** + * Get nest separator. + * + * @return string + */ + public function getNestSeparator() + { + return $this->nestSeparator; + } + /** * Set if rendering should occour without sections or not. * @@ -68,47 +74,48 @@ public function setNestSeparator($separator) * into the global namespace of the INI file. * * @param bool $withoutSections - * @return \Zend\Config\Writer\Ini + * @return Ini */ - public function setRenderWithoutSections($withoutSections=true) + public function setRenderWithoutSectionsFlags($withoutSections) { - $this->_renderWithoutSections = (bool)$withoutSections; + $this->renderWithoutSections = (bool) $withoutSections; return $this; } /** - * Render a Zend\Config into a INI config string. + * Return whether the writer should render without sections. * - * @since 1.10 + * @return boolean + */ + public function shouldRenderWithoutSections() + { + return $this->renderWithoutSections; + } + + /** + * processConfig(): defined by AbstractWriter. + * + * @param array $config * @return string */ - public function render() + public function processConfig(array $config) { - $iniString = ''; - $extends = $this->_config->getExtends(); - $sectionName = $this->_config->getSectionName(); - - if($this->_renderWithoutSections == true) { - $iniString .= $this->_addBranch($this->_config); - } else if (is_string($sectionName)) { - $iniString .= '[' . $sectionName . ']' . "\n" - . $this->_addBranch($this->_config) - . "\n"; + $iniString = ''; + + if ($this->shouldRenderWithoutSections()) { + $iniString .= $this->addBranch($config); } else { - $config = $this->_sortRootElements($this->_config); + $config = $this->sortRootElements($config); + foreach ($config as $sectionName => $data) { - if (!($data instanceof Config\Config)) { + if (!is_array($data)) { $iniString .= $sectionName . ' = ' - . $this->_prepareValue($data) + . $this->prepareValue($data) . "\n"; } else { - if (isset($extends[$sectionName])) { - $sectionName .= ' : ' . $extends[$sectionName]; - } - $iniString .= '[' . $sectionName . ']' . "\n" - . $this->_addBranch($data) + . $this->addBranch($data) . "\n"; } } @@ -118,24 +125,24 @@ public function render() } /** - * Add a branch to an INI string recursively + * Add a branch to an INI string recursively. * - * @param \Zend\Config\Config $config - * @return void + * @param array $config + * @return string */ - protected function _addBranch(Config\Config $config, $parents = array()) + protected function addBranch(array $config, $parents = array()) { $iniString = ''; foreach ($config as $key => $value) { $group = array_merge($parents, array($key)); - if ($value instanceof Config\Config) { - $iniString .= $this->_addBranch($value, $group); + if (is_array($value)) { + $iniString .= $this->addBranch($value, $group); } else { - $iniString .= implode($this->_nestSeparator, $group) + $iniString .= implode($this->nestSeparator, $group) . ' = ' - . $this->_prepareValue($value) + . $this->prepareValue($value) . "\n"; } } @@ -144,50 +151,48 @@ protected function _addBranch(Config\Config $config, $parents = array()) } /** - * Prepare a value for INI + * Prepare a value for INI. * * @param mixed $value * @return string */ - protected function _prepareValue($value) + protected function prepareValue($value) { if (is_integer($value) || is_float($value)) { return $value; } elseif (is_bool($value)) { return ($value ? 'true' : 'false'); - } elseif (strpos($value, '"') === false) { + } elseif (false === strpos($value, '"')) { return '"' . $value . '"'; } else { - throw new Config\Exception\RuntimeException('Value can not contain double quotes "'); + throw new Exception\RuntimeException('Value can not contain double quotes'); } } - + /** - * Root elements that are not assigned to any section needs to be - * on the top of config. - * - * @see http://framework.zend.com/issues/browse/ZF-6289 - * @param Zend\Config - * @return Zend\Config + * Root elements that are not assigned to any section needs to be on the + * top of config. + * + * @param array $config + * @return array */ - protected function _sortRootElements(\Zend\Config\Config $config) + protected function sortRootElements(array $config) { - $configArray = $config->toArray(); $sections = array(); - - // remove sections from config array - foreach ($configArray as $key => $value) { + + // Remove sections from config array. + foreach ($config as $key => $value) { if (is_array($value)) { $sections[$key] = $value; - unset($configArray[$key]); + unset($config[$key]); } } - - // readd sections to the end + + // Read sections to the end. foreach ($sections as $key => $value) { - $configArray[$key] = $value; + $config[$key] = $value; } - - return new \Zend\Config\Config($configArray); + + return $config; } -} +} \ No newline at end of file diff --git a/src/Writer/Json.php b/src/Writer/Json.php deleted file mode 100644 index 4cdd4dc..0000000 --- a/src/Writer/Json.php +++ /dev/null @@ -1,100 +0,0 @@ -_prettyPrint; - } - - /** - * Set prettyPrint flag - * - * @param bool $prettyPrint PrettyPrint flag - * @return Zend_Config_Writer_Json - */ - public function setPrettyPrint($flag) - { - $this->_prettyPrint = (bool) $flag; - return $this; - } - - /** - * Render a Zend_Config into a JSON config string. - * - * @since 1.10 - * @return string - */ - public function render() - { - $data = $this->_config->toArray(); - $sectionName = $this->_config->getSectionName(); - $extends = $this->_config->getExtends(); - - if (is_string($sectionName)) { - $data = array($sectionName => $data); - } - - foreach ($extends as $section => $parentSection) { - $data[$section][JsonConfig::EXTENDS_NAME] = $parentSection; - } - - // Ensure that each "extends" section actually exists - foreach ($data as $section => $sectionData) { - if (is_array($sectionData) && isset($sectionData[JsonConfig::EXTENDS_NAME])) { - $sectionExtends = $sectionData[JsonConfig::EXTENDS_NAME]; - if (!isset($data[$sectionExtends])) { - // Remove "extends" declaration if section does not exist - unset($data[$section][JsonConfig::EXTENDS_NAME]); - } - } - } - - $out = JsonUtil::encode($data); - if ($this->prettyPrint()) { - $out = JsonUtil::prettyPrint($out); - } - return $out; - } -} diff --git a/src/Reader/Reader.php b/src/Writer/PhpArray.php similarity index 68% rename from src/Reader/Reader.php rename to src/Writer/PhpArray.php index 60671dd..feef9a1 100644 --- a/src/Reader/Reader.php +++ b/src/Writer/PhpArray.php @@ -18,12 +18,7 @@ * @license http://framework.zend.com/license/new-bsd New BSD License */ -/** - * @namespace - */ -namespace Zend\Config\Reader; - -use \Zend\Config\Config; +namespace Zend\Config\Writer; /** * @category Zend @@ -31,21 +26,20 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -interface Reader +class PhpArray extends AbstractWriter { /** - * Read a file and create a config object. - * - * @param string $filename - * @return Config + * processConfig(): defined by AbstractWriter. + * + * @param array $config + * @return string */ - public function readFile($filename); - - /** - * Read a string and create a config object. - * - * @param string $string - * @return Config - */ - public function readString($string); + public function processConfig(array $config) + { + + $arrayString = "'); - $extends = $this->_config->getExtends(); - $sectionName = $this->_config->getSectionName(); + $writer = new XMLWriter('UTF-8'); + $writer->openMemory(); + $writer->setIndent(true); + $writer->setIndentString(str_repeat(' ', 4)); - if (is_string($sectionName)) { - $child = $xml->addChild($sectionName); + $writer->startDocument('1.0', 'UTF-8'); + $writer->startElement('zend-config'); - $this->_addBranch($this->_config, $child, $xml); - } else { - foreach ($this->_config as $sectionName => $data) { - if (!($data instanceof Config\Config)) { - $xml->addChild($sectionName, (string) $data); - } else { - $child = $xml->addChild($sectionName); - - if (isset($extends[$sectionName])) { - $child->addAttribute('zf:extends', $extends[$sectionName], Config\Xml::XML_NAMESPACE); - } - - $this->_addBranch($data, $child, $xml); - } + foreach ($config as $sectionName => $data) { + if (!is_array($data)) { + $writer->writeElement($sectionName, (string) $data); + } else { + $this->addBranch($sectionName, $data, $writer); } } - $dom = dom_import_simplexml($xml)->ownerDocument; - $dom->formatOutput = true; - - $xmlString = $dom->saveXML(); + $writer->endElement(); + $writer->endDocument(); - return $xmlString; + return $writer->outputMemory(); } /** - * Add a branch to an XML object recursively + * Add a branch to an XML object recursively. * - * @param \Zend\Config\Config $config - * @param SimpleXMLElement $xml - * @param SimpleXMLElement $parent + * @param string $branchName + * @param array $config + * @param XMLWriter $writer * @return void */ - protected function _addBranch(Config\Config $config, \SimpleXMLElement $xml, \SimpleXMLElement $parent) + protected function addBranch($branchName, array $config, XMLWriter $writer) { $branchType = null; @@ -91,34 +78,31 @@ protected function _addBranch(Config\Config $config, \SimpleXMLElement $xml, \Si if ($branchType === null) { if (is_numeric($key)) { $branchType = 'numeric'; - $branchName = $xml->getName(); - $xml = $parent; - - unset($parent->{$branchName}); } else { + $writer->addElement($branchName); $branchType = 'string'; } } else if ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) { - throw new Config\Exception\RuntimeException('Mixing of string and numeric keys is not allowed'); + throw new Exception\RuntimeException('Mixing of string and numeric keys is not allowed'); } if ($branchType === 'numeric') { - if ($value instanceof Config\Config) { - $child = $parent->addChild($branchName); - - $this->_addBranch($value, $child, $parent); + if (is_array($value)) { + $this->addBranch($value, $data, $writer); } else { - $parent->addChild($branchName, (string) $value); + $writer->writeElement($branchName, (string) $value); } } else { - if ($value instanceof Config\Config) { - $child = $xml->addChild($key); - - $this->_addBranch($value, $child, $xml); + if (is_array($value)) { + $this->addBranch($key, $data, $writer); } else { - $xml->addChild($key, (string) $value); + $writer->writeElement($key, (string) $value); } } } + + if ($branchType === 'string') { + $writer->endElement(); + } } } diff --git a/src/Writer/Yaml.php b/src/Writer/Yaml.php deleted file mode 100644 index 1e2e9ff..0000000 --- a/src/Writer/Yaml.php +++ /dev/null @@ -1,138 +0,0 @@ -_yamlEncoder; - } - - /** - * Set callback for decoding YAML - * - * @param callable $yamlEncoder the decoder to set - * @return Zend_Config_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; - } - - /** - * Render a Zend_Config into a YAML config string. - * - * @since 1.10 - * @return string - */ - public function render() - { - $data = $this->_config->toArray(); - $sectionName = $this->_config->getSectionName(); - $extends = $this->_config->getExtends(); - - if (is_string($sectionName)) { - $data = array($sectionName => $data); - } - - foreach ($extends as $section => $parentSection) { - $data[$section][YamlConfig::EXTENDS_NAME] = $parentSection; - } - - // Ensure that each "extends" section actually exists - foreach ($data as $section => $sectionData) { - if (is_array($sectionData) && isset($sectionData[YamlConfig::EXTENDS_NAME])) { - $sectionExtends = $sectionData[YamlConfig::EXTENDS_NAME]; - if (!isset($data[$sectionExtends])) { - // Remove "extends" declaration if section does not exist - unset($data[$section][YamlConfig::EXTENDS_NAME]); - } - } - } - - return call_user_func($this->getYamlEncoder(), $data); - } - - /** - * Very dumb YAML encoder - * - * Until we have Zend_Yaml... - * - * @param array $data YAML data - * @return string - */ - public static function encode($data) - { - return self::_encodeYaml(0, $data); - } - - /** - * Service function for encoding YAML - * - * @param int $indent Current indent level - * @param array $data Data to encode - * @return string - */ - protected static function _encodeYaml($indent, $data) - { - reset($data); - $result = ""; - $numeric = is_numeric(key($data)); - - foreach($data as $key => $value) { - if(is_array($value)) { - $encoded = "\n".self::_encodeYaml($indent+1, $value); - } else { - $encoded = (string)$value."\n"; - } - $result .= str_repeat(" ", $indent).($numeric?"- ":"$key: ").$encoded; - } - return $result; - } -} From 3e3b732afdd967b543ba8df740fba972e9f977f2 Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Sun, 18 Dec 2011 18:07:55 +0100 Subject: [PATCH 07/18] Added basic config factory --- src/Factory.php | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/Factory.php diff --git a/src/Factory.php b/src/Factory.php new file mode 100644 index 0000000..3b2e4e9 --- /dev/null +++ b/src/Factory.php @@ -0,0 +1,89 @@ +readers['ini'])) { + $this->readers['ini'] = new Reader\Ini(); + } + + return $this->readers['ini']->readFile($filename); + break; + + case 'xml': + if (!isset($this->readers['xml'])) { + $this->readers['xml'] = new Reader\Ini(); + } + + return $this->readers['xml']->readFile($filename); + break; + } + + return null; + } + + /** + * Read configuration from multiple files and merge them. + * + * @param array $files + * @return array + */ + public function fromFiles(array $files) + { + $config = array(); + + foreach ($files as $file) { + $config = array_replace_recursive($config, self::fromFile($file)); + } + + return $config; + } +} From d8a2fa6b54cc6bc255e99a3cacc225541d25bce9 Mon Sep 17 00:00:00 2001 From: Jurian Sluiman Date: Sun, 18 Dec 2011 18:34:22 +0100 Subject: [PATCH 08/18] Change interface methods for Zend\Config\Reader s/readFile/fromFile/g and s/readString/fromtString/g --- src/Factory.php | 6 +++--- src/Reader.php | 8 ++++---- src/Reader/AbstractReader.php | 12 ++++++------ src/Reader/Ini.php | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index 3b2e4e9..8dde955 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -55,15 +55,15 @@ public function fromFile($filename) $this->readers['ini'] = new Reader\Ini(); } - return $this->readers['ini']->readFile($filename); + return $this->readers['ini']->fromFile($filename); break; case 'xml': if (!isset($this->readers['xml'])) { - $this->readers['xml'] = new Reader\Ini(); + $this->readers['xml'] = new Reader\Xml(); } - return $this->readers['xml']->readFile($filename); + return $this->readers['xml']->fromFile($filename); break; } diff --git a/src/Reader.php b/src/Reader.php index a52db4c..665ebe7 100644 --- a/src/Reader.php +++ b/src/Reader.php @@ -29,18 +29,18 @@ interface Reader { /** - * Read a file and create a config object. + * Read from a file and create a config object. * * @param string $filename * @return array */ - public function readFile($filename); + public function fromFile($filename); /** - * Read a string and create a config object. + * Read from a string and create a config object. * * @param string $string * @return array */ - public function readString($string); + public function fromString($string); } diff --git a/src/Reader/AbstractReader.php b/src/Reader/AbstractReader.php index 47c1e47..ba37c56 100644 --- a/src/Reader/AbstractReader.php +++ b/src/Reader/AbstractReader.php @@ -55,13 +55,13 @@ abstract class AbstractReader implements Reader protected $processedExtends; /** - * readFile(): defined by Reader interface. + * fromFile(): defined by Reader interface. * - * @see Reader::readFile() + * @see Reader::fromFile() * @param string $filename * @return array */ - public function readFile($filename) + public function fromFile($filename) { $this->extends = array(); @@ -69,13 +69,13 @@ public function readFile($filename) } /** - * readString(): defined by Reader interface. + * fromString(): defined by Reader interface. * - * @see Reader::readString() + * @see Reader::fromString() * @param string $string * @return array */ - public function readString($string) + public function fromString($string) { $this->extends = array(); diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php index 6b110c0..21daef9 100644 --- a/src/Reader/Ini.php +++ b/src/Reader/Ini.php @@ -209,7 +209,7 @@ protected function processKey($key, $value, array &$config) } else { if ($key === '@include') { $reader = clone $this; - $include = $reader->readFile($this->directory . '/' . $value)->toArray(); + $include = $reader->fromFile($this->directory . '/' . $value)->toArray(); $config = array_replace_recursive($config, $include); } else { $config[$key] = str_replace('{DIR}', $this->directory, $value); From f1dd5fc0f9b36a7d07b9b837c67cb8ea2a0c7a07 Mon Sep 17 00:00:00 2001 From: Jurian Sluiman Date: Sun, 18 Dec 2011 18:40:00 +0100 Subject: [PATCH 09/18] Change interface methods for Zend\Config\Writer s/writeFile/toFile/g and s/writeString/toString/g --- src/Writer.php | 4 ++-- src/Writer/AbstractWriter.php | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Writer.php b/src/Writer.php index e8c3e6e..7fe55f3 100644 --- a/src/Writer.php +++ b/src/Writer.php @@ -36,7 +36,7 @@ interface Writer * @param boolean $exclusiveLock * @return void */ - public function writeFile($filename, $config, $exclusiveLock = true); + public function toFile($filename, $config, $exclusiveLock = true); /** * Write a config object to a string. @@ -44,5 +44,5 @@ public function writeFile($filename, $config, $exclusiveLock = true); * @param mixed $config * @return string */ - public function writeString($config); + public function toString($config); } diff --git a/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php index 7022178..eacecfe 100644 --- a/src/Writer/AbstractWriter.php +++ b/src/Writer/AbstractWriter.php @@ -33,15 +33,15 @@ abstract class AbstractWriter implements Writer { /** - * writeFile(): defined by Writer interface. + * toFile(): defined by Writer interface. * - * @see Writer::writeFile() + * @see Writer::toFile() * @param string $filename * @param mixed $config * @param boolean $exclusiveLock * @return void */ - public function writeFile($filename, $config, $exclusiveLock = true) + public function toFile($filename, $config, $exclusiveLock = true) { if (!is_writable($filename)) { throw new Exception\RuntimeException(sprintf('File "%s" is not writable', $filename)); @@ -53,17 +53,17 @@ public function writeFile($filename, $config, $exclusiveLock = true) $flags |= LOCK_EX; } - file_put_contents($filename, $this->writeString($config), $exclusiveLock); + file_put_contents($filename, $this->toString($config), $exclusiveLock); } /** - * writeString(): defined by Writer interface. + * toString(): defined by Writer interface. * - * @see Writer::writeFile() + * @see Writer::toString() * @param mixed $config * @return void */ - public function writeString($config) + public function toString($config) { if ($config instanceof Traversable) { $config = IteratorToArray::convert($config); From 6ff9b87533845680da3f4a4d1809d92d6e662f89 Mon Sep 17 00:00:00 2001 From: Thinkscape Date: Sat, 10 Dec 2011 15:22:23 +0100 Subject: [PATCH 10/18] Add Config Parser interface, Token parser and tests --- src/Config.php | 99 ++++++++++++++++++- src/Parser.php | 44 +++++++++ src/Parser/Queue.php | 57 +++++++++++ src/Parser/Token.php | 229 +++++++++++++++++++++++++++++++++++++++++++ test/ParserTest.php | 209 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 633 insertions(+), 5 deletions(-) create mode 100644 src/Parser.php create mode 100644 src/Parser/Queue.php create mode 100644 src/Parser/Token.php create mode 100644 test/ParserTest.php diff --git a/src/Config.php b/src/Config.php index 91dd273..85fd57a 100644 --- a/src/Config.php +++ b/src/Config.php @@ -25,7 +25,10 @@ use \Countable, \Iterator, - \ArrayAccess; + \ArrayAccess, + Zend\Config\Exception\InvalidArgumentException, + Zend\Config\Parser, + Zend\Config\Parser\Queue as ParserQueue; /** * @category Zend @@ -56,6 +59,13 @@ class Config implements Countable, Iterator, ArrayAccess */ protected $data = array(); + /** + * Data withing the configuration. + * + * @var \Zend\Config\Parser\Queue + */ + protected $parsers; + /** * Used when unsetting values during iteration to ensure we do not skip * the next element. @@ -81,21 +91,36 @@ class Config implements Countable, Iterator, ArrayAccess * * @param array $array * @param boolean $allowModifications - * @return void + * @param \Zend\Config\Parser\Queue|\Zend\Config\Parser|Traversable|array $parsers + * @return \Zend\Config\Config */ - public function __construct(array $array, $allowModifications = false) + public function __construct(array $array, $allowModifications = false, $parsers = null) { $this->allowModifications = (boolean) $allowModifications; + if ($parsers !== null) { + $parsers = $this->setParsers($parsers); + } else { + // create empty queue + $parsers = $this->getParsers(); + } + foreach ($array as $key => $value) { if (is_array($value)) { - $this->data[$key] = new self($value, $this->allowModifications); + $this->data[$key] = new self($value, $this->allowModifications, $parsers); } else { $this->data[$key] = $value; } - + $this->count++; } + + /** + * Process config + */ + if(!$parsers->isEmpty()){ + $this->parse(); + } } /** @@ -400,4 +425,68 @@ public function isReadOnly() { return !$this->allowModifications; } + + /** + * Get parsers queue for this config. + * + * @return \Zend\Config\Parser\Queue + */ + public function getParsers(){ + if ($this->parsers === null) { + $this->parsers = new ParserQueue(); + } + return $this->parsers; + } + + /** + * Set config parsers + * + * @param \Zend\Config\Parser\Queue|\Zend\Config\Parser|Traversable|array $parsers + * @return \Zend\Config\Parser\Queue + * @throws Exception\InvalidArgumentException + */ + public function setParsers($parsers) + { + // A complete, ready to use queue object + if ($parsers instanceof ParserQueue) { + return $this->parsers = $parsers; + } + + // A single parser + elseif ($parsers instanceof Parser) { + $this->parsers = new ParserQueue(); + $this->parsers->insert($parsers); + return $this->parsers; + } + + // An array of parsers + elseif ( + !is_array($parsers) && + !($parsers instanceof \Traversable) && + !($parsers instanceof ParserQueue) + ) { + throw new InvalidArgumentException('Cannot use ' . gettype($parsers) . ' as a parsers.'); + } + + $this->parsers = new ParserQueue(); + foreach ($parsers as $parser) { + if ($parser instanceof Parser) { + $this->parsers->insert($parser); + } else { + throw new InvalidArgumentException('Cannot use ' . gettype($parser) . ' as a parser'); + } + } + + return $this->parsers; + } + + /** + * Process the whole config structure with each parser in the queue. + * + * @return void + */ + public function parse() + { + $this->getParsers()->parse($this); + } } diff --git a/src/Parser.php b/src/Parser.php new file mode 100644 index 0000000..a93b24a --- /dev/null +++ b/src/Parser.php @@ -0,0 +1,44 @@ +isReadOnly()) { + throw new InvalidArgumentException('Cannot parse config because it is read-only'); + } + + foreach ($this as $parser) { + /** @var $parser \Zend\Config\Parser */ + $parser->parse($config); + } + } +} diff --git a/src/Parser/Token.php b/src/Parser/Token.php new file mode 100644 index 0000000..5cc58ec --- /dev/null +++ b/src/Parser/Token.php @@ -0,0 +1,229 @@ + value + * to replace it with + * @param string $prefix + * @param string $suffix + * @internal param array $options + * @return \Zend\Config\Parser\Token + */ + public function __construct($tokens = array(), $prefix = '', $suffix = '') + { + $this->setTokens($tokens); + $this->setPrefix($prefix); + $this->setSuffix($suffix); + } + + /** + * @return string + */ + public function getPrefix() + { + return $this->prefix; + } + + /** + * @return string + */ + public function getSuffix() + { + return $this->suffix; + } + + /** + * @param string $prefix + * @return mixed + */ + public function setPrefix($prefix) + { + // reset map + $this->map = null; + + return $this->prefix = $prefix; + } + + /** + * @param string $suffix + * @return string + */ + public function setSuffix($suffix) + { + // reset map + $this->map = null; + + return $this->suffix = $suffix; + } + + /** + * Set token registry. + * + * @param array|\Zend\Config\Config|\ArrayObject|\Traversable $tokens Associative array of TOKEN => value + * to replace it with + * @throws \Zend\Config\Exception\InvalidArgumentException + */ + public function setTokens($tokens) + { + if (is_array($tokens)) { + $this->tokens = $tokens; + } elseif ($tokens instanceof Config) { + $this->tokens = $tokens->toArray(); + } elseif ($tokens instanceof \Traversable) { + $this->tokens = array(); + foreach ($tokens as $key => $val) { + $this->tokens[$key] = $val; + } + } else { + throw new InvalidArgumentException('Cannot use ' . gettype($tokens) . ' as token registry.'); + } + + // reset map + $this->map = null; + } + + /** + * Get current token registry. + * @return array + */ + public function getTokens() + { + return $this->tokens; + } + + /** + * Add new token. + * + * @param $token + * @param $value + * @throws \Zend\Config\Exception\InvalidArgumentException + */ + public function addToken($token, $value) + { + if (!is_scalar($token)) { + throw new InvalidArgumentException('Cannot use ' . gettype($token) . ' as token name.'); + } + $this->tokens[$token] = $value; + + // reset map + $this->map = null; + } + + /** + * Add new token. + * + * @param $token + * @param $value + * @throws \Zend\Config\Exception\InvalidArgumentException + */ + public function setToken($token, $value) + { + return $this->addToken($token, $value); + } + + public function parse(Config $config) + { + if ($config->isReadOnly()) { + throw new InvalidArgumentException('Cannot parse config because it is read-only'); + } + + if ($this->map === null) { + /** + * Build replacement map + */ + if (!$this->suffix && !$this->prefix) { + $this->map = $this->tokens; + } else { + $this->map = array(); + foreach ($this->tokens as $token => $value) { + $this->map[$this->prefix . $token . $this->suffix] = $value; + } + } + } + + /** + * Walk through config and replace values + */ + $keys = array_keys($this->map); + $values = array_values($this->map); + foreach ($config as $key => $val) { + if ($val instanceof Config) { + $this->parse($val); + } else { + $config->$key = str_replace($keys,$values,$val); + } + } + + return $config; + } + +} diff --git a/test/ParserTest.php b/test/ParserTest.php new file mode 100644 index 0000000..b65ec95 --- /dev/null +++ b/test/ParserTest.php @@ -0,0 +1,209 @@ +_nested = array( + 'a' => 1, + 'b' => 2, + 'c' => array( + 'ca' => 3, + 'cb' => 4, + 'cc' => 5, + 'cd' => array( + 'cda' => 6, + 'cdb' => 7 + ), + ), + 'd' => array( + 'da' => 8, + 'db' => 9 + ), + 'e' => 10 + ); + + $this->_tokenBare = array( + 'simple' => 'BARETOKEN', + 'inside' => 'some text with BARETOKEN inside', + 'nested' => array( + 'simple' => 'BARETOKEN', + 'inside' => 'some text with BARETOKEN inside', + ), + ); + + $this->_tokenPrefix = array( + 'simple' => '::TOKEN', + 'inside' => ':: some text with ::TOKEN inside ::', + 'nested' => array( + 'simple' => '::TOKEN', + 'inside' => ':: some text with ::TOKEN inside ::', + ), + ); + + $this->_tokenSuffix = array( + 'simple' => 'TOKEN::', + 'inside' => ':: some text with TOKEN:: inside ::', + 'nested' => array( + 'simple' => 'TOKEN::', + 'inside' => ':: some text with TOKEN:: inside ::', + ), + ); + + $this->_tokenSurround = array( + 'simple' => '##TOKEN##', + 'inside' => '## some text with ##TOKEN## inside ##', + 'nested' => array( + 'simple' => '##TOKEN##', + 'inside' => '## some text with ##TOKEN## inside ##', + ), + ); + + $this->_tokenSurroundMixed = array( + 'simple' => '##TOKEN##', + 'inside' => '## some text with ##TOKEN## inside ##', + 'simple2' => '@@TOKEN@@', + 'inside' => '## some text with ##TOKEN## inside ##', + ); + } + + public function testEmptyParsersCollection() + { + $config = new Config($this->_nested); + $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); + $this->assertEquals($this->_nested,$config->toArray()); + } + + public function testParsersQueue() + { + $parser1 = new TokenParser(); + $parser2 = new TokenParser(); + $config = new Config(array(),true,array($parser1,$parser2)); + + $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); + $this->assertEquals(2,$config->getParsers()->count()); + $this->assertTrue($config->getParsers()->contains($parser1)); + $this->assertTrue($config->getParsers()->contains($parser2)); + } + + public function testParsersCollectionPersistence() + { + $config = new Config($this->_nested); + $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); + $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->c->getParsers()); + $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->c->cd->getParsers()); + $this->assertSame($config->getParsers(), $config->c->getParsers()); + $this->assertSame($config->c->getParsers(), $config->c->cd->getParsers()); + } + + public function testBareTokenPost() + { + $config = new Config($this->_tokenBare, true); + $parser = new TokenParser(); + $parser->addToken('BARETOKEN', 'some replaced value'); + $parser->parse($config); + + $this->assertEquals('some replaced value', $config->simple); + $this->assertEquals('some text with some replaced value inside', $config->inside); + $this->assertEquals('some replaced value', $config->nested->simple); + $this->assertEquals('some text with some replaced value inside', $config->nested->inside); + } + + public function testBareTokenJIT() + { + $parser = new TokenParser(array('BARETOKEN' => 'some replaced value')); + $config = new Config($this->_tokenBare, true, array($parser)); + + $this->assertEquals('some replaced value', $config->simple); + $this->assertEquals('some text with some replaced value inside', $config->inside); + $this->assertEquals('some replaced value', $config->nested->simple); + $this->assertEquals('some text with some replaced value inside', $config->nested->inside); + } + + public function testTokenPrefix() + { + $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'::'); + $config = new Config($this->_tokenPrefix, true, array($parser)); + + $this->assertEquals('some replaced value', $config->simple); + $this->assertEquals(':: some text with some replaced value inside ::', $config->inside); + $this->assertEquals('some replaced value', $config->nested->simple); + $this->assertEquals(':: some text with some replaced value inside ::', $config->nested->inside); + } + + public function testTokenSuffix() + { + $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'','::'); + $config = new Config($this->_tokenSuffix, true, array($parser)); + + $this->assertEquals('some replaced value', $config->simple); + $this->assertEquals(':: some text with some replaced value inside ::', $config->inside); + $this->assertEquals('some replaced value', $config->nested->simple); + $this->assertEquals(':: some text with some replaced value inside ::', $config->nested->inside); + } + + /** + * @depends testTokenSuffix + * @depends testTokenPrefix + */ + public function testTokenSurround() + { + $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'##','##'); + $config = new Config($this->_tokenSurround, true, array($parser)); + + $this->assertEquals('some replaced value', $config->simple); + $this->assertEquals('## some text with some replaced value inside ##', $config->inside); + $this->assertEquals('some replaced value', $config->nested->simple); + $this->assertEquals('## some text with some replaced value inside ##', $config->nested->inside); + } + + /** + * @depends testTokenSurround + */ + public function testTokenChangeParams(){ + $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'##','##'); + $config = new Config($this->_tokenSurround, true, array($parser)); + $config->nested['nested']['']; + $this->assertEquals('some replaced value', $config->simple); + $this->assertEquals('## some text with some replaced value inside ##', $config->inside); + $this->assertEquals('some replaced value', $config->nested->simple); + $this->assertEquals('## some text with some replaced value inside ##', $config->nested->inside); + } +} + From cb098ad6530dafd3f693ce22d4a5d8b482bce0ae Mon Sep 17 00:00:00 2001 From: Thinkscape Date: Wed, 14 Dec 2011 22:41:27 +0100 Subject: [PATCH 11/18] Add Translator and Filter parser, add more tests --- src/Config.php | 14 +++- src/Parser.php | 9 +- src/Parser/Filter.php | 104 +++++++++++++++++++++++ src/Parser/Queue.php | 18 ++++ src/Parser/Token.php | 44 +++++++--- src/Parser/Translator.php | 129 ++++++++++++++++++++++++++++ test/ParserTest.php | 171 ++++++++++++++++++++++++++++++++++---- 7 files changed, 456 insertions(+), 33 deletions(-) create mode 100644 src/Parser/Filter.php create mode 100644 src/Parser/Translator.php diff --git a/src/Config.php b/src/Config.php index 85fd57a..249e3ec 100644 --- a/src/Config.php +++ b/src/Config.php @@ -164,9 +164,13 @@ public function __set($name, $value) { if ($this->allowModifications) { if (is_array($value)) { - $this->data[$name] = new self($value, true); + $this->data[$name] = new self($value, true, $this->parsers); } else { - $this->data[$name] = $value; + if (!$this->parsers->isEmpty()) { + $this->data[$name] = $this->parsers->parseValue($value); + } else { + $this->data[$name] = $value; + } } $this->count++; @@ -381,13 +385,15 @@ public function merge(self $merge) foreach ($merge as $key => $item) { if (array_key_exists($key, $this->data)) { if ($item instanceof self && $this->data[$key] instanceof self) { - $this->data[$key] = $this->data[$key]->merge(new self($item->toArray(), $this->allowModifications)); + $this->data[$key] = $this->data[$key]->merge( + new self($item->toArray(), $this->allowModifications, $this->parsers) + ); } else { $this->data[$key] = $item; } } else { if ($item instanceof self) { - $this->data[$key] = new self($item->toArray(), $this->allowModifications); + $this->data[$key] = new self($item->toArray(), $this->allowModifications, $this->parsers); } else { $this->data[$key] = $item; } diff --git a/src/Parser.php b/src/Parser.php index a93b24a..53e6c55 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -34,11 +34,16 @@ interface Parser /** * Process the whole Config structure and recursively parse all its values. * - * @protected - * @abstract * @param Config $value * @return \Zend\Config\Config */ public function parse(Config $value); + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function parseValue($value); } diff --git a/src/Parser/Filter.php b/src/Parser/Filter.php new file mode 100644 index 0000000..287f16a --- /dev/null +++ b/src/Parser/Filter.php @@ -0,0 +1,104 @@ +setFilter($filter); + } + + /** + * @return \Zend\Filter\Filter + */ + public function getFilter() + { + return $this->translator; + } + + /** + * @param \Zend\Filter\Filter $filter + */ + public function setFilter(ZendFilter $filter) + { + $this->filter = $filter; + } + + public function parse(Config $config) + { + if ($config->isReadOnly()) { + throw new InvalidArgumentException('Cannot parse config because it is read-only'); + } + + /** + * Walk through config and replace values + */ + foreach ($config as $key => $val) { + if ($val instanceof Config) { + $this->parse($val); + } else { + $config->$key = $this->filter->filter($val); + } + } + + return $config; + } + + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function parseValue($value) + { + return $this->filter->filter($value); + } + +} diff --git a/src/Parser/Queue.php b/src/Parser/Queue.php index 8eb7033..c01487f 100644 --- a/src/Parser/Queue.php +++ b/src/Parser/Queue.php @@ -54,4 +54,22 @@ public function parse(Config $config) $parser->parse($config); } } + + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function parseValue($value) + { + foreach ($this as $parser) { + /** @var $parser \Zend\Config\Parser */ + $value = $parser->parseValue($value); + } + + return $value; + } + + } diff --git a/src/Parser/Token.php b/src/Parser/Token.php index 5cc58ec..c9753d6 100644 --- a/src/Parser/Token.php +++ b/src/Parser/Token.php @@ -65,8 +65,6 @@ class Token implements Parser */ protected $map = null; - - /** * Token Parser walks through a Config structure and replaces all * occurences of tokens with supplied values. @@ -190,6 +188,20 @@ public function setToken($token, $value) return $this->addToken($token, $value); } + /** + * Build replacement map + */ + protected function buildMap(){ + if (!$this->suffix && !$this->prefix) { + $this->map = $this->tokens; + } else { + $this->map = array(); + foreach ($this->tokens as $token => $value) { + $this->map[$this->prefix . $token . $this->suffix] = $value; + } + } + } + public function parse(Config $config) { if ($config->isReadOnly()) { @@ -197,17 +209,7 @@ public function parse(Config $config) } if ($this->map === null) { - /** - * Build replacement map - */ - if (!$this->suffix && !$this->prefix) { - $this->map = $this->tokens; - } else { - $this->map = array(); - foreach ($this->tokens as $token => $value) { - $this->map[$this->prefix . $token . $this->suffix] = $value; - } - } + $this->buildMap(); } /** @@ -226,4 +228,20 @@ public function parse(Config $config) return $config; } + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function parseValue($value) + { + if ($this->map === null) { + $this->buildMap(); + } + $keys = array_keys($this->map); + $values = array_values($this->map); + return str_replace($keys,$values,$value); + } + } diff --git a/src/Parser/Translator.php b/src/Parser/Translator.php new file mode 100644 index 0000000..76df512 --- /dev/null +++ b/src/Parser/Translator.php @@ -0,0 +1,129 @@ +setTranslator($translator); + $this->setLocale($locale); + } + + /** + * @return \Zend\Translator\Translator + */ + public function getTranslator() + { + return $this->translator; + } + + /** + * @param \Zend\Translator\Translator $translator + */ + public function setTranslator(ZendTranslator $translator) + { + $this->translator = $translator; + } + + /** + * @return \Zend\Locale\Locale|string|null + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param \Zend\Locale\Locale|string|null $locale + */ + public function setLocale($locale) + { + $this->locale = $locale; + } + + public function parse(Config $config) + { + if ($config->isReadOnly()) { + throw new InvalidArgumentException('Cannot parse config because it is read-only'); + } + + /** + * Walk through config and replace values + */ + foreach ($config as $key => $val) { + if ($val instanceof Config) { + $this->parse($val); + } else { + $config->$key = $this->translator->translate($val,$this->locale); + } + } + + return $config; + } + + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function parseValue($value) + { + return $this->translator->translate($value,$this->locale); + } + +} diff --git a/test/ParserTest.php b/test/ParserTest.php index b65ec95..57aadf8 100644 --- a/test/ParserTest.php +++ b/test/ParserTest.php @@ -22,7 +22,13 @@ namespace ZendTest\Config; use Zend\Config\Config, - Zend\Config\Parser\Token as TokenParser; + Zend\Config\Parser\Token as TokenParser, + Zend\Config\Parser\Translator as TranslatorParser, + Zend\Config\Parser\Filter as FilterParser, + Zend\Translator\Translator, + Zend\Translator\Adapter\ArrayAdapter, + Zend\Filter\StringToLower +; /** * @category Zend @@ -36,6 +42,8 @@ class ParserTest extends \PHPUnit_Framework_TestCase { protected $_nested; protected $_tokenBare,$_tokenPrefix, $_tokenSuffix, $_tokenSurround,$_tokenSurroundMixed; + protected $_translator,$_translatorStrings; + protected $_filter; public function setUp() { @@ -98,26 +106,60 @@ public function setUp() $this->_tokenSurroundMixed = array( 'simple' => '##TOKEN##', 'inside' => '## some text with ##TOKEN## inside ##', - 'simple2' => '@@TOKEN@@', - 'inside' => '## some text with ##TOKEN## inside ##', + 'nested' => array( + 'simple' => '@@TOKEN@@', + 'inside' => '@@ some text with @@TOKEN@@ inside @@', + ), + ); + + $this->_translator = array( + 'pages' => array( + array( + 'id' => 'oneDog', + 'label' => 'one dog', + 'route' => 'app-one-dog' + ), + array( + 'id' => 'twoDogs', + 'label' => 'two dogs', + 'route' => 'app-two-dogs' + ), + ) + ); + + $this->_translatorStrings = array( + 'one dog' => 'ein Hund', + 'two dogs' => 'zwei Hunde' + ); + + $this->_filter = array( + 'simple' => 'some MixedCase VALue', + 'nested' => array( + 'simple' => 'OTHER mixed Case Value', + ), ); + + if (ArrayAdapter::hasCache()) { + ArrayAdapter::clearCache(); + ArrayAdapter::removeCache(); + } } public function testEmptyParsersCollection() { $config = new Config($this->_nested); $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); - $this->assertEquals($this->_nested,$config->toArray()); + $this->assertEquals($this->_nested, $config->toArray()); } public function testParsersQueue() { $parser1 = new TokenParser(); $parser2 = new TokenParser(); - $config = new Config(array(),true,array($parser1,$parser2)); + $config = new Config(array(), true, array($parser1, $parser2)); $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); - $this->assertEquals(2,$config->getParsers()->count()); + $this->assertEquals(2, $config->getParsers()->count()); $this->assertTrue($config->getParsers()->contains($parser1)); $this->assertTrue($config->getParsers()->contains($parser2)); } @@ -158,7 +200,7 @@ public function testBareTokenJIT() public function testTokenPrefix() { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'::'); + $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '::'); $config = new Config($this->_tokenPrefix, true, array($parser)); $this->assertEquals('some replaced value', $config->simple); @@ -169,7 +211,7 @@ public function testTokenPrefix() public function testTokenSuffix() { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'','::'); + $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '', '::'); $config = new Config($this->_tokenSuffix, true, array($parser)); $this->assertEquals('some replaced value', $config->simple); @@ -184,7 +226,7 @@ public function testTokenSuffix() */ public function testTokenSurround() { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'##','##'); + $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); $config = new Config($this->_tokenSurround, true, array($parser)); $this->assertEquals('some replaced value', $config->simple); @@ -196,14 +238,115 @@ public function testTokenSurround() /** * @depends testTokenSurround */ - public function testTokenChangeParams(){ - $parser = new TokenParser(array('TOKEN' => 'some replaced value'),'##','##'); - $config = new Config($this->_tokenSurround, true, array($parser)); - $config->nested['nested']['']; + public function testTokenChangeParams() + { + $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); + $config = new Config($this->_tokenSurroundMixed, true); + $parser->parse($config); + $this->assertEquals('some replaced value', $config->simple); + $this->assertEquals('## some text with some replaced value inside ##', $config->inside); + $this->assertEquals('@@TOKEN@@', $config->nested->simple); + $this->assertEquals('@@ some text with @@TOKEN@@ inside @@', $config->nested->inside); + + /** + * Now change prefix and suffix on the parser + */ + $parser->setPrefix('@@'); + $parser->setSuffix('@@'); + + /** + * Parse the config again + */ + $parser->parse($config); + $this->assertEquals('some replaced value', $config->simple); $this->assertEquals('## some text with some replaced value inside ##', $config->inside); $this->assertEquals('some replaced value', $config->nested->simple); - $this->assertEquals('## some text with some replaced value inside ##', $config->nested->inside); + $this->assertEquals('@@ some text with some replaced value inside @@', $config->nested->inside); } + + /** + * @depends testTokenSurround + */ + public function testJITToken() + { + $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); + $config = new Config($this->_tokenSurround, true, $parser); + + $config->simple = 'Changed text with ##TOKEN## inside'; + $this->assertEquals('Changed text with some replaced value inside', $config->simple); + + $config->newKey = 'New text with ##TOKEN##'; + $this->assertEquals('New text with some replaced value', $config->newKey); + } + + /** + * @depends testJITToken + */ + public function testJITNestedToken() + { + $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); + $config = new Config($this->_tokenSurround, true, $parser); + + $config->nested->moreNested = array(); + $config->nested->moreNested->newKey = 'New text with ##TOKEN##'; + $this->assertEquals('New text with some replaced value', $config->nested->moreNested->newKey); + } + + public function testTranslator(){ + $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); + error_reporting(E_ALL);ini_set('display_errors',1); + $parser = new TranslatorParser($translator); + $config = new Config($this->_translator,true); + + $parser->parse($config); + + $this->assertEquals('oneDog',$config->pages[0]->id); + $this->assertEquals('ein Hund',$config->pages[0]->label); + + $this->assertEquals('twoDogs',$config->pages[1]->id); + $this->assertEquals('zwei Hunde',$config->pages[1]->label); + } + + public function testJITTranslator(){ + $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); + $parser = new TranslatorParser($translator); + $config = new Config(array(), true, $parser); + + $config->newValue = 'one dog'; + $this->assertEquals('ein Hund',$config->newValue); + + $config->newValue = 'two dogs'; + $this->assertEquals('zwei Hunde',$config->newValue); + + $config->unknownTranslation = 'three dogs'; + $this->assertEquals('three dogs',$config->unknownTranslation); + } + + public function testFilter(){ + $filter = new StringToLower(); + $parser = new FilterParser($filter); + $config = new Config($this->_filter,1); + + $parser->parse($config); + + $this->assertEquals('some mixedcase value',$config->simple); + $this->assertEquals('other mixed case value',$config->nested->simple); + } + + public function testJITFilter(){ + $filter = new StringToLower(); + $parser = new FilterParser($filter); + $config = new Config($this->_filter,1,$parser); + + $this->assertEquals('some mixedcase value',$config->simple); + $this->assertEquals('other mixed case value',$config->nested->simple); + + $config->newValue = 'THIRD mixed CASE value'; + $this->assertEquals('third mixed case value',$config->newValue); + } + + + } From 40ab875a0f5d0f9090d42db06d067cb7dcbf851a Mon Sep 17 00:00:00 2001 From: Thinkscape Date: Wed, 14 Dec 2011 23:03:19 +0100 Subject: [PATCH 12/18] Add more tests for parser queues --- test/ParserTest.php | 54 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/test/ParserTest.php b/test/ParserTest.php index 57aadf8..0dcd2ab 100644 --- a/test/ParserTest.php +++ b/test/ParserTest.php @@ -27,7 +27,9 @@ Zend\Config\Parser\Filter as FilterParser, Zend\Translator\Translator, Zend\Translator\Adapter\ArrayAdapter, - Zend\Filter\StringToLower + Zend\Filter\StringToLower, + Zend\Filter\StringToUpper, + Zend\Filter\PregReplace ; /** @@ -346,7 +348,57 @@ public function testJITFilter(){ $this->assertEquals('third mixed case value',$config->newValue); } + /** + * @depends testFilter + */ + public function testParsersQueueFIFO(){ + $lower = new StringToLower(); + $upper = new StringToUpper(); + $lowerParser = new FilterParser($lower); + $upperParser = new FilterParser($upper); + + /** + * Default queue order (FIFO) + */ + $config = new Config( + $this->_filter, + 1, + array( + $upperParser, + $lowerParser + ) + ); + $this->assertEquals('some mixedcase value',$config->simple); + $this->assertEquals('other mixed case value',$config->nested->simple); + } + /** + * @depends testParsersQueueFIFO + */ + public function testParsersQueuePriorities(){ + $lower = new StringToLower(); + $upper = new StringToUpper(); + $replace = new PregReplace('/[a-z]/',''); + $lowerParser = new FilterParser($lower); + $upperParser = new FilterParser($upper); + $replaceParser = new FilterParser($replace); + $config = new Config(array(),1); + + /** + * Insert lower case filter with higher priority + */ + $config->getParsers()->insert($upperParser,10); + $config->getParsers()->insert($lowerParser,1000); + $config->simple = 'some MixedCase VALue'; + $this->assertEquals('SOME MIXEDCASE VALUE',$config->simple); + + /** + * Add even higher priority replace parser that will remove all lowercase letters + */ + $config->getParsers()->insert($replaceParser,10000); + $config->newValue = 'THIRD mixed CASE value'; + $this->assertEquals('THIRD CASE ',$config->newValue); + } } From 1fd9b74607378332aff56295e8a3cf5dff7182ec Mon Sep 17 00:00:00 2001 From: Thinkscape Date: Thu, 15 Dec 2011 14:14:32 +0100 Subject: [PATCH 13/18] Add Constant parser, reformat to match zf2 CS --- src/Parser/Constant.php | 110 +++++++++++++++++++++++++++++++ test/ParserTest.php | 142 ++++++++++++++++++++++++++++------------ 2 files changed, 210 insertions(+), 42 deletions(-) create mode 100644 src/Parser/Constant.php diff --git a/src/Parser/Constant.php b/src/Parser/Constant.php new file mode 100644 index 0000000..0cea90a --- /dev/null +++ b/src/Parser/Constant.php @@ -0,0 +1,110 @@ +setUserOnly($userOnly); + $this->setPrefix($prefix); + $this->setSuffix($suffix); + + $this->loadConstants(); + } + + /** + * @return bool + */ + public function getUserOnly() + { + return $this->userOnly; + } + + /** + * Should we use only user-defined constants? + * + * @param $userOnly + * @return bool + */ + public function setUserOnly($userOnly) + { + return $this->userOnly = $userOnly; + } + + /** + * Load all currently defined constants into parser. + * + * @return void + */ + public function loadConstants() + { + if ($this->userOnly) { + $constants = get_defined_constants(true); + $constants = isset($constants['user']) ? $constants['user'] : array(); + $this->setTokens($constants); + } else { + $this->setTokens(get_defined_constants()); + } + } + + /** + * Get current token registry. + * @return array + */ + public function getTokens() + { + return $this->tokens; + } + +} diff --git a/test/ParserTest.php b/test/ParserTest.php index 0dcd2ab..96d191b 100644 --- a/test/ParserTest.php +++ b/test/ParserTest.php @@ -22,15 +22,15 @@ namespace ZendTest\Config; use Zend\Config\Config, - Zend\Config\Parser\Token as TokenParser, - Zend\Config\Parser\Translator as TranslatorParser, - Zend\Config\Parser\Filter as FilterParser, - Zend\Translator\Translator, - Zend\Translator\Adapter\ArrayAdapter, - Zend\Filter\StringToLower, - Zend\Filter\StringToUpper, - Zend\Filter\PregReplace -; +Zend\Config\Parser\Token as TokenParser, +Zend\Config\Parser\Translator as TranslatorParser, +Zend\Config\Parser\Filter as FilterParser, +Zend\Config\Parser\Constant as ConstantParser, +Zend\Translator\Translator, +Zend\Translator\Adapter\ArrayAdapter, +Zend\Filter\StringToLower, +Zend\Filter\StringToUpper, +Zend\Filter\PregReplace; /** * @category Zend @@ -43,8 +43,9 @@ class ParserTest extends \PHPUnit_Framework_TestCase { protected $_nested; - protected $_tokenBare,$_tokenPrefix, $_tokenSuffix, $_tokenSurround,$_tokenSurroundMixed; - protected $_translator,$_translatorStrings; + protected $_tokenBare, $_tokenPrefix, $_tokenSuffix, $_tokenSurround, $_tokenSurroundMixed; + protected $_translator, $_translatorStrings; + protected $_userConstants, $_phpConstants; protected $_filter; public function setUp() @@ -145,6 +146,24 @@ public function setUp() ArrayAdapter::clearCache(); ArrayAdapter::removeCache(); } + + $this->_userConstants = array( + 'simple' => 'SOME_USERLAND_CONSTANT', + 'inside' => 'some text with SOME_USERLAND_CONSTANT inside', + 'nested' => array( + 'simple' => 'SOME_USERLAND_CONSTANT', + 'inside' => 'some text with SOME_USERLAND_CONSTANT inside', + ), + ); + + $this->_phpConstants = array( + 'phpVersion' => 'PHP_VERSION', + 'phpVersionInside' => 'Current PHP version is: PHP_VERSION', + 'nested' => array( + 'phpVersion' => 'PHP_VERSION', + 'phpVersionInside' => 'Current PHP version is: PHP_VERSION', + ), + ); } public function testEmptyParsersCollection() @@ -295,63 +314,101 @@ public function testJITNestedToken() $this->assertEquals('New text with some replaced value', $config->nested->moreNested->newKey); } - public function testTranslator(){ + /** + * @depends testTokenSurround + */ + public function testUserConstants() + { + define('SOME_USERLAND_CONSTANT', 'some constant value'); + + $parser = new ConstantParser(); + $config = new Config($this->_userConstants, true); + $parser->parse($config); + + $this->assertEquals('some constant value', $config->simple); + $this->assertEquals('some text with some constant value inside', $config->inside); + $this->assertEquals('some constant value', $config->nested->simple); + $this->assertEquals('some text with some constant value inside', $config->nested->inside); + } + + /** + * @depends testTokenSurround + */ + public function testPHPConstants() + { + $parser = new ConstantParser(false); + $config = new Config($this->_phpConstants, true); + $parser->parse($config); + + $this->assertEquals(PHP_VERSION, $config->phpVersion); + $this->assertEquals('Current PHP version is: ' . PHP_VERSION, $config->phpVersionInside); + $this->assertEquals(PHP_VERSION, $config->nested->phpVersion); + $this->assertEquals('Current PHP version is: ' . PHP_VERSION, $config->nested->phpVersionInside); + } + + public function testTranslator() + { $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); - error_reporting(E_ALL);ini_set('display_errors',1); + error_reporting(E_ALL); + ini_set('display_errors', 1); $parser = new TranslatorParser($translator); - $config = new Config($this->_translator,true); + $config = new Config($this->_translator, true); $parser->parse($config); - $this->assertEquals('oneDog',$config->pages[0]->id); - $this->assertEquals('ein Hund',$config->pages[0]->label); + $this->assertEquals('oneDog', $config->pages[0]->id); + $this->assertEquals('ein Hund', $config->pages[0]->label); - $this->assertEquals('twoDogs',$config->pages[1]->id); - $this->assertEquals('zwei Hunde',$config->pages[1]->label); + $this->assertEquals('twoDogs', $config->pages[1]->id); + $this->assertEquals('zwei Hunde', $config->pages[1]->label); } - public function testJITTranslator(){ + public function testJITTranslator() + { $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); $parser = new TranslatorParser($translator); $config = new Config(array(), true, $parser); $config->newValue = 'one dog'; - $this->assertEquals('ein Hund',$config->newValue); + $this->assertEquals('ein Hund', $config->newValue); $config->newValue = 'two dogs'; - $this->assertEquals('zwei Hunde',$config->newValue); + $this->assertEquals('zwei Hunde', $config->newValue); $config->unknownTranslation = 'three dogs'; - $this->assertEquals('three dogs',$config->unknownTranslation); + $this->assertEquals('three dogs', $config->unknownTranslation); } - public function testFilter(){ + public function testFilter() + { $filter = new StringToLower(); $parser = new FilterParser($filter); - $config = new Config($this->_filter,1); + $config = new Config($this->_filter, 1); $parser->parse($config); - $this->assertEquals('some mixedcase value',$config->simple); - $this->assertEquals('other mixed case value',$config->nested->simple); + $this->assertEquals('some mixedcase value', $config->simple); + $this->assertEquals('other mixed case value', $config->nested->simple); } - public function testJITFilter(){ + public function testJITFilter() + { $filter = new StringToLower(); $parser = new FilterParser($filter); - $config = new Config($this->_filter,1,$parser); + $config = new Config($this->_filter, 1, $parser); - $this->assertEquals('some mixedcase value',$config->simple); - $this->assertEquals('other mixed case value',$config->nested->simple); + $this->assertEquals('some mixedcase value', $config->simple); + $this->assertEquals('other mixed case value', $config->nested->simple); $config->newValue = 'THIRD mixed CASE value'; - $this->assertEquals('third mixed case value',$config->newValue); + $this->assertEquals('third mixed case value', $config->newValue); } /** * @depends testFilter */ - public function testParsersQueueFIFO(){ + public function testParsersQueueFIFO() + { $lower = new StringToLower(); $upper = new StringToUpper(); $lowerParser = new FilterParser($lower); @@ -368,36 +425,37 @@ public function testParsersQueueFIFO(){ $lowerParser ) ); - $this->assertEquals('some mixedcase value',$config->simple); - $this->assertEquals('other mixed case value',$config->nested->simple); + $this->assertEquals('some mixedcase value', $config->simple); + $this->assertEquals('other mixed case value', $config->nested->simple); } /** * @depends testParsersQueueFIFO */ - public function testParsersQueuePriorities(){ + public function testParsersQueuePriorities() + { $lower = new StringToLower(); $upper = new StringToUpper(); - $replace = new PregReplace('/[a-z]/',''); + $replace = new PregReplace('/[a-z]/', ''); $lowerParser = new FilterParser($lower); $upperParser = new FilterParser($upper); $replaceParser = new FilterParser($replace); - $config = new Config(array(),1); + $config = new Config(array(), 1); /** * Insert lower case filter with higher priority */ - $config->getParsers()->insert($upperParser,10); - $config->getParsers()->insert($lowerParser,1000); + $config->getParsers()->insert($upperParser, 10); + $config->getParsers()->insert($lowerParser, 1000); $config->simple = 'some MixedCase VALue'; - $this->assertEquals('SOME MIXEDCASE VALUE',$config->simple); + $this->assertEquals('SOME MIXEDCASE VALUE', $config->simple); /** * Add even higher priority replace parser that will remove all lowercase letters */ - $config->getParsers()->insert($replaceParser,10000); + $config->getParsers()->insert($replaceParser, 10000); $config->newValue = 'THIRD mixed CASE value'; - $this->assertEquals('THIRD CASE ',$config->newValue); + $this->assertEquals('THIRD CASE ', $config->newValue); } } From 7e1678d6806e0c806f1a14f1cbae5d5d0cd58b97 Mon Sep 17 00:00:00 2001 From: Thinkscape Date: Tue, 24 Jan 2012 23:10:05 +0100 Subject: [PATCH 14/18] Refactor Config\Parser to Config\Processor, remove JIT processing functionality --- src/Config.php | 113 +---------- src/{Parser.php => Processor.php} | 6 +- src/{Parser => Processor}/Constant.php | 12 +- src/{Parser => Processor}/Filter.php | 14 +- src/{Parser => Processor}/Queue.php | 21 +- src/{Parser => Processor}/Token.php | 16 +- src/{Parser => Processor}/Translator.php | 14 +- test/{ParserTest.php => ProcessorTest.php} | 218 +++++++-------------- 8 files changed, 118 insertions(+), 296 deletions(-) rename src/{Parser.php => Processor.php} (91%) rename src/{Parser => Processor}/Constant.php (90%) rename src/{Parser => Processor}/Filter.php (89%) rename src/{Parser => Processor}/Queue.php (80%) rename src/{Parser => Processor}/Token.php (94%) rename src/{Parser => Processor}/Translator.php (91%) rename test/{ParserTest.php => ProcessorTest.php} (61%) diff --git a/src/Config.php b/src/Config.php index 249e3ec..91dd273 100644 --- a/src/Config.php +++ b/src/Config.php @@ -25,10 +25,7 @@ use \Countable, \Iterator, - \ArrayAccess, - Zend\Config\Exception\InvalidArgumentException, - Zend\Config\Parser, - Zend\Config\Parser\Queue as ParserQueue; + \ArrayAccess; /** * @category Zend @@ -59,13 +56,6 @@ class Config implements Countable, Iterator, ArrayAccess */ protected $data = array(); - /** - * Data withing the configuration. - * - * @var \Zend\Config\Parser\Queue - */ - protected $parsers; - /** * Used when unsetting values during iteration to ensure we do not skip * the next element. @@ -91,36 +81,21 @@ class Config implements Countable, Iterator, ArrayAccess * * @param array $array * @param boolean $allowModifications - * @param \Zend\Config\Parser\Queue|\Zend\Config\Parser|Traversable|array $parsers - * @return \Zend\Config\Config + * @return void */ - public function __construct(array $array, $allowModifications = false, $parsers = null) + public function __construct(array $array, $allowModifications = false) { $this->allowModifications = (boolean) $allowModifications; - if ($parsers !== null) { - $parsers = $this->setParsers($parsers); - } else { - // create empty queue - $parsers = $this->getParsers(); - } - foreach ($array as $key => $value) { if (is_array($value)) { - $this->data[$key] = new self($value, $this->allowModifications, $parsers); + $this->data[$key] = new self($value, $this->allowModifications); } else { $this->data[$key] = $value; } - + $this->count++; } - - /** - * Process config - */ - if(!$parsers->isEmpty()){ - $this->parse(); - } } /** @@ -164,13 +139,9 @@ public function __set($name, $value) { if ($this->allowModifications) { if (is_array($value)) { - $this->data[$name] = new self($value, true, $this->parsers); + $this->data[$name] = new self($value, true); } else { - if (!$this->parsers->isEmpty()) { - $this->data[$name] = $this->parsers->parseValue($value); - } else { - $this->data[$name] = $value; - } + $this->data[$name] = $value; } $this->count++; @@ -385,15 +356,13 @@ public function merge(self $merge) foreach ($merge as $key => $item) { if (array_key_exists($key, $this->data)) { if ($item instanceof self && $this->data[$key] instanceof self) { - $this->data[$key] = $this->data[$key]->merge( - new self($item->toArray(), $this->allowModifications, $this->parsers) - ); + $this->data[$key] = $this->data[$key]->merge(new self($item->toArray(), $this->allowModifications)); } else { $this->data[$key] = $item; } } else { if ($item instanceof self) { - $this->data[$key] = new self($item->toArray(), $this->allowModifications, $this->parsers); + $this->data[$key] = new self($item->toArray(), $this->allowModifications); } else { $this->data[$key] = $item; } @@ -431,68 +400,4 @@ public function isReadOnly() { return !$this->allowModifications; } - - /** - * Get parsers queue for this config. - * - * @return \Zend\Config\Parser\Queue - */ - public function getParsers(){ - if ($this->parsers === null) { - $this->parsers = new ParserQueue(); - } - return $this->parsers; - } - - /** - * Set config parsers - * - * @param \Zend\Config\Parser\Queue|\Zend\Config\Parser|Traversable|array $parsers - * @return \Zend\Config\Parser\Queue - * @throws Exception\InvalidArgumentException - */ - public function setParsers($parsers) - { - // A complete, ready to use queue object - if ($parsers instanceof ParserQueue) { - return $this->parsers = $parsers; - } - - // A single parser - elseif ($parsers instanceof Parser) { - $this->parsers = new ParserQueue(); - $this->parsers->insert($parsers); - return $this->parsers; - } - - // An array of parsers - elseif ( - !is_array($parsers) && - !($parsers instanceof \Traversable) && - !($parsers instanceof ParserQueue) - ) { - throw new InvalidArgumentException('Cannot use ' . gettype($parsers) . ' as a parsers.'); - } - - $this->parsers = new ParserQueue(); - foreach ($parsers as $parser) { - if ($parser instanceof Parser) { - $this->parsers->insert($parser); - } else { - throw new InvalidArgumentException('Cannot use ' . gettype($parser) . ' as a parser'); - } - } - - return $this->parsers; - } - - /** - * Process the whole config structure with each parser in the queue. - * - * @return void - */ - public function parse() - { - $this->getParsers()->parse($this); - } } diff --git a/src/Parser.php b/src/Processor.php similarity index 91% rename from src/Parser.php rename to src/Processor.php index 53e6c55..e80f9bb 100644 --- a/src/Parser.php +++ b/src/Processor.php @@ -29,7 +29,7 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -interface Parser +interface Processor { /** * Process the whole Config structure and recursively parse all its values. @@ -37,7 +37,7 @@ interface Parser * @param Config $value * @return \Zend\Config\Config */ - public function parse(Config $value); + public function process(Config $value); /** * Process a single value @@ -45,5 +45,5 @@ public function parse(Config $value); * @param $value * @return mixed */ - public function parseValue($value); + public function processValue($value); } diff --git a/src/Parser/Constant.php b/src/Processor/Constant.php similarity index 90% rename from src/Parser/Constant.php rename to src/Processor/Constant.php index 0cea90a..69f4793 100644 --- a/src/Parser/Constant.php +++ b/src/Processor/Constant.php @@ -21,11 +21,11 @@ /** * @namespace */ -namespace Zend\Config\Parser; +namespace Zend\Config\Processor; use Zend\Config\Config, - Zend\Config\Parser, - Zend\Config\Parser\Token, + Zend\Config\Processor, + Zend\Config\Processor\Token, Zend\Config\Exception\InvalidArgumentException, \Traversable, \ArrayObject; @@ -36,7 +36,7 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Constant extends Token implements Parser +class Constant extends Token implements Processor { /** * Replace only user-defined tokens @@ -46,13 +46,13 @@ class Constant extends Token implements Parser protected $userOnly = true; /** - * Constant Parser walks through a Config structure and replaces all + * Constant Processor walks through a Config structure and replaces all * PHP constants with their respective values * * @param bool $userOnly True to process only user-defined constants, false to process all PHP constants * @param string $prefix Optional prefix * @param string $suffix Optional suffix - * @return \Zend\Config\Parser\Constant + * @return \Zend\Config\Processor\Constant */ public function __construct($userOnly = true, $prefix = '', $suffix = '') { diff --git a/src/Parser/Filter.php b/src/Processor/Filter.php similarity index 89% rename from src/Parser/Filter.php rename to src/Processor/Filter.php index 287f16a..6b35b5d 100644 --- a/src/Parser/Filter.php +++ b/src/Processor/Filter.php @@ -21,10 +21,10 @@ /** * @namespace */ -namespace Zend\Config\Parser; +namespace Zend\Config\Processor; use Zend\Config\Config, - Zend\Config\Parser, + Zend\Config\Processor, Zend\Config\Exception\InvalidArgumentException, Zend\Filter\Filter as ZendFilter, \Traversable, @@ -36,7 +36,7 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Filter implements Parser +class Filter implements Processor { /** * @var \Zend\Filter\Filter @@ -47,7 +47,7 @@ class Filter implements Parser * Filter all config values using the supplied Zend\Filter * * @param \Zend\Filter\Filter $filter - * @return \Zend\Config\Parser\Filter + * @return \Zend\Config\Processor\Filter */ public function __construct(ZendFilter $filter) { @@ -70,7 +70,7 @@ public function setFilter(ZendFilter $filter) $this->filter = $filter; } - public function parse(Config $config) + public function process(Config $config) { if ($config->isReadOnly()) { throw new InvalidArgumentException('Cannot parse config because it is read-only'); @@ -81,7 +81,7 @@ public function parse(Config $config) */ foreach ($config as $key => $val) { if ($val instanceof Config) { - $this->parse($val); + $this->process($val); } else { $config->$key = $this->filter->filter($val); } @@ -96,7 +96,7 @@ public function parse(Config $config) * @param $value * @return mixed */ - public function parseValue($value) + public function processValue($value) { return $this->filter->filter($value); } diff --git a/src/Parser/Queue.php b/src/Processor/Queue.php similarity index 80% rename from src/Parser/Queue.php rename to src/Processor/Queue.php index c01487f..42d1169 100644 --- a/src/Parser/Queue.php +++ b/src/Processor/Queue.php @@ -21,10 +21,10 @@ /** * @namespace */ -namespace Zend\Config\Parser; +namespace Zend\Config\Processor; use Zend\Config\Config, - Zend\Config\Parser, + Zend\Config\Processor, Zend\Config\Exception\InvalidArgumentException, Zend\Stdlib\PriorityQueue; @@ -34,24 +34,23 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Queue extends PriorityQueue implements Parser +class Queue extends PriorityQueue implements Processor { - /** * Process the whole config structure with each parser in the queue. * * @param \Zend\Config\Config $config * @throws \Zend\Config\Exception\InvalidArgumentException */ - public function parse(Config $config) + public function process(Config $config) { if ($config->isReadOnly()) { throw new InvalidArgumentException('Cannot parse config because it is read-only'); } foreach ($this as $parser) { - /** @var $parser \Zend\Config\Parser */ - $parser->parse($config); + /** @var $parser \Zend\Config\Processor */ + $parser->process($config); } } @@ -61,15 +60,13 @@ public function parse(Config $config) * @param $value * @return mixed */ - public function parseValue($value) + public function processValue($value) { foreach ($this as $parser) { - /** @var $parser \Zend\Config\Parser */ - $value = $parser->parseValue($value); + /** @var $parser \Zend\Config\Processor */ + $value = $parser->processValue($value); } return $value; } - - } diff --git a/src/Parser/Token.php b/src/Processor/Token.php similarity index 94% rename from src/Parser/Token.php rename to src/Processor/Token.php index c9753d6..23fbc9d 100644 --- a/src/Parser/Token.php +++ b/src/Processor/Token.php @@ -21,10 +21,10 @@ /** * @namespace */ -namespace Zend\Config\Parser; +namespace Zend\Config\Processor; use Zend\Config\Config, - Zend\Config\Parser, + Zend\Config\Processor, Zend\Config\Exception\InvalidArgumentException, \Traversable, \ArrayObject; @@ -35,7 +35,7 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Token implements Parser +class Token implements Processor { /** * Token prefix. @@ -66,7 +66,7 @@ class Token implements Parser protected $map = null; /** - * Token Parser walks through a Config structure and replaces all + * Token Processor walks through a Config structure and replaces all * occurences of tokens with supplied values. * * @param array|\Zend\Config\Config|ArrayObject|\Traversable $tokens Associative array of TOKEN => value @@ -74,7 +74,7 @@ class Token implements Parser * @param string $prefix * @param string $suffix * @internal param array $options - * @return \Zend\Config\Parser\Token + * @return \Zend\Config\Processor\Token */ public function __construct($tokens = array(), $prefix = '', $suffix = '') { @@ -202,7 +202,7 @@ protected function buildMap(){ } } - public function parse(Config $config) + public function process(Config $config) { if ($config->isReadOnly()) { throw new InvalidArgumentException('Cannot parse config because it is read-only'); @@ -219,7 +219,7 @@ public function parse(Config $config) $values = array_values($this->map); foreach ($config as $key => $val) { if ($val instanceof Config) { - $this->parse($val); + $this->process($val); } else { $config->$key = str_replace($keys,$values,$val); } @@ -234,7 +234,7 @@ public function parse(Config $config) * @param $value * @return mixed */ - public function parseValue($value) + public function processValue($value) { if ($this->map === null) { $this->buildMap(); diff --git a/src/Parser/Translator.php b/src/Processor/Translator.php similarity index 91% rename from src/Parser/Translator.php rename to src/Processor/Translator.php index 76df512..19362d1 100644 --- a/src/Parser/Translator.php +++ b/src/Processor/Translator.php @@ -21,10 +21,10 @@ /** * @namespace */ -namespace Zend\Config\Parser; +namespace Zend\Config\Processor; use Zend\Config\Config, - Zend\Config\Parser, + Zend\Config\Processor, Zend\Config\Exception\InvalidArgumentException, Zend\Translator\Translator as ZendTranslator, Zend\Locale\Locale, @@ -37,7 +37,7 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Translator implements Parser +class Translator implements Processor { /** * @var \Zend\Translator\Translator @@ -55,7 +55,7 @@ class Translator implements Parser * * @param \Zend\Translator\Translator $translator * @param \Zend\Locale\Locale|string|null $locale - * @return \Zend\Config\Parser\Translator + * @return \Zend\Config\Processor\Translator */ public function __construct(ZendTranslator $translator, $locale = null) { @@ -95,7 +95,7 @@ public function setLocale($locale) $this->locale = $locale; } - public function parse(Config $config) + public function process(Config $config) { if ($config->isReadOnly()) { throw new InvalidArgumentException('Cannot parse config because it is read-only'); @@ -106,7 +106,7 @@ public function parse(Config $config) */ foreach ($config as $key => $val) { if ($val instanceof Config) { - $this->parse($val); + $this->process($val); } else { $config->$key = $this->translator->translate($val,$this->locale); } @@ -121,7 +121,7 @@ public function parse(Config $config) * @param $value * @return mixed */ - public function parseValue($value) + public function processValue($value) { return $this->translator->translate($value,$this->locale); } diff --git a/test/ParserTest.php b/test/ProcessorTest.php similarity index 61% rename from test/ParserTest.php rename to test/ProcessorTest.php index 96d191b..2682180 100644 --- a/test/ParserTest.php +++ b/test/ProcessorTest.php @@ -15,17 +15,18 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace ZendTest\Config; use Zend\Config\Config, -Zend\Config\Parser\Token as TokenParser, -Zend\Config\Parser\Translator as TranslatorParser, -Zend\Config\Parser\Filter as FilterParser, -Zend\Config\Parser\Constant as ConstantParser, +Zend\Config\Processor\Token as TokenProcessor, +Zend\Config\Processor\Translator as TranslatorProcessor, +Zend\Config\Processor\Filter as FilterProcessor, +Zend\Config\Processor\Constant as ConstantProcessor, +Zend\Config\Processor\Queue as Queue, Zend\Translator\Translator, Zend\Translator\Adapter\ArrayAdapter, Zend\Filter\StringToLower, @@ -40,7 +41,7 @@ * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ -class ParserTest extends \PHPUnit_Framework_TestCase +class ProcessorTest extends \PHPUnit_Framework_TestCase { protected $_nested; protected $_tokenBare, $_tokenPrefix, $_tokenSuffix, $_tokenSurround, $_tokenSurroundMixed; @@ -166,52 +167,26 @@ public function setUp() ); } - public function testEmptyParsersCollection() - { - $config = new Config($this->_nested); - $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); - $this->assertEquals($this->_nested, $config->toArray()); - } - - public function testParsersQueue() - { - $parser1 = new TokenParser(); - $parser2 = new TokenParser(); - $config = new Config(array(), true, array($parser1, $parser2)); - - $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); - $this->assertEquals(2, $config->getParsers()->count()); - $this->assertTrue($config->getParsers()->contains($parser1)); - $this->assertTrue($config->getParsers()->contains($parser2)); - } - - public function testParsersCollectionPersistence() + public function testProcessorsQueue() { - $config = new Config($this->_nested); - $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->getParsers()); - $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->c->getParsers()); - $this->assertInstanceOf('\Zend\Config\Parser\Queue', $config->c->cd->getParsers()); - $this->assertSame($config->getParsers(), $config->c->getParsers()); - $this->assertSame($config->c->getParsers(), $config->c->cd->getParsers()); + $processor1 = new TokenProcessor(); + $processor2 = new TokenProcessor(); + $queue = new Queue(); + $queue->insert($processor1); + $queue->insert($processor2); + + $this->assertInstanceOf('\Zend\Config\Processor\Queue', $queue); + $this->assertEquals(2, $queue->count()); + $this->assertTrue($queue->contains($processor1)); + $this->assertTrue($queue->contains($processor2)); } public function testBareTokenPost() { $config = new Config($this->_tokenBare, true); - $parser = new TokenParser(); - $parser->addToken('BARETOKEN', 'some replaced value'); - $parser->parse($config); - - $this->assertEquals('some replaced value', $config->simple); - $this->assertEquals('some text with some replaced value inside', $config->inside); - $this->assertEquals('some replaced value', $config->nested->simple); - $this->assertEquals('some text with some replaced value inside', $config->nested->inside); - } - - public function testBareTokenJIT() - { - $parser = new TokenParser(array('BARETOKEN' => 'some replaced value')); - $config = new Config($this->_tokenBare, true, array($parser)); + $processor = new TokenProcessor(); + $processor->addToken('BARETOKEN', 'some replaced value'); + $processor->process($config); $this->assertEquals('some replaced value', $config->simple); $this->assertEquals('some text with some replaced value inside', $config->inside); @@ -221,8 +196,9 @@ public function testBareTokenJIT() public function testTokenPrefix() { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '::'); - $config = new Config($this->_tokenPrefix, true, array($parser)); + $config = new Config($this->_tokenPrefix, true); + $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '::'); + $processor->process($config); $this->assertEquals('some replaced value', $config->simple); $this->assertEquals(':: some text with some replaced value inside ::', $config->inside); @@ -232,8 +208,9 @@ public function testTokenPrefix() public function testTokenSuffix() { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '', '::'); - $config = new Config($this->_tokenSuffix, true, array($parser)); + $config = new Config($this->_tokenSuffix, true); + $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '', '::'); + $processor->process($config); $this->assertEquals('some replaced value', $config->simple); $this->assertEquals(':: some text with some replaced value inside ::', $config->inside); @@ -247,8 +224,9 @@ public function testTokenSuffix() */ public function testTokenSurround() { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); - $config = new Config($this->_tokenSurround, true, array($parser)); + $config = new Config($this->_tokenSurround, true); + $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '##', '##'); + $processor->process($config); $this->assertEquals('some replaced value', $config->simple); $this->assertEquals('## some text with some replaced value inside ##', $config->inside); @@ -261,24 +239,24 @@ public function testTokenSurround() */ public function testTokenChangeParams() { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); $config = new Config($this->_tokenSurroundMixed, true); - $parser->parse($config); + $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '##', '##'); + $processor->process($config); $this->assertEquals('some replaced value', $config->simple); $this->assertEquals('## some text with some replaced value inside ##', $config->inside); $this->assertEquals('@@TOKEN@@', $config->nested->simple); $this->assertEquals('@@ some text with @@TOKEN@@ inside @@', $config->nested->inside); /** - * Now change prefix and suffix on the parser + * Now change prefix and suffix on the processor */ - $parser->setPrefix('@@'); - $parser->setSuffix('@@'); + $processor->setPrefix('@@'); + $processor->setSuffix('@@'); /** * Parse the config again */ - $parser->parse($config); + $processor->process($config); $this->assertEquals('some replaced value', $config->simple); $this->assertEquals('## some text with some replaced value inside ##', $config->inside); @@ -286,34 +264,6 @@ public function testTokenChangeParams() $this->assertEquals('@@ some text with some replaced value inside @@', $config->nested->inside); } - /** - * @depends testTokenSurround - */ - public function testJITToken() - { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); - $config = new Config($this->_tokenSurround, true, $parser); - - $config->simple = 'Changed text with ##TOKEN## inside'; - $this->assertEquals('Changed text with some replaced value inside', $config->simple); - - $config->newKey = 'New text with ##TOKEN##'; - $this->assertEquals('New text with some replaced value', $config->newKey); - } - - /** - * @depends testJITToken - */ - public function testJITNestedToken() - { - $parser = new TokenParser(array('TOKEN' => 'some replaced value'), '##', '##'); - $config = new Config($this->_tokenSurround, true, $parser); - - $config->nested->moreNested = array(); - $config->nested->moreNested->newKey = 'New text with ##TOKEN##'; - $this->assertEquals('New text with some replaced value', $config->nested->moreNested->newKey); - } - /** * @depends testTokenSurround */ @@ -321,9 +271,9 @@ public function testUserConstants() { define('SOME_USERLAND_CONSTANT', 'some constant value'); - $parser = new ConstantParser(); $config = new Config($this->_userConstants, true); - $parser->parse($config); + $processor = new ConstantProcessor(); + $processor->process($config); $this->assertEquals('some constant value', $config->simple); $this->assertEquals('some text with some constant value inside', $config->inside); @@ -336,9 +286,9 @@ public function testUserConstants() */ public function testPHPConstants() { - $parser = new ConstantParser(false); $config = new Config($this->_phpConstants, true); - $parser->parse($config); + $processor = new ConstantProcessor(false); + $processor->process($config); $this->assertEquals(PHP_VERSION, $config->phpVersion); $this->assertEquals('Current PHP version is: ' . PHP_VERSION, $config->phpVersionInside); @@ -348,13 +298,11 @@ public function testPHPConstants() public function testTranslator() { - $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); - error_reporting(E_ALL); - ini_set('display_errors', 1); - $parser = new TranslatorParser($translator); $config = new Config($this->_translator, true); + $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); + $processor = new TranslatorProcessor($translator); - $parser->parse($config); + $processor->process($config); $this->assertEquals('oneDog', $config->pages[0]->id); $this->assertEquals('ein Hund', $config->pages[0]->label); @@ -363,98 +311,70 @@ public function testTranslator() $this->assertEquals('zwei Hunde', $config->pages[1]->label); } - public function testJITTranslator() - { - $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); - $parser = new TranslatorParser($translator); - $config = new Config(array(), true, $parser); - - $config->newValue = 'one dog'; - $this->assertEquals('ein Hund', $config->newValue); - - $config->newValue = 'two dogs'; - $this->assertEquals('zwei Hunde', $config->newValue); - - $config->unknownTranslation = 'three dogs'; - $this->assertEquals('three dogs', $config->unknownTranslation); - } - public function testFilter() { + $config = new Config($this->_filter, true); $filter = new StringToLower(); - $parser = new FilterParser($filter); - $config = new Config($this->_filter, 1); - - $parser->parse($config); + $processor = new FilterProcessor($filter); + $processor->process($config); $this->assertEquals('some mixedcase value', $config->simple); $this->assertEquals('other mixed case value', $config->nested->simple); } - public function testJITFilter() - { - $filter = new StringToLower(); - $parser = new FilterParser($filter); - $config = new Config($this->_filter, 1, $parser); - - $this->assertEquals('some mixedcase value', $config->simple); - $this->assertEquals('other mixed case value', $config->nested->simple); - - $config->newValue = 'THIRD mixed CASE value'; - $this->assertEquals('third mixed case value', $config->newValue); - } - /** * @depends testFilter */ - public function testParsersQueueFIFO() + public function testProcessorsQueueFIFO() { + $config = new Config($this->_filter, true); $lower = new StringToLower(); $upper = new StringToUpper(); - $lowerParser = new FilterParser($lower); - $upperParser = new FilterParser($upper); + $lowerProcessor = new FilterProcessor($lower); + $upperProcessor = new FilterProcessor($upper); /** * Default queue order (FIFO) */ - $config = new Config( - $this->_filter, - 1, - array( - $upperParser, - $lowerParser - ) - ); + $queue = new Queue(); + $queue->insert($upperProcessor); + $queue->insert($lowerProcessor); + $queue->process($config); + $this->assertEquals('some mixedcase value', $config->simple); $this->assertEquals('other mixed case value', $config->nested->simple); } /** - * @depends testParsersQueueFIFO + * @depends testProcessorsQueueFIFO */ - public function testParsersQueuePriorities() + public function testProcessorsQueuePriorities() { + $config = new Config($this->_filter, 1); $lower = new StringToLower(); $upper = new StringToUpper(); $replace = new PregReplace('/[a-z]/', ''); - $lowerParser = new FilterParser($lower); - $upperParser = new FilterParser($upper); - $replaceParser = new FilterParser($replace); - $config = new Config(array(), 1); + $lowerProcessor = new FilterProcessor($lower); + $upperProcessor = new FilterProcessor($upper); + $replaceProcessor = new FilterProcessor($replace); + $queue = new Queue(); /** * Insert lower case filter with higher priority */ - $config->getParsers()->insert($upperParser, 10); - $config->getParsers()->insert($lowerParser, 1000); + $queue->insert($upperProcessor, 10); + $queue->insert($lowerProcessor, 1000); + $config->simple = 'some MixedCase VALue'; + $queue->process($config); $this->assertEquals('SOME MIXEDCASE VALUE', $config->simple); /** - * Add even higher priority replace parser that will remove all lowercase letters + * Add even higher priority replace processor that will remove all lowercase letters */ - $config->getParsers()->insert($replaceParser, 10000); + $queue->insert($replaceProcessor, 10000); $config->newValue = 'THIRD mixed CASE value'; + $queue->process($config); $this->assertEquals('THIRD CASE ', $config->newValue); } From 35b9c182951135cceabce6e32d7b21975453e0e8 Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Fri, 10 Feb 2012 17:27:48 +0100 Subject: [PATCH 15/18] Removed constant, __DIR__ and inheritance support from readers --- src/Config.php | 9 +- src/Reader/AbstractReader.php | 184 ---------------------------------- src/Reader/Ini.php | 85 +++++----------- src/Reader/Xml.php | 93 +++++------------ 4 files changed, 49 insertions(+), 322 deletions(-) delete mode 100644 src/Reader/AbstractReader.php diff --git a/src/Config.php b/src/Config.php index 8d93941..407d990 100644 --- a/src/Config.php +++ b/src/Config.php @@ -61,13 +61,6 @@ class Config implements Countable, Iterator, ArrayAccess */ protected $skipNextIteration; - /** - * Internal error messages. - * - * @var null|array - */ - protected $_errorMessages = array(); - /** * Zend_Config provides a property based interface to * an array. The data are read-only unless $allowModifications @@ -381,7 +374,7 @@ public function setReadOnly() { $this->allowModifications = false; - foreach ($this->data as $key => $value) { + foreach ($this->data as $value) { if ($value instanceof self) { $value->setReadOnly(); } diff --git a/src/Reader/AbstractReader.php b/src/Reader/AbstractReader.php deleted file mode 100644 index ba37c56..0000000 --- a/src/Reader/AbstractReader.php +++ /dev/null @@ -1,184 +0,0 @@ -extends = array(); - - return $this->processAllExtends($this->processFile($filename)); - } - - /** - * fromString(): defined by Reader interface. - * - * @see Reader::fromString() - * @param string $string - * @return array - */ - public function fromString($string) - { - $this->extends = array(); - - return $this->processAllExtends($this->processString($string)); - } - - /** - * Process a file. - * - * @param string $filename - * @return array - */ - abstract protected function processFile($filename); - - /** - * Process a string. - * - * @param string $string - * @return array - */ - abstract protected function processString($string); - - /** - * Process all extends directives. - * - * @return array - */ - protected function processAllExtends(array $data) - { - $this->processedExtends = array(); - - if (!$this->shouldProcessExtends()) { - return $data; - } - - // Check for circular extends - $extends = $this->extends; - - foreach ($extends as $extendingSection => $extendedSection) { - if (!isset($data[$extendedSection])) { - throw new Exception\RuntimeException(sprintf('Missing extended section "%s"', $extendedSection)); - } elseif (!isset($data[$extendingSection])) { - throw new Exception\RuntimeException(sprintf('Missing extending section "%s"', $extendingSection)); - } elseif (!isset($this->extends[$extendingSection])) { - continue; - } - - $this->processExtend($data, $extendingSection, $extendedSection); - } - - return $data; - } - - /** - * Process a single extend directive. - * - * The $data array is always passed by references, so modifications on it - * won't require a copy of it (since it is always modified) on every call. - * - * @param array $data - * @param string $extendingSection - * @param string $extendedSection - * @return void - */ - protected function processExtend(array &$data, $extendingSection, $extendedSection) - { - if (isset($this->processedExtends[$extendingSection])) { - throw new Exception\RuntimeException('Illegal circular inheritance detected'); - } - - $this->processedExtends[$extendingSection] = $extendedSection; - - if (isset($this->extends[$extendedSection])) { - $this->processExtends($data, $extendedSection, $this->extends[$extendedSection]); - } - - $data[$extendingSection] = array_replace_recursive( - $data[$extendedSection], - $data[$extendingSection] - ); - - unset($this->extends[$extendingSection]); - } - - /** - * Set whether to process extends. - * - * @param boolean $flag - * @return self - */ - public function setProcessExtendsFlag($flag) - { - $this->processExtends = (boolean) $flag; - return $this; - } - - /** - * Check whether to process extends. - * - * @return boolean - */ - public function shouldProcessExtends() - { - return $this->processExtends; - } -} diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php index 21daef9..292e2ba 100644 --- a/src/Reader/Ini.php +++ b/src/Reader/Ini.php @@ -21,7 +21,8 @@ namespace Zend\Config\Reader; -use Zend\Config\Exception; +use Zend\Config\Reader, + Zend\Config\Exception; /** * XML config reader. @@ -32,7 +33,7 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Ini extends AbstractReader +class Ini implements Reader { /** * Separator for nesting levels of configuration data identifiers. @@ -41,13 +42,6 @@ class Ini extends AbstractReader */ protected $nestSeparator = '.'; - /** - * Separator for parent section names. - * - * @var string - */ - protected $sectionSeparator = ':'; - /** * Directory of the file to process. * @@ -78,35 +72,13 @@ public function getNestSeparator() } /** - * Set section separator. - * - * @param string $separator - * @return self - */ - public function setSectionSeparator($separator) - { - $this->sectionSeparator = $separator; - return $this; - } - - /** - * Get section separator. + * fromFile(): defined by Reader interface. * - * @return string - */ - public function getSectionSeparator() - { - return $this->sectionSeparator; - } - - /** - * processFile(): defined by AbstractReader. - * - * @see AbstractReader::processFile() + * @see Reader::fromFile() * @param string $filename * @return array */ - protected function processFile($filename) + protected function fromFile($filename) { $this->directory = dirname($filename); @@ -114,15 +86,15 @@ protected function processFile($filename) } /** - * processString(): defined by AbstractReader. + * fromString(): defined by Reader interface. * - * @see AbstractReader::processString() + * @see Reader::fromString() * @param string $string * @return array */ - protected function processString($string) + protected function fromString($string) { - $this->directory = __DIR__; + $this->directory = null; return $this->process(parse_ini_string($string, true)); } @@ -135,28 +107,13 @@ protected function processString($string) */ protected function process(array $data) { - $this->extends = array(); - $config = array(); - - foreach ($data as $key => $value) { - $pieces = explode($this->sectionSeparator, $key); - $section = trim($pieces[0]); - - switch (count($pieces)) { - case 2: - $this->extends[$section] = trim($pieces[1]); - // Break intentionally omitted. - - case 1: - if (is_array($value)) { - $config[$section] = $this->processSection($value); - } else { - $config[$section] = $value; - } - break; - - default: - throw new Exception\RuntimeException(sprintf('Section "%s" may not extend multiple sexctions', $section)); + $config = array(); + + foreach ($data as $section => $value) { + if (is_array($value)) { + $config[$section] = $this->processSection($value); + } else { + $config[$section] = $value; } } @@ -208,11 +165,15 @@ protected function processKey($key, $value, array &$config) $this->processKey($pieces[1], $value, $config[$pieces[0]]); } else { if ($key === '@include') { + if ($this->directory === null) { + throw new Exception\RuntimeException('Cannot process @include statement for a string config'); + } + $reader = clone $this; - $include = $reader->fromFile($this->directory . '/' . $value)->toArray(); + $include = $reader->fromFile($this->directory . '/' . $value); $config = array_replace_recursive($config, $include); } else { - $config[$key] = str_replace('{DIR}', $this->directory, $value); + $config[$key] = $value; } } } diff --git a/src/Reader/Xml.php b/src/Reader/Xml.php index 8f1fc71..3d667eb 100644 --- a/src/Reader/Xml.php +++ b/src/Reader/Xml.php @@ -35,11 +35,6 @@ */ class Xml extends AbstractReader { - /** - * XML namespace for ZF-related tags and attributes. - */ - const XML_NAMESPACE = 'http://framework.zend.com/xml/zend-config-xml/1.0/'; - /** * XML Reader instance. * @@ -65,13 +60,13 @@ class Xml extends AbstractReader ); /** - * processFile(): defined by AbstractReader. + * fromFile(): defined by Reader interface. * - * @see AbstractReader::processFile() + * @see Reader::fromFile() * @param string $filename * @return array */ - protected function processFile($filename) + protected function fromFile($filename) { $this->reader = new XMLReader(); $this->reader->open($filename, null, LIBXML_XINCLUDE); @@ -82,18 +77,18 @@ protected function processFile($filename) } /** - * processString(): defined by AbstractReader. + * fromString(): defined by Reader interface. * - * @see AbstractReader::processString() + * @see Reader::fromString() * @param string $string * @return array */ - protected function processString($string) + protected function fromString($string) { $this->reader = new XMLReader(); $this->reader->xml($string, null, LIBXML_XINCLUDE); - $this->directory = __DIR__; + $this->directory = null; return $this->process(); } @@ -127,64 +122,30 @@ protected function processNextElement() } $attributes = $this->getAttributes(); - $depth = $this->reader->depth; $name = $this->reader->name; - if ($depth === 1 && isset($attributes['zf']['extends'])) { - $this->extends[$name] = $attributes['zf']['extends']; + if ($this->reader->isEmptyElement) { + $child = array(); + } else { + $child = $this->processNextElement(); } - if ($this->reader->namespaceURI === self::XML_NAMESPACE) { - switch ($this->reader->localName) { - case 'const': - if (!isset($attributes['default']['name'])) { - throw new Exception\RuntimeException('Misssing "name" attribute in "zf:const" node'); - } - - $constantName = $attributes['default']['name']; - - if (!defined($constantName)) { - throw new Exception\RuntimeException(sprintf('Constant with name "%s" was not defined', $constantName)); - } - - $text .= constant($constantName); - break; + if ($attributes) { + if (!is_array($child)) { + $child = array(); + } - case 'dir': - $text .= $this->directory; - break; + $child = array_merge($child, $attributes); + } - default: - throw new Exception\RuntimeException(sprintf('Unknown zf:node with name "%s" found', $name)); + if (isset($children[$name])) { + if (!is_array($children[$name]) || !$children[$name]) { + $children[$name] = array($children[$name]); } + + $children[$name][] = $child; } else { - if (isset($attributes['zf']['value'])) { - $children[$name] = $attributes['zf']['value']; - } else { - if ($this->reader->isEmptyElement) { - $child = array(); - } else { - $child = $this->processNextElement(); - } - - if ($attributes['default']) { - if (!is_array($child)) { - $child = array(); - } - - $child = array_merge($child, $attributes['default']); - } - - if (isset($children[$name])) { - if (!is_array($children[$name]) || !$children[$name]) { - $children[$name] = array($children[$name]); - } - - $children[$name][] = $child; - } else { - $children[$name] = $child; - } - } + $children[$name] = $child; } } elseif ($this->reader->nodeType === XMLReader::END_ELEMENT) { break; @@ -203,15 +164,11 @@ protected function processNextElement() */ protected function getAttributes() { - $attributes = array('default' => array(), 'zf' => array()); + $attributes = array(); if ($this->reader->hasAttributes) { while ($this->reader->moveToNextAttribute()) { - if ($this->reader->namespaceURI === self::XML_NAMESPACE) { - $attributes['zf'][$this->reader->localName] = $this->reader->value; - } else { - $attributes['default'][$this->reader->localName] = $this->reader->value; - } + $attributes[$this->reader->localName] = $this->reader->value; } $this->reader->moveToElement(); From da2ee69c84c616e073a94a0989a22b8bbc983813 Mon Sep 17 00:00:00 2001 From: Enrico Zimuel Date: Tue, 28 Feb 2012 19:13:12 +0100 Subject: [PATCH 16/18] Config refactor + unit test + doc --- src/Config.php | 6 +- src/Exception.php | 2 +- src/Exception/InvalidArgumentException.php | 2 +- src/Exception/RuntimeException.php | 2 +- src/Factory.php | 24 +- src/Processor.php | 2 +- src/Processor/Constant.php | 2 +- src/Processor/Filter.php | 37 +- src/Processor/Queue.php | 2 +- src/Processor/Token.php | 74 ++-- src/Processor/Translator.php | 8 +- src/Reader.php | 8 +- src/Reader/Ini.php | 38 +- src/Reader/Xml.php | 49 ++- src/Writer.php | 2 +- src/Writer/AbstractWriter.php | 23 +- src/Writer/Ini.php | 2 +- src/Writer/PhpArray.php | 2 +- src/Writer/Xml.php | 11 +- test/ConfigTest.php | 66 ++-- test/FactoryTest.php | 89 +++++ test/IniTest.php | 330 ---------------- test/JsonTest.php | 285 -------------- test/ProcessorTest.php | 190 +++++++-- test/Reader/AbstractReaderTestCase.php | 38 +- test/Reader/IniTest.php | 49 ++- test/Reader/TestAssets/Ini/constants.ini | 3 - test/Reader/TestAssets/Ini/current-dir.ini | 2 - test/Reader/TestAssets/Ini/invalid.ini | 2 + .../TestAssets/Ini/non-existent-constant.ini | 2 - test/Reader/TestAssets/Xml/constants.xml | 7 - test/Reader/TestAssets/Xml/current-dir.xml | 6 - test/Reader/TestAssets/Xml/include-base.xml | 3 +- test/Reader/TestAssets/Xml/invalid.xml | 4 + .../TestAssets/Xml/non-existent-constant.xml | 6 - test/Reader/XmlTest.php | 44 ++- test/TestAssets/Ini/include-base.ini | 2 + test/TestAssets/Ini/include-base2.ini | 2 + test/TestAssets/Xml/include-base.xml | 6 + test/TestAssets/Xml/include-base2.xml | 6 + test/Writer/AbstractWriterTestCase.php | 101 +++++ test/Writer/ArrayWriterTest.php | 114 ------ test/Writer/IniTest.php | 214 +--------- test/Writer/JsonTest.php | 150 ------- test/Writer/PhpArrayTest.php | 68 ++++ test/Writer/XmlTest.php | 198 +++------- test/Writer/YamlTest.php | 139 ------- test/Writer/files/PhpReader.php | 9 + test/Writer/files/allsections-pretty.json | 47 --- test/Writer/files/allsections.ini | 4 +- test/Writer/files/allsections.json | 1 - test/Writer/files/allsections.yaml | 36 -- test/XmlTest.php | 368 ------------------ test/YamlTest.php | 340 ---------------- test/_files/booleans.ini | 6 - 55 files changed, 827 insertions(+), 2406 deletions(-) create mode 100644 test/FactoryTest.php delete mode 100644 test/IniTest.php delete mode 100644 test/JsonTest.php delete mode 100644 test/Reader/TestAssets/Ini/constants.ini delete mode 100644 test/Reader/TestAssets/Ini/current-dir.ini create mode 100644 test/Reader/TestAssets/Ini/invalid.ini delete mode 100644 test/Reader/TestAssets/Ini/non-existent-constant.ini delete mode 100644 test/Reader/TestAssets/Xml/constants.xml delete mode 100644 test/Reader/TestAssets/Xml/current-dir.xml create mode 100644 test/Reader/TestAssets/Xml/invalid.xml delete mode 100644 test/Reader/TestAssets/Xml/non-existent-constant.xml create mode 100644 test/TestAssets/Ini/include-base.ini create mode 100644 test/TestAssets/Ini/include-base2.ini create mode 100644 test/TestAssets/Xml/include-base.xml create mode 100644 test/TestAssets/Xml/include-base2.xml create mode 100644 test/Writer/AbstractWriterTestCase.php delete mode 100644 test/Writer/ArrayWriterTest.php delete mode 100644 test/Writer/JsonTest.php create mode 100644 test/Writer/PhpArrayTest.php delete mode 100644 test/Writer/YamlTest.php create mode 100644 test/Writer/files/PhpReader.php delete mode 100644 test/Writer/files/allsections-pretty.json delete mode 100644 test/Writer/files/allsections.json delete mode 100644 test/Writer/files/allsections.yaml delete mode 100644 test/XmlTest.php delete mode 100644 test/YamlTest.php delete mode 100644 test/_files/booleans.ini diff --git a/src/Config.php b/src/Config.php index 407d990..14899f4 100644 --- a/src/Config.php +++ b/src/Config.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -183,7 +183,7 @@ public function toArray() } /** - * Support isset() overloading on PHP 5.1. + * isset() overloading * * @param string $name * @return boolean @@ -194,7 +194,7 @@ public function __isset($name) } /** - * Support unset() overloading on PHP 5.1. + * unset() overloading * * @param string $name * @return void diff --git a/src/Exception.php b/src/Exception.php index f5878d3..ad6677b 100644 --- a/src/Exception.php +++ b/src/Exception.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index 8900ee2..8298266 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php index 8c6ceb7..387678c 100644 --- a/src/Exception/RuntimeException.php +++ b/src/Exception/RuntimeException.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Factory.php b/src/Factory.php index 8dde955..6dd1e14 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -33,7 +33,7 @@ class Factory * * @var array */ - protected $readers = array(); + protected static $readers = array(); /** * Read a config from a file. @@ -41,8 +41,12 @@ class Factory * @param string $filename * @return array */ - public function fromFile($filename) + public static function fromFile($filename) { + if (!file_exists($filename)) { + throw new Exception\RuntimeException("The file $filename doesn't exists."); + } + $pathinfo = pathinfo($filename); switch (strtolower($pathinfo['extension'])) { @@ -51,19 +55,19 @@ public function fromFile($filename) break; case 'ini': - if (!isset($this->readers['ini'])) { - $this->readers['ini'] = new Reader\Ini(); + if (!isset(self::$readers['ini'])) { + self::$readers['ini'] = new Reader\Ini(); } - return $this->readers['ini']->fromFile($filename); + return self::$readers['ini']->fromFile($filename); break; case 'xml': - if (!isset($this->readers['xml'])) { - $this->readers['xml'] = new Reader\Xml(); + if (!isset(self::$readers['xml'])) { + self::$readers['xml'] = new Reader\Xml(); } - return $this->readers['xml']->fromFile($filename); + return self::$readers['xml']->fromFile($filename); break; } @@ -76,7 +80,7 @@ public function fromFile($filename) * @param array $files * @return array */ - public function fromFiles(array $files) + public static function fromFiles(array $files) { $config = array(); diff --git a/src/Processor.php b/src/Processor.php index e80f9bb..996260c 100644 --- a/src/Processor.php +++ b/src/Processor.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Processor/Constant.php b/src/Processor/Constant.php index 69f4793..5821e5a 100644 --- a/src/Processor/Constant.php +++ b/src/Processor/Constant.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Processor/Filter.php b/src/Processor/Filter.php index 6b35b5d..e27b1d2 100644 --- a/src/Processor/Filter.php +++ b/src/Processor/Filter.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -25,7 +25,7 @@ use Zend\Config\Config, Zend\Config\Processor, - Zend\Config\Exception\InvalidArgumentException, + Zend\Config\Exception, Zend\Filter\Filter as ZendFilter, \Traversable, \ArrayObject; @@ -59,7 +59,7 @@ public function __construct(ZendFilter $filter) */ public function getFilter() { - return $this->translator; + return $this->filter; } /** @@ -70,10 +70,16 @@ public function setFilter(ZendFilter $filter) $this->filter = $filter; } + /** + * Process + * + * @param Config $config + * @return Config + */ public function process(Config $config) { if ($config->isReadOnly()) { - throw new InvalidArgumentException('Cannot parse config because it is read-only'); + throw new Exception\InvalidArgumentException('Cannot parse config because it is read-only'); } /** @@ -90,15 +96,14 @@ public function process(Config $config) return $config; } - /** - * Process a single value - * - * @param $value - * @return mixed - */ - public function processValue($value) - { - return $this->filter->filter($value); - } - -} + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function processValue($value) + { + return $this->filter->filter($value); + } +} \ No newline at end of file diff --git a/src/Processor/Queue.php b/src/Processor/Queue.php index 42d1169..8cb3029 100644 --- a/src/Processor/Queue.php +++ b/src/Processor/Queue.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Processor/Token.php b/src/Processor/Token.php index 23fbc9d..0264941 100644 --- a/src/Processor/Token.php +++ b/src/Processor/Token.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -25,7 +25,7 @@ use Zend\Config\Config, Zend\Config\Processor, - Zend\Config\Exception\InvalidArgumentException, + Zend\Config\Exception, \Traversable, \ArrayObject; @@ -142,7 +142,7 @@ public function setTokens($tokens) $this->tokens[$key] = $val; } } else { - throw new InvalidArgumentException('Cannot use ' . gettype($tokens) . ' as token registry.'); + throw new Exception\InvalidArgumentException('Cannot use ' . gettype($tokens) . ' as token registry.'); } // reset map @@ -168,7 +168,7 @@ public function getTokens() public function addToken($token, $value) { if (!is_scalar($token)) { - throw new InvalidArgumentException('Cannot use ' . gettype($token) . ' as token name.'); + throw new Exception\InvalidArgumentException('Cannot use ' . gettype($token) . ' as token name.'); } $this->tokens[$token] = $value; @@ -188,24 +188,31 @@ public function setToken($token, $value) return $this->addToken($token, $value); } - /** - * Build replacement map - */ - protected function buildMap(){ - if (!$this->suffix && !$this->prefix) { - $this->map = $this->tokens; - } else { - $this->map = array(); - foreach ($this->tokens as $token => $value) { - $this->map[$this->prefix . $token . $this->suffix] = $value; - } - } + /** + * Build replacement map + */ + protected function buildMap() + { + if (!$this->suffix && !$this->prefix) { + $this->map = $this->tokens; + } else { + $this->map = array(); + foreach ($this->tokens as $token => $value) { + $this->map[$this->prefix . $token . $this->suffix] = $value; + } } + } + /** + * Process + * + * @param Config $config + * @return Config + */ public function process(Config $config) { if ($config->isReadOnly()) { - throw new InvalidArgumentException('Cannot parse config because it is read-only'); + throw new Exception\InvalidArgumentException('Cannot parse config because it is read-only'); } if ($this->map === null) { @@ -228,20 +235,19 @@ public function process(Config $config) return $config; } - /** - * Process a single value - * - * @param $value - * @return mixed - */ - public function processValue($value) - { - if ($this->map === null) { - $this->buildMap(); - } - $keys = array_keys($this->map); - $values = array_values($this->map); - return str_replace($keys,$values,$value); - } - -} + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function processValue($value) + { + if ($this->map === null) { + $this->buildMap(); + } + $keys = array_keys($this->map); + $values = array_values($this->map); + 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 19362d1..74c1080 100644 --- a/src/Processor/Translator.php +++ b/src/Processor/Translator.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -53,9 +53,9 @@ class Translator implements Processor * Translator uses the supplied Zend\Translator\Translator to find and * translate language strings in config. * - * @param \Zend\Translator\Translator $translator - * @param \Zend\Locale\Locale|string|null $locale - * @return \Zend\Config\Processor\Translator + * @param ZendTranslator $translator + * @param Locale|string|null $locale + * @return ZendTranslator */ public function __construct(ZendTranslator $translator, $locale = null) { diff --git a/src/Reader.php b/src/Reader.php index 665ebe7..622ade7 100644 --- a/src/Reader.php +++ b/src/Reader.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -29,7 +29,7 @@ interface Reader { /** - * Read from a file and create a config object. + * Read from a file and create an array * * @param string $filename * @return array @@ -37,10 +37,10 @@ interface Reader public function fromFile($filename); /** - * Read from a string and create a config object. + * Read from a string and create an array * * @param string $string - * @return array + * @return array|boolean */ public function fromString($string); } diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php index 292e2ba..a5ce4cb 100644 --- a/src/Reader/Ini.php +++ b/src/Reader/Ini.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Config * @subpackage Reader - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -78,11 +78,25 @@ public function getNestSeparator() * @param string $filename * @return array */ - protected function fromFile($filename) + public function fromFile($filename) { + if (!file_exists($filename)) { + throw new Exception\RuntimeException("The file $filename doesn't exists."); + } $this->directory = dirname($filename); - return $this->process(parse_ini_file($filename, true)); + set_error_handler( + function($error, $message = '', $file = '', $line = 0) use ($filename) { + throw new Exception\RuntimeException(sprintf( + 'Error reading INI file "%s": %s', + $filename, $message + ), $error); + }, E_WARNING + ); + $ini = parse_ini_file($filename, true); + restore_error_handler(); + + return $this->process($ini); } /** @@ -92,11 +106,25 @@ protected function fromFile($filename) * @param string $string * @return array */ - protected function fromString($string) + public function fromString($string) { + if (empty($string)) { + return array(); + } $this->directory = null; - return $this->process(parse_ini_string($string, true)); + set_error_handler( + function($error, $message = '', $file = '', $line = 0) { + throw new Exception\RuntimeException(sprintf( + 'Error reading INI string: %s', + $message + ), $error); + }, E_WARNING + ); + $ini = parse_ini_string($string, true); + restore_error_handler(); + + return $this->process($ini); } /** diff --git a/src/Reader/Xml.php b/src/Reader/Xml.php index 3d667eb..ee4f910 100644 --- a/src/Reader/Xml.php +++ b/src/Reader/Xml.php @@ -15,13 +15,14 @@ * @category Zend * @package Zend_Config * @subpackage Reader - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Config\Reader; use XMLReader, + Zend\Config\Reader, Zend\Config\Exception; /** @@ -33,7 +34,7 @@ * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ -class Xml extends AbstractReader +class Xml implements Reader { /** * XML Reader instance. @@ -66,14 +67,29 @@ class Xml extends AbstractReader * @param string $filename * @return array */ - protected function fromFile($filename) + public function fromFile($filename) { + if (!file_exists($filename)) { + throw new Exception\RuntimeException("The file $filename doesn't exists."); + } $this->reader = new XMLReader(); - $this->reader->open($filename, null, LIBXML_XINCLUDE); + + $this->reader->open($filename, null, LIBXML_XINCLUDE); $this->directory = dirname($filename); - return $this->process(); + set_error_handler( + function($error, $message = '', $file = '', $line = 0) use ($filename) { + throw new Exception\RuntimeException(sprintf( + 'Error reading XML file "%s": %s', + $filename, $message + ), $error); + }, E_WARNING + ); + $return = $this->process(); + restore_error_handler(); + + return $return; } /** @@ -83,14 +99,29 @@ protected function fromFile($filename) * @param string $string * @return array */ - protected function fromString($string) + public function fromString($string) { + if (empty($string)) { + return array(); + } $this->reader = new XMLReader(); + $this->reader->xml($string, null, LIBXML_XINCLUDE); $this->directory = null; - return $this->process(); + set_error_handler( + function($error, $message = '', $file = '', $line = 0) { + throw new Exception\RuntimeException(sprintf( + 'Error reading XML string: %s', + $message + ), $error); + }, E_WARNING + ); + $return = $this->process(); + restore_error_handler(); + + return $return; } /** @@ -100,8 +131,6 @@ protected function fromString($string) */ protected function process() { - $this->extends = array(); - return $this->processNextElement(); } @@ -153,7 +182,7 @@ protected function processNextElement() $text .= $this->reader->value; } } - + return $children ?: $text; } diff --git a/src/Writer.php b/src/Writer.php index 7fe55f3..c6d711c 100644 --- a/src/Writer.php +++ b/src/Writer.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php index eacecfe..c3d6fa4 100644 --- a/src/Writer/AbstractWriter.php +++ b/src/Writer/AbstractWriter.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -22,7 +22,9 @@ use Zend\Config\Writer, Zend\Config\Exception, - Zend\Stdlib\IteratorToArray; + Zend\Config\Config, + Zend\Stdlib\IteratorToArray, + Traversable; /** * @category Zend @@ -43,17 +45,26 @@ abstract class AbstractWriter implements Writer */ public function toFile($filename, $config, $exclusiveLock = true) { - if (!is_writable($filename)) { - throw new Exception\RuntimeException(sprintf('File "%s" is not writable', $filename)); + if (empty($filename)) { + throw new Exception\InvalidArgumentException('No file name specified'); } - + $flags = 0; if ($exclusiveLock) { $flags |= LOCK_EX; } - + + set_error_handler( + function($error, $message = '', $file = '', $line = 0) use ($filename) { + throw new Exception\RuntimeException(sprintf( + 'Error writing to "%s": %s', + $filename, $message + ), $error); + }, E_WARNING + ); file_put_contents($filename, $this->toString($config), $exclusiveLock); + restore_error_handler(); } /** diff --git a/src/Writer/Ini.php b/src/Writer/Ini.php index 3c85a17..19210e3 100644 --- a/src/Writer/Ini.php +++ b/src/Writer/Ini.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Writer/PhpArray.php b/src/Writer/PhpArray.php index feef9a1..565cf3d 100644 --- a/src/Writer/PhpArray.php +++ b/src/Writer/PhpArray.php @@ -14,7 +14,7 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ diff --git a/src/Writer/Xml.php b/src/Writer/Xml.php index 949de19..38090e5 100644 --- a/src/Writer/Xml.php +++ b/src/Writer/Xml.php @@ -14,14 +14,13 @@ * * @category Zend * @package Zend_Config - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Config\Writer; -use Zend\Config\Reader\Xml, - Zend\Config\Exception, +use Zend\Config\Exception, XMLWriter; /** @@ -79,7 +78,7 @@ protected function addBranch($branchName, array $config, XMLWriter $writer) if (is_numeric($key)) { $branchType = 'numeric'; } else { - $writer->addElement($branchName); + $writer->startElement($branchName); $branchType = 'string'; } } else if ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) { @@ -88,13 +87,13 @@ protected function addBranch($branchName, array $config, XMLWriter $writer) if ($branchType === 'numeric') { if (is_array($value)) { - $this->addBranch($value, $data, $writer); + $this->addBranch($value, $value, $writer); } else { $writer->writeElement($branchName, (string) $value); } } else { if (is_array($value)) { - $this->addBranch($key, $data, $writer); + $this->addBranch($key, $value, $writer); } else { $writer->writeElement($key, (string) $value); } diff --git a/test/ConfigTest.php b/test/ConfigTest.php index 3e7cf2e..b2ffe3d 100644 --- a/test/ConfigTest.php +++ b/test/ConfigTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -33,13 +33,13 @@ */ class ConfigTest extends \PHPUnit_Framework_TestCase { - protected $_iniFileConfig; - protected $_iniFileNested; + protected $iniFileConfig; + protected $iniFileNested; public function setUp() { // Arrays representing common config configurations - $this->_all = array( + $this->all = array( 'hostname' => 'all', 'name' => 'thisname', 'db' => array( @@ -55,12 +55,12 @@ public function setUp() ) ); - $this->_numericData = array( + $this->numericData = array( 0 => 34, 1 => 'test', ); - $this->_menuData1 = array( + $this->menuData1 = array( 'button' => array( 'b0' => array( 'L1' => 'button0-1', @@ -77,14 +77,14 @@ public function setUp() ) ); - $this->_leadingdot = array('.test' => 'dot-test'); - $this->_invalidkey = array(' ' => 'test', ''=>'test2'); + $this->leadingdot = array('.test' => 'dot-test'); + $this->invalidkey = array(' ' => 'test', ''=>'test2'); } public function testLoadSingleSection() { - $config = new Config($this->_all, false); + $config = new Config($this->all, false); $this->assertEquals('all', $config->hostname); $this->assertEquals('live', $config->db->name); @@ -94,7 +94,7 @@ public function testLoadSingleSection() public function testIsset() { - $config = new Config($this->_all, false); + $config = new Config($this->all, false); $this->assertFalse(isset($config->notarealkey)); $this->assertTrue(isset($config->hostname)); // top level @@ -103,7 +103,7 @@ public function testIsset() public function testModification() { - $config = new Config($this->_all, true); + $config = new Config($this->all, true); // overwrite an existing key $this->assertEquals('thisname', $config->name); @@ -123,35 +123,35 @@ public function testModification() public function testNoModifications() { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'is read only'); - $config = new Config($this->_all); + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Config is read only'); + $config = new Config($this->all); $config->hostname = 'test'; } public function testNoNestedModifications() { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'is read only'); - $config = new Config($this->_all); + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Config is read only'); + $config = new Config($this->all); $config->db->host = 'test'; } public function testNumericKeys() { - $data = new Config($this->_numericData); + $data = new Config($this->numericData); $this->assertEquals('test', $data->{1}); $this->assertEquals(34, $data->{0}); } public function testCount() { - $data = new Config($this->_menuData1); + $data = new Config($this->menuData1); $this->assertEquals(3, count($data->button)); } public function testIterator() { // top level - $config = new Config($this->_all); + $config = new Config($this->all); $var = ''; foreach ($config as $key=>$value) { if (is_string($value)) { @@ -168,7 +168,7 @@ public function testIterator() $this->assertContains('key = host, value = 127.0.0.1', $var); // 2 nests - $config = new Config($this->_menuData1); + $config = new Config($this->menuData1); $var = ''; foreach ($config->button->b1 as $key=>$value) { $var .= "\nkey = $key, value = $value"; @@ -178,7 +178,7 @@ public function testIterator() public function testArray() { - $config = new Config($this->_all); + $config = new Config($this->all); ob_start(); print_r($config->toArray()); @@ -192,8 +192,8 @@ public function testArray() public function testErrorWriteToReadOnly() { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'read only'); - $config = new Config($this->_all); + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Config is read only'); + $config = new Config($this->all); $config->test = '32'; } @@ -236,14 +236,14 @@ public function testZF402() public function testZf1019_HandlingInvalidKeyNames() { - $config = new Config($this->_leadingdot); + $config = new Config($this->leadingdot); $array = $config->toArray(); $this->assertContains('dot-test', $array['.test']); } public function testZF1019_EmptyKeys() { - $config = new Config($this->_invalidkey); + $config = new Config($this->invalidkey); $array = $config->toArray(); $this->assertContains('test', $array[' ']); $this->assertContains('test', $array['']); @@ -251,7 +251,7 @@ public function testZF1019_EmptyKeys() public function testZF1417_DefaultValues() { - $config = new Config($this->_all); + $config = new Config($this->all); $value = $config->get('notthere', 'default'); $this->assertTrue($value === 'default'); $this->assertTrue($config->notThere === null); @@ -261,7 +261,7 @@ public function testZF1417_DefaultValues() public function testUnsetException() { // allow modifications is off - expect an exception - $config = new Config($this->_all, false); + $config = new Config($this->all, false); $this->assertTrue(isset($config->hostname)); // top level @@ -272,7 +272,7 @@ public function testUnsetException() public function testUnset() { // allow modifications is on - $config = new Config($this->_all, true); + $config = new Config($this->all, true); $this->assertTrue(isset($config->hostname)); $this->assertTrue(isset($config->db->name)); @@ -319,7 +319,7 @@ public function testMerge() public function testArrayAccess() { - $config = new Config($this->_all, true); + $config = new Config($this->all, true); $this->assertEquals('thisname', $config['name']); $config['name'] = 'anothername'; @@ -370,7 +370,7 @@ public function testSetReadOnly() $config->b = 'b'; $config->setReadOnly(); - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'is read only'); + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Config is read only'); $config->c = 'c'; } @@ -508,12 +508,12 @@ public function testUnsettingLastElementDuringForeachDoesNotSkipAnElement() */ public function testSetReadOnlyAppliesToChildren() { - $config = new Config($this->_all, true); + $config = new Config($this->all, true); $config->setReadOnly(); - $this->assertTrue($config->readOnly()); - $this->assertTrue($config->one->readOnly(), 'First level children are writable'); - $this->assertTrue($config->one->two->readOnly(), 'Second level children are writable'); + $this->assertTrue($config->isReadOnly()); + $this->assertTrue($config->one->isReadOnly(), 'First level children are writable'); + $this->assertTrue($config->one->two->isReadOnly(), 'Second level children are writable'); } public function testZF6995_toArrayDoesNotDisturbInternalIterator() diff --git a/test/FactoryTest.php b/test/FactoryTest.php new file mode 100644 index 0000000..ddeef0b --- /dev/null +++ b/test/FactoryTest.php @@ -0,0 +1,89 @@ +assertEquals('bar', $config['base']['foo']); + } + + public function testFromXml() + { + $config = Factory::fromFile(__DIR__ . '/TestAssets/Xml/include-base.xml'); + + $this->assertEquals('bar', $config['base']['foo']); + } + + public function testFromIniFiles() + { + $files = array ( + __DIR__ . '/TestAssets/Ini/include-base.ini', + __DIR__ . '/TestAssets/Ini/include-base2.ini' + ); + + $config = Factory::fromFiles($files); + $this->assertEquals('bar', $config['base']['foo']); + $this->assertEquals('baz', $config['test']['bar']); + } + + public function testFromXmlFiles() + { + $files = array ( + __DIR__ . '/TestAssets/Xml/include-base.xml', + __DIR__ . '/TestAssets/Xml/include-base2.xml' + ); + + $config = Factory::fromFiles($files); + $this->assertEquals('bar', $config['base']['foo']); + $this->assertEquals('baz', $config['test']['bar']); + } + + public function testFromIniAndXmlFiles() + { + $files = array ( + __DIR__ . '/TestAssets/Ini/include-base.ini', + __DIR__ . '/TestAssets/Xml/include-base2.xml' + ); + + $config = Factory::fromFiles($files); + $this->assertEquals('bar', $config['base']['foo']); + $this->assertEquals('baz', $config['test']['bar']); + } +} + diff --git a/test/IniTest.php b/test/IniTest.php deleted file mode 100644 index 1dbc363..0000000 --- a/test/IniTest.php +++ /dev/null @@ -1,330 +0,0 @@ -_iniFileConfig = __DIR__ . '/_files/config.ini'; - $this->_iniFileAllSectionsConfig = __DIR__ . '/_files/allsections.ini'; - $this->_iniFileCircularConfig = __DIR__ . '/_files/circular.ini'; - $this->_iniFileMultipleInheritanceConfig = __DIR__ . '/_files/multipleinheritance.ini'; - $this->_iniFileSeparatorConfig = __DIR__ . '/_files/separator.ini'; - $this->_nonReadableConfig = __DIR__ . '/_files/nonreadable.ini'; - $this->_iniFileNoSectionsConfig = __DIR__ . '/_files/nosections.ini'; - $this->_iniFileInvalid = __DIR__ . '/_files/invalid.ini'; - $this->_iniFileBooleans = __DIR__ . '/_files/booleans.ini'; - } - - public function testLoadSingleSection() - { - $config = new Ini($this->_iniFileConfig, 'all'); - - $this->assertEquals('all', $config->hostname); - $this->assertEquals('live', $config->db->name); - $this->assertEquals('multi', $config->one->two->three); - $this->assertNull(@$config->nonexistent); // property doesn't exist - } - - public function testSectionInclude() - { - $config = new Ini($this->_iniFileConfig, 'staging'); - - $this->assertEquals('', $config->debug); // only in staging - $this->assertEquals('thisname', $config->name); // only in all - $this->assertEquals('username', $config->db->user); // only in all (nested version) - $this->assertEquals('staging', $config->hostname); // inherited and overridden - $this->assertEquals('dbstaging', $config->db->name); // inherited and overridden - } - - public function testTrueValues() - { - $config = new Ini($this->_iniFileConfig, 'debug'); - - $this->assertInternalType('string', $config->debug); - $this->assertEquals('1', $config->debug); - $this->assertInternalType('string', $config->values->changed); - $this->assertEquals('1', $config->values->changed); - } - - public function testEmptyValues() - { - $config = new Ini($this->_iniFileConfig, 'debug'); - - $this->assertInternalType('string', $config->special->no); - $this->assertEquals('', $config->special->no); - $this->assertInternalType('string', $config->special->null); - $this->assertEquals('', $config->special->null); - $this->assertInternalType('string', $config->special->false); - $this->assertEquals('', $config->special->false); - } - - public function testMultiDepthExtends() - { - $config = new Ini($this->_iniFileConfig, 'other_staging'); - - $this->assertEquals('otherStaging', $config->only_in); // only in other_staging - $this->assertEquals('', $config->debug); // 1 level down: only in staging - $this->assertEquals('thisname', $config->name); // 2 levels down: only in all - $this->assertEquals('username', $config->db->user); // 2 levels down: only in all (nested version) - $this->assertEquals('staging', $config->hostname); // inherited from two to one and overridden - $this->assertEquals('dbstaging', $config->db->name); // inherited from two to one and overridden - $this->assertEquals('anotherpwd', $config->db->pass); // inherited from two to other_staging and overridden - } - - public function testErrorNoExtendsSection() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'cannot be found'); - $config = new Ini($this->_iniFileConfig, 'extendserror'); - } - - public function testInvalidKeys() - { - $sections = array('leadingdot', 'onedot', 'twodots', 'threedots', 'trailingdot'); - foreach ($sections as $section) { - try { - $config = new Ini($this->_iniFileConfig, $section); - $this->fail('An expected Zend\\Config\\Exception has not been raised'); - } catch (\Zend\Config\Exception\RuntimeException $expected) { - $this->assertContains('Invalid key', $expected->getMessage()); - } - } - } - - /** - * @group ZF-426 - */ - public function testErrorCreateSubKey() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Cannot create sub-key for'); - $config = new Ini($this->_iniFileConfig, 'zf426'); - } - - /** - * @group ZF-413 - */ - public function testMultiSections() - { - $config = new Ini($this->_iniFileAllSectionsConfig, array('staging','other_staging')); - - $this->assertEquals('otherStaging', $config->only_in); - $this->assertEquals('staging', $config->hostname); - - } - - /** - * @group ZF-413 - */ - public function testAllSections() - { - $config = new Ini($this->_iniFileAllSectionsConfig, null); - $this->assertEquals('otherStaging', $config->other_staging->only_in); - $this->assertEquals('staging', $config->staging->hostname); - } - - /** - * @group ZF-414 - */ - public function testGetSectionNameAndAreAllSectionsLoaded() - { - $config = new Ini($this->_iniFileAllSectionsConfig, null); - $this->assertEquals(null, $config->getSectionName()); - $this->assertEquals(true, $config->areAllSectionsLoaded()); - - $config = new Ini($this->_iniFileAllSectionsConfig, 'all'); - $this->assertEquals('all', $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - - $config = new Ini($this->_iniFileAllSectionsConfig, array('staging','other_staging')); - $this->assertEquals(array('staging','other_staging'), $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - } - - /** - * @group ZF-415 - */ - public function testErrorCircularInheritance() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'circular inheritance'); - $config = new Ini($this->_iniFileCircularConfig, null); - } - - public function testErrorNoFile() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Filename is not set'); - $config = new Ini('',''); - } - - public function testErrorFileNotFound() - { - try { - $file = '/tmp/notFoundFile'; - $config = new Ini($file); - $this->fail('Missing expected exception'); - } catch (\Zend\Config\Exception\RuntimeException $e) { - // read exception stack - do { - $stack[] = $e; - } while ( ($e = $e->getPrevious()) ); - - // test two thrown exceptions - $this->assertEquals(2, count($stack)); - $this->assertContains($file, $stack[0]->getMessage()); - $this->assertContains('parse_ini_file', $stack[1]->getMessage()); - } - } - - public function testErrorMultipleExensions() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'may not extend multiple sections'); - $config = new Ini($this->_iniFileMultipleInheritanceConfig, 'three'); - zend::dump($config); - } - - public function testErrorNoSectionFound() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'cannot be found'); - $config = new Ini($this->_iniFileConfig,'notthere'); - } - - public function testErrorNoSectionFoundWhenMultipleSectionsProvided() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'cannot be found'); - $config = new Ini($this->_iniFileConfig,array('all', 'notthere')); - } - - /** - * @group ZF-3196 - * @group ZF2-13 - */ - public function testErrorInvalidIniFile() - { - try { - $config = new Ini($this->_iniFileInvalid); - $this->fail('Missing expected exception'); - } catch (\Zend\Config\Exception\RuntimeException $e) { - // read exception stack - do { - $stack[] = $e; - } while ( ($e = $e->getPrevious()) ); - - // test three thrown exceptions - $this->assertEquals(3, count($stack)); - $this->assertContains($this->_iniFileInvalid, $stack[0]->getMessage()); - $this->assertContains('syntax error', $stack[1]->getMessage()); - $this->assertContains('deprecated', $stack[2]->getMessage()); - } - } - - /** - * @group ZF-2508 - */ - public function testNoSections() - { - $config = new Ini($this->_iniFileNoSectionsConfig); - - $this->assertEquals('all', $config->hostname); - $this->assertEquals('two', $config->one->two); - $this->assertEquals('4', $config->one->three->four); - $this->assertEquals('5', $config->one->three->five); - } - - /** - * @group ZF-2843 - */ - public function testNoSectionNoTree() - { - $filename = __DIR__ . '/_files/zf2843.ini'; - $config = new Ini($filename, null, array('nestSeparator' => '.')); - - $this->assertEquals('123', $config->abc); - $this->assertEquals('jkl', $config->ghi); - } - - /** - * @group ZF-8159 - */ - public function testLoadMultipleSections() - { - $config = new Ini( - __DIR__ . '/_files/zf8159.ini', - array('first', 'second') - ); - - $this->assertTrue(isset( - $config->user->login->elements->password - )); - - $this->assertEquals( - 'password', - $config->user->login->elements->password->type - ); - } - - /** - * @group ZF-5800 - */ - public function testArraysOfKeysCreatedUsingAttributesAndKeys() - { - $filename = __DIR__ . '/_files/zf5800.ini'; - $config = new Ini($filename, 'dev'); - $this->assertEquals('nice.guy@company.com', $config->receiver->{0}->mail); - $this->assertEquals('1', $config->receiver->{0}->html); - $this->assertNull($config->receiver->mail); - } - - /** - * @group ZF-6508 - */ - public function testPreservationOfIntegerKeys() - { - $filename = __DIR__ . '/_files/zf6508.ini'; - $config = new Ini($filename, 'all'); - $this->assertEquals(true, isset($config->{1002})); - - } - - public function testBooleans() - { - $config = new Ini($this->_iniFileBooleans, 'all'); - $this->assertEquals(true, (bool)$config->trueValue); - $this->assertEquals(false, (bool)$config->falseValue); - $this->assertEquals(true, (bool)$config->trueString); - $this->assertEquals(false, (bool)$config->falseString); - } - -} diff --git a/test/JsonTest.php b/test/JsonTest.php deleted file mode 100644 index 1c1c098..0000000 --- a/test/JsonTest.php +++ /dev/null @@ -1,285 +0,0 @@ -_iniFileConfig = __DIR__ . '/_files/config.json'; - $this->_iniFileAllSectionsConfig = __DIR__ . '/_files/allsections.json'; - $this->_iniFileCircularConfig = __DIR__ . '/_files/circular.json'; - $this->_iniFileMultipleInheritanceConfig = __DIR__ . '/_files/multipleinheritance.json'; - $this->_nonReadableConfig = __DIR__ . '/_files/nonreadable.json'; - $this->_iniFileNoSectionsConfig = __DIR__ . '/_files/nosections.json'; - $this->_iniFileInvalid = __DIR__ . '/_files/invalid.json'; - } - - public function testLoadSingleSection() - { - $config = new JsonConfig($this->_iniFileConfig, 'all'); - - $this->assertEquals('all', $config->hostname); - $this->assertEquals('live', $config->db->name); - $this->assertEquals('multi', $config->one->two->three); - $this->assertNull(@$config->nonexistent); // property doesn't exist - } - - public function testSectionInclude() - { - $config = new JsonConfig($this->_iniFileConfig, 'staging'); - - $this->assertEquals('', $config->debug); // only in staging - $this->assertEquals('thisname', $config->name); // only in all - $this->assertEquals('username', $config->db->user); // only in all (nested version) - $this->assertEquals('dbstaging', $config->db->name); // inherited and overridden - } - - public function testTrueValues() - { - $config = new JsonConfig($this->_iniFileConfig, 'debug'); - - $this->assertTrue($config->debug); - $this->assertTrue($config->values->changed); - } - - public function testEmptyValues() - { - $config = new JsonConfig($this->_iniFileConfig, 'debug'); - - $this->assertInternalType('string', $config->special->no); - $this->assertEquals('no', $config->special->no); - $this->assertNull($config->special->null); - $this->assertFalse($config->special->false); - } - - /** - * @group review - */ - public function testMultiDepthExtends() - { - $config = new JsonConfig($this->_iniFileConfig, 'other_staging'); - - $this->assertEquals('otherStaging', $config->only_in); // only in other_staging - $this->assertEquals('', $config->debug); // 1 level down: only in staging - $this->assertEquals('thisname', $config->name); // 2 levels down: only in all - $this->assertEquals('username', $config->db->user); // 2 levels down: only in all (nested version) - $this->assertEquals('staging', $config->hostname); // inherited from two to one and overridden - $this->assertEquals('dbstaging', $config->db->name); // inherited from two to one and overridden - $this->assertEquals('anotherpwd', $config->db->pass); // inherited from two to other_staging and overridden - } - - public function testRaisesExceptionWhenSectionNotFound() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'cannot be found'); - $config = new JsonConfig($this->_iniFileConfig, 'extendserror'); - } - - public function testRetrievesAndMergesMultipleSections() - { - $config = new JsonConfig($this->_iniFileAllSectionsConfig, array('staging','other_staging')); - - $this->assertEquals('otherStaging', $config->only_in); - $this->assertEquals('dbstaging', $config->db->name); - - } - - public function testCanRetrieveAllSections() - { - $config = new JsonConfig($this->_iniFileAllSectionsConfig, null); - $this->assertEquals('otherStaging', $config->other_staging->only_in); - $this->assertEquals('dbstaging', $config->staging->db->name); - } - - public function testAllowsLoadingAllSectionsOrSomeSectionsSelectively() - { - $config = new JsonConfig($this->_iniFileAllSectionsConfig, null); - $this->assertEquals(null, $config->getSectionName()); - $this->assertEquals(true, $config->areAllSectionsLoaded()); - - $config = new JsonConfig($this->_iniFileAllSectionsConfig, 'all'); - $this->assertEquals('all', $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - - $config = new JsonConfig($this->_iniFileAllSectionsConfig, array('staging','other_staging')); - $this->assertEquals(array('staging','other_staging'), $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - } - - public function testDetectsCircularInheritance() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'circular inheritance'); - $config = new JsonConfig($this->_iniFileCircularConfig, null); - } - - public function testRaisesErrorWhenNoFileProvided() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'not set'); - $config = new JsonConfig('',''); - } - - public function testRaisesErrorOnAttemptsToExtendMultipleSectionsAtOnce() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Invalid'); - $config = new JsonConfig($this->_iniFileMultipleInheritanceConfig, 'multiinherit'); - } - - public function testRaisesErrorWhenSectionNotFound() - { - try { - $config = new JsonConfig($this->_iniFileConfig,array('all', 'notthere')); - $this->fail('An expected exception has not been raised'); - } catch (\Zend\Config\Exception $expected) { - $this->assertContains('cannot be found', $expected->getMessage()); - } - - try { - $config = new JsonConfig($this->_iniFileConfig,'notthere'); - $this->fail('An expected exception has not been raised'); - } catch (\Zend\Config\Exception $expected) { - $this->assertContains('cannot be found', $expected->getMessage()); - } - } - - public function testCanLoadConfigWithNoSections() - { - $config = new JsonConfig($this->_iniFileNoSectionsConfig); - - $this->assertEquals('all', $config->hostname); - $this->assertEquals('two', $config->one->two); - $this->assertEquals('4', $config->one->three->four); - $this->assertEquals('5', $config->one->three->five); - } - - public function testRaisesExceptionOnInvalidJsonMarkup() - { - $this->setExpectedException('Zend\Json\Exception', 'Syntax error'); - $config = new JsonConfig($this->_iniFileInvalid); - } - - public function testOptionsPassedAreHonored() - { - $config = new JsonConfig($this->_iniFileConfig, 'staging', array( - 'skipExtends' => true, - 'allowModifications' => true, - 'bar' => 'foo', // ignored - )); - $this->assertNull($config->name); // demonstrates extends were skipped - $config->foo = 'bar'; - $this->assertEquals('bar', $config->foo); // demonstrates modifications were made - } - - public function testZf2StyleOptionsAreHonored() - { - $config = new JsonConfig($this->_iniFileConfig, 'staging', array( - 'skip_extends' => true, - 'allow_modifications' => true, - 'bar' => 'foo', // ignored - )); - $this->assertNull($config->name); // demonstrates extends were skipped - $config->foo = 'bar'; - $this->assertEquals('bar', $config->foo); // demonstrates modifications were made - } - - public function testAllowsPassingJsonStringsToConstructor() - { - $json =<<assertTrue($config->debug); - $this->assertEquals('bar', $config->foo); - $this->assertNull($config->bar); - } - - public function testProcessesSectionsWithSingleValues() - { - $json = '{"all":"values"}'; - $config = new JsonConfig($json, 'all'); - $this->assertEquals('values', $config->all); - } - - public function testReplacesConstantNamesWithValuesByDefault() - { - if (!defined('ZEND_CONFIG_JSON_ENV')) { - define('ZEND_CONFIG_JSON_ENV', 'testing'); - } - if (!defined('ZEND_CONFIG_JSON_ENV_PATH')) { - define('ZEND_CONFIG_JSON_ENV_PATH', dirname(__FILE__)); - } - if (!defined('ZEND_CONFIG_JSON_ENV_INT')) { - define('ZEND_CONFIG_JSON_ENV_INT', 42); - } - $json = '{"env":"ZEND_CONFIG_JSON_ENV","path":"ZEND_CONFIG_JSON_ENV_PATH/tests","int":ZEND_CONFIG_JSON_ENV_INT}'; - $config = new JsonConfig($json); - $this->assertEquals(ZEND_CONFIG_JSON_ENV, $config->env); - $this->assertEquals(ZEND_CONFIG_JSON_ENV_PATH . '/tests', $config->path); - $this->assertEquals(ZEND_CONFIG_JSON_ENV_INT, $config->int); - } - - public function testCanIgnoreConstantsWhenParsing() - { - if (!defined('ZEND_CONFIG_JSON_ENV')) { - define('ZEND_CONFIG_JSON_ENV', 'testing'); - } - $json = '{"env":"ZEND_CONFIG_JSON_ENV"}'; - $config = new JsonConfig($json, null, array('ignore_constants' => true)); - $this->assertEquals('ZEND_CONFIG_JSON_ENV', $config->env); - } - - public function testIgnoringConstantsCanLeadToParseErrors() - { - if (!defined('ZEND_CONFIG_JSON_ENV')) { - define('ZEND_CONFIG_JSON_ENV', 'testing'); - } - if (!defined('ZEND_CONFIG_JSON_ENV_PATH')) { - define('ZEND_CONFIG_JSON_ENV_PATH', dirname(__FILE__)); - } - if (!defined('ZEND_CONFIG_JSON_ENV_INT')) { - define('ZEND_CONFIG_JSON_ENV_INT', 42); - } - $json = '{"env":"ZEND_CONFIG_JSON_ENV","path":"ZEND_CONFIG_JSON_ENV_PATH/tests","int":ZEND_CONFIG_JSON_ENV_INT}'; - - $this->setExpectedException('Zend\Json\Exception', 'Syntax'); - $config = new JsonConfig($json, null, array('ignore_constants' => true)); - } - - public function testNestedConfigSetsAreArrays() - { - $config = new JsonConfig(__DIR__ . '/_files/nested.json', 'testing'); - $array = $config->toArray(); - $this->assertInternalType('array', $array['definitions'][0]); - } -} diff --git a/test/ProcessorTest.php b/test/ProcessorTest.php index 2682180..d051154 100644 --- a/test/ProcessorTest.php +++ b/test/ProcessorTest.php @@ -43,16 +43,16 @@ */ class ProcessorTest extends \PHPUnit_Framework_TestCase { - protected $_nested; - protected $_tokenBare, $_tokenPrefix, $_tokenSuffix, $_tokenSurround, $_tokenSurroundMixed; - protected $_translator, $_translatorStrings; - protected $_userConstants, $_phpConstants; - protected $_filter; + protected $nested; + protected $tokenBare, $tokenPrefix, $tokenSuffix, $tokenSurround, $tokenSurroundMixed; + protected $translator, $translatorStrings; + protected $userConstants, $phpConstants; + protected $filter; public function setUp() { // Arrays representing common config configurations - $this->_nested = array( + $this->nested = array( 'a' => 1, 'b' => 2, 'c' => array( @@ -71,7 +71,7 @@ public function setUp() 'e' => 10 ); - $this->_tokenBare = array( + $this->tokenBare = array( 'simple' => 'BARETOKEN', 'inside' => 'some text with BARETOKEN inside', 'nested' => array( @@ -80,7 +80,7 @@ public function setUp() ), ); - $this->_tokenPrefix = array( + $this->tokenPrefix = array( 'simple' => '::TOKEN', 'inside' => ':: some text with ::TOKEN inside ::', 'nested' => array( @@ -89,7 +89,7 @@ public function setUp() ), ); - $this->_tokenSuffix = array( + $this->tokenSuffix = array( 'simple' => 'TOKEN::', 'inside' => ':: some text with TOKEN:: inside ::', 'nested' => array( @@ -98,7 +98,7 @@ public function setUp() ), ); - $this->_tokenSurround = array( + $this->tokenSurround = array( 'simple' => '##TOKEN##', 'inside' => '## some text with ##TOKEN## inside ##', 'nested' => array( @@ -107,7 +107,7 @@ public function setUp() ), ); - $this->_tokenSurroundMixed = array( + $this->tokenSurroundMixed = array( 'simple' => '##TOKEN##', 'inside' => '## some text with ##TOKEN## inside ##', 'nested' => array( @@ -116,7 +116,7 @@ public function setUp() ), ); - $this->_translator = array( + $this->translator = array( 'pages' => array( array( 'id' => 'oneDog', @@ -131,12 +131,12 @@ public function setUp() ) ); - $this->_translatorStrings = array( + $this->translatorStrings = array( 'one dog' => 'ein Hund', 'two dogs' => 'zwei Hunde' ); - $this->_filter = array( + $this->filter = array( 'simple' => 'some MixedCase VALue', 'nested' => array( 'simple' => 'OTHER mixed Case Value', @@ -148,7 +148,7 @@ public function setUp() ArrayAdapter::removeCache(); } - $this->_userConstants = array( + $this->userConstants = array( 'simple' => 'SOME_USERLAND_CONSTANT', 'inside' => 'some text with SOME_USERLAND_CONSTANT inside', 'nested' => array( @@ -157,7 +157,7 @@ public function setUp() ), ); - $this->_phpConstants = array( + $this->phpConstants = array( 'phpVersion' => 'PHP_VERSION', 'phpVersionInside' => 'Current PHP version is: PHP_VERSION', 'nested' => array( @@ -183,20 +183,47 @@ public function testProcessorsQueue() public function testBareTokenPost() { - $config = new Config($this->_tokenBare, true); + $config = new Config($this->tokenBare, true); $processor = new TokenProcessor(); $processor->addToken('BARETOKEN', 'some replaced value'); $processor->process($config); + $this->assertEquals(array('BARETOKEN' => 'some replaced value'), $processor->getTokens()); $this->assertEquals('some replaced value', $config->simple); $this->assertEquals('some text with some replaced value inside', $config->inside); $this->assertEquals('some replaced value', $config->nested->simple); $this->assertEquals('some text with some replaced value inside', $config->nested->inside); } + public function testAddInvalidToken() + { + $processor = new TokenProcessor(); + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Cannot use ' . gettype(array()) . ' as token name.'); + $processor->addToken(array(), 'bar'); + } + + public function testSingleValueToken() + { + $processor = new TokenProcessor(); + $processor->addToken('BARETOKEN', 'test'); + $data = 'BARETOKEN'; + $out = $processor->processValue($data); + $this->assertEquals($out, 'test'); + } + + public function testTokenReadOnly() + { + $config = new Config($this->tokenBare, false); + $processor = new TokenProcessor(); + $processor->addToken('BARETOKEN', 'some replaced value'); + + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Cannot parse config because it is read-only'); + $processor->process($config); + } + public function testTokenPrefix() { - $config = new Config($this->_tokenPrefix, true); + $config = new Config($this->tokenPrefix, true); $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '::'); $processor->process($config); @@ -208,7 +235,7 @@ public function testTokenPrefix() public function testTokenSuffix() { - $config = new Config($this->_tokenSuffix, true); + $config = new Config($this->tokenSuffix, true); $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '', '::'); $processor->process($config); @@ -224,7 +251,7 @@ public function testTokenSuffix() */ public function testTokenSurround() { - $config = new Config($this->_tokenSurround, true); + $config = new Config($this->tokenSurround, true); $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '##', '##'); $processor->process($config); @@ -239,7 +266,7 @@ public function testTokenSurround() */ public function testTokenChangeParams() { - $config = new Config($this->_tokenSurroundMixed, true); + $config = new Config($this->tokenSurroundMixed, true); $processor = new TokenProcessor(array('TOKEN' => 'some replaced value'), '##', '##'); $processor->process($config); $this->assertEquals('some replaced value', $config->simple); @@ -271,22 +298,49 @@ public function testUserConstants() { define('SOME_USERLAND_CONSTANT', 'some constant value'); - $config = new Config($this->_userConstants, true); - $processor = new ConstantProcessor(); + $config = new Config($this->userConstants, true); + $processor = new ConstantProcessor(false); $processor->process($config); + $tokens = $processor->getTokens(); + $this->assertTrue(is_array($tokens)); + $this->assertTrue(in_array('SOME_USERLAND_CONSTANT', $tokens)); + $this->assertTrue(!$processor->getUserOnly()); + $this->assertEquals('some constant value', $config->simple); $this->assertEquals('some text with some constant value inside', $config->inside); $this->assertEquals('some constant value', $config->nested->simple); $this->assertEquals('some text with some constant value inside', $config->nested->inside); } + /** + * @depends testUserConstants + */ + public function testUserOnlyConstants() + { + + $config = new Config($this->userConstants, true); + $processor = new ConstantProcessor(); + $processor->process($config); + + $tokens = $processor->getTokens(); + + $this->assertTrue(is_array($tokens)); + $this->assertTrue(in_array('SOME_USERLAND_CONSTANT', $tokens)); + $this->assertTrue($processor->getUserOnly()); + + $this->assertEquals('some constant value', $config->simple); + $this->assertEquals('some text with some constant value inside', $config->inside); + $this->assertEquals('some constant value', $config->nested->simple); + $this->assertEquals('some text with some constant value inside', $config->nested->inside); + } + /** * @depends testTokenSurround */ public function testPHPConstants() { - $config = new Config($this->_phpConstants, true); + $config = new Config($this->phpConstants, true); $processor = new ConstantProcessor(false); $processor->process($config); @@ -298,8 +352,8 @@ public function testPHPConstants() public function testTranslator() { - $config = new Config($this->_translator, true); - $translator = new Translator(Translator::AN_ARRAY, $this->_translatorStrings, 'de_DE'); + $config = new Config($this->translator, true); + $translator = new Translator(Translator::AN_ARRAY, $this->translatorStrings, 'de_DE'); $processor = new TranslatorProcessor($translator); $processor->process($config); @@ -310,24 +364,62 @@ public function testTranslator() $this->assertEquals('twoDogs', $config->pages[1]->id); $this->assertEquals('zwei Hunde', $config->pages[1]->label); } + + public function testTranslatorReadOnly() + { + $config = new Config($this->translator, false); + $translator = new Translator(Translator::AN_ARRAY, $this->translatorStrings, 'de_DE'); + $processor = new TranslatorProcessor($translator); + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Cannot parse config because it is read-only'); + $processor->process($config); + } + public function testTranslatorSingleValue() + { + $translator = new Translator(Translator::AN_ARRAY, $this->translatorStrings, 'de_DE'); + $processor = new TranslatorProcessor($translator); + $word = 'one dog'; + $this->assertEquals('ein Hund', $processor->processValue($word)); + } + public function testFilter() { - $config = new Config($this->_filter, true); + $config = new Config($this->filter, true); $filter = new StringToLower(); $processor = new FilterProcessor($filter); + + $this->assertTrue($processor->getFilter() instanceof StringToLower); $processor->process($config); $this->assertEquals('some mixedcase value', $config->simple); $this->assertEquals('other mixed case value', $config->nested->simple); } + public function testFilterReadOnly() + { + $config = new Config($this->filter, false); + $filter = new StringToLower(); + $processor = new FilterProcessor($filter); + + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Cannot parse config because it is read-only'); + $processor->process($config); + } + + public function testFilterValue() + { + $filter = new StringToLower(); + $processor = new FilterProcessor($filter); + + $value = 'TEST'; + $this->assertEquals('test', $processor->processValue($value)); + } + /** * @depends testFilter */ - public function testProcessorsQueueFIFO() + public function testQueueFIFO() { - $config = new Config($this->_filter, true); + $config = new Config($this->filter, true); $lower = new StringToLower(); $upper = new StringToUpper(); $lowerProcessor = new FilterProcessor($lower); @@ -344,13 +436,47 @@ public function testProcessorsQueueFIFO() $this->assertEquals('some mixedcase value', $config->simple); $this->assertEquals('other mixed case value', $config->nested->simple); } + + public function testQueueReadOnly() + { + $config = new Config($this->filter, false); + $lower = new StringToLower(); + $lowerProcessor = new FilterProcessor($lower); + + /** + * Default queue order (FIFO) + */ + $queue = new Queue(); + $queue->insert($lowerProcessor); + + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Cannot parse config because it is read-only'); + $queue->process($config); + } + + public function testQueueSingleValue() + { + $lower = new StringToLower(); + $upper = new StringToUpper(); + $lowerProcessor = new FilterProcessor($lower); + $upperProcessor = new FilterProcessor($upper); + /** + * Default queue order (FIFO) + */ + $queue = new Queue(); + $queue->insert($upperProcessor); + $queue->insert($lowerProcessor); + + $data ='TeSt'; + $this->assertEquals('test', $queue->processValue($data)); + + } /** - * @depends testProcessorsQueueFIFO + * @depends testQueueFIFO */ - public function testProcessorsQueuePriorities() + public function testQueuePriorities() { - $config = new Config($this->_filter, 1); + $config = new Config($this->filter, 1); $lower = new StringToLower(); $upper = new StringToUpper(); $replace = new PregReplace('/[a-z]/', ''); diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php index 65af19e..a3e07e8 100644 --- a/test/Reader/AbstractReaderTestCase.php +++ b/test/Reader/AbstractReaderTestCase.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -46,37 +46,23 @@ abstract class AbstractReaderTestCase extends TestCase * @return string */ abstract protected function getTestAssetPath($name); - - public function testInclude() - { - $config = $this->reader->readFile($this->getTestAssetPath('include-base')); - $this->assertEquals('foo', $config->base->foo); - } - - public function testCurrentDirInFile() + + public function testMissingFile() { - $config = $this->reader->readFile($this->getTestAssetPath('current-dir')); - - $this->assertEquals(dirname($this->getTestAssetPath('current-dir')), $config->base->foo); + $filename = $this->getTestAssetPath('no-file'); + $this->setExpectedException('Zend\Config\Exception\RuntimeException', "The file $filename doesn't exists."); + $config = $this->reader->fromFile($filename); } - public function testCurrentDirInString() + public function testFromFile() { - $config = $this->reader->readString(file_get_contents($this->getTestAssetPath('current-dir'))); - $reflectionClass = new ReflectionClass($this->reader); - - $this->assertEquals(dirname($reflectionClass->getFileName()), $config->base->foo); + $config = $this->reader->fromFile($this->getTestAssetPath('include-base')); + $this->assertEquals('foo', $config['base']['foo']); } - public function testConstants() + public function testFromEmptyString() { - if (!defined('ZEND_CONFIG_TEST_CONSTANT')) { - define('ZEND_CONFIG_TEST_CONSTANT', 'test'); - } - - $config = $this->reader->readFile($this->getTestAssetPath('constants')); - - $this->assertEquals('foo-test-bar-test', $config->base->foo); - $this->assertEquals('ZEND_CONFIG_TEST_CONSTANT', $config->base->bar->const->name); + $config = $this->reader->fromString(''); + $this->assertTrue(!$config); } } diff --git a/test/Reader/IniTest.php b/test/Reader/IniTest.php index 6bf6859..a2fa063 100644 --- a/test/Reader/IniTest.php +++ b/test/Reader/IniTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -49,10 +49,51 @@ protected function getTestAssetPath($name) return __DIR__ . '/TestAssets/Ini/' . $name . '.ini'; } - public function testNonExistentConstant() + public function testInvalidIniFile() + { + $this->reader = new Ini(); + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayIni = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testFromString() { - $config = $this->reader->readFile($this->getTestAssetPath('non-existent-constant')); + $ini = <<reader->fromString($ini); + $this->assertEquals($arrayIni['test'], 'foo'); + $this->assertEquals($arrayIni['bar'][0], 'baz'); + $this->assertEquals($arrayIni['bar'][1], 'foo'); + } + + public function testInvalidString() + { + $ini = <<setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayIni = $this->reader->fromString($ini); + } + + public function testFromStringWithSection() + { + $ini = <<assertEquals('foo-ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT', $config->base->foo); + $arrayIni = $this->reader->fromString($ini); + $this->assertEquals($arrayIni['all']['test'], 'foo'); + $this->assertEquals($arrayIni['all']['bar'][0], 'baz'); + $this->assertEquals($arrayIni['all']['bar'][1], 'foo'); } } diff --git a/test/Reader/TestAssets/Ini/constants.ini b/test/Reader/TestAssets/Ini/constants.ini deleted file mode 100644 index a11988b..0000000 --- a/test/Reader/TestAssets/Ini/constants.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -foo = 'foo-'ZEND_CONFIG_TEST_CONSTANT'-bar-'ZEND_CONFIG_TEST_CONSTANT -bar.const.name = 'ZEND_CONFIG_TEST_CONSTANT' diff --git a/test/Reader/TestAssets/Ini/current-dir.ini b/test/Reader/TestAssets/Ini/current-dir.ini deleted file mode 100644 index 4b8b897..0000000 --- a/test/Reader/TestAssets/Ini/current-dir.ini +++ /dev/null @@ -1,2 +0,0 @@ -[base] -foo = '{DIR}' diff --git a/test/Reader/TestAssets/Ini/invalid.ini b/test/Reader/TestAssets/Ini/invalid.ini new file mode 100644 index 0000000..96bebf0 --- /dev/null +++ b/test/Reader/TestAssets/Ini/invalid.ini @@ -0,0 +1,2 @@ +[test] +foo=='bar' \ No newline at end of file diff --git a/test/Reader/TestAssets/Ini/non-existent-constant.ini b/test/Reader/TestAssets/Ini/non-existent-constant.ini deleted file mode 100644 index 2abc0e1..0000000 --- a/test/Reader/TestAssets/Ini/non-existent-constant.ini +++ /dev/null @@ -1,2 +0,0 @@ -[base] -foo = 'foo-'ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT diff --git a/test/Reader/TestAssets/Xml/constants.xml b/test/Reader/TestAssets/Xml/constants.xml deleted file mode 100644 index 8384ad0..0000000 --- a/test/Reader/TestAssets/Xml/constants.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - foo--bar- - - - \ No newline at end of file diff --git a/test/Reader/TestAssets/Xml/current-dir.xml b/test/Reader/TestAssets/Xml/current-dir.xml deleted file mode 100644 index 29326ac..0000000 --- a/test/Reader/TestAssets/Xml/current-dir.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/test/Reader/TestAssets/Xml/include-base.xml b/test/Reader/TestAssets/Xml/include-base.xml index e77f119..b2862b5 100644 --- a/test/Reader/TestAssets/Xml/include-base.xml +++ b/test/Reader/TestAssets/Xml/include-base.xml @@ -1,6 +1,5 @@ - + diff --git a/test/Reader/TestAssets/Xml/invalid.xml b/test/Reader/TestAssets/Xml/invalid.xml new file mode 100644 index 0000000..edac7d5 --- /dev/null +++ b/test/Reader/TestAssets/Xml/invalid.xml @@ -0,0 +1,4 @@ + + + value + \ No newline at end of file diff --git a/test/Reader/TestAssets/Xml/non-existent-constant.xml b/test/Reader/TestAssets/Xml/non-existent-constant.xml deleted file mode 100644 index e35d626..0000000 --- a/test/Reader/TestAssets/Xml/non-existent-constant.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - foo- - - \ No newline at end of file diff --git a/test/Reader/XmlTest.php b/test/Reader/XmlTest.php index 042cf2e..d25a19f 100644 --- a/test/Reader/XmlTest.php +++ b/test/Reader/XmlTest.php @@ -15,7 +15,7 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ @@ -23,7 +23,6 @@ use \Zend\Config\Reader\Xml; - /** * @category Zend * @package Zend_Config @@ -50,10 +49,41 @@ protected function getTestAssetPath($name) return __DIR__ . '/TestAssets/Xml/' . $name . '.xml'; } - public function testNonExistentConstant() + public function testInvalidXmlFile() + { + $this->reader = new Xml(); + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayXml = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testFromString() { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Constant with name "ZEND_CONFIG_TEST_NON_EXISTENT_CONSTANT" was not defined'); - $config = $this->reader->readFile($this->getTestAssetPath('non-existent-constant')); - var_dump($config); + $xml = << + + foo + baz + foo + + +ECS; + + $arrayXml= $this->reader->fromString($xml); + $this->assertEquals($arrayXml['test'], 'foo'); + $this->assertEquals($arrayXml['bar'][0], 'baz'); + $this->assertEquals($arrayXml['bar'][1], 'foo'); + } + + public function testInvalidString() + { + $xml = << + + baz + + +ECS; + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayXml = $this->reader->fromString($xml); } -} +} \ No newline at end of file diff --git a/test/TestAssets/Ini/include-base.ini b/test/TestAssets/Ini/include-base.ini new file mode 100644 index 0000000..54d0b56 --- /dev/null +++ b/test/TestAssets/Ini/include-base.ini @@ -0,0 +1,2 @@ +[base] +foo = "bar" \ No newline at end of file diff --git a/test/TestAssets/Ini/include-base2.ini b/test/TestAssets/Ini/include-base2.ini new file mode 100644 index 0000000..c2a372b --- /dev/null +++ b/test/TestAssets/Ini/include-base2.ini @@ -0,0 +1,2 @@ +[test] +bar = "baz" diff --git a/test/TestAssets/Xml/include-base.xml b/test/TestAssets/Xml/include-base.xml new file mode 100644 index 0000000..82b9111 --- /dev/null +++ b/test/TestAssets/Xml/include-base.xml @@ -0,0 +1,6 @@ + + + + bar + + \ No newline at end of file diff --git a/test/TestAssets/Xml/include-base2.xml b/test/TestAssets/Xml/include-base2.xml new file mode 100644 index 0000000..e7cc59a --- /dev/null +++ b/test/TestAssets/Xml/include-base2.xml @@ -0,0 +1,6 @@ + + + + baz + + \ No newline at end of file diff --git a/test/Writer/AbstractWriterTestCase.php b/test/Writer/AbstractWriterTestCase.php new file mode 100644 index 0000000..ccbd4fe --- /dev/null +++ b/test/Writer/AbstractWriterTestCase.php @@ -0,0 +1,101 @@ +tmpfile)) { + $this->tmpfile = tempnam(sys_get_temp_dir(), 'zend-config-writer'); + } + return $this->tmpfile; + } + + public function tearDown() + { + @unlink($this->getTestAssetFileName()); + } + + public function testNoFilenameSet() + { + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No file name specified'); + $this->writer->toFile('', ''); + } + + public function testFileNotValid() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $this->writer->toFile('.', new Config(array())); + } + + public function testFileNotWritable() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + chmod($this->getTestAssetFileName(), 0444); + $this->writer->toFile($this->getTestAssetFileName(), new Config(array())); + } + + public function testWriteAndRead() + { + $config = new Config(array('default' => array('test' => 'foo'))); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('foo', $config['default']['test']); + } +} diff --git a/test/Writer/ArrayWriterTest.php b/test/Writer/ArrayWriterTest.php deleted file mode 100644 index 350ded2..0000000 --- a/test/Writer/ArrayWriterTest.php +++ /dev/null @@ -1,114 +0,0 @@ -_tempName = tempnam(__DIR__ . '/temp', 'tmp'); - } - - public function tearDown() - { - @unlink($this->_tempName); - } - - public function testNoFilenameSet() - { - $writer = new ArrayWriter(array('config' => new Config(array()))); - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No filename was set'); - $writer->write(); - } - - public function testNoConfigSet() - { - $writer = new ArrayWriter(array('filename' => $this->_tempName)); - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No config was set'); - $writer->write(); - } - - public function testFileNotWritable() - { - $writer = new ArrayWriter(array('config' => new Config(array()), 'filename' => '/../../../')); - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Could not write to file'); - $writer->write(); - } - - public function testWriteAndRead() - { - $config = new Config(array('test' => 'foo')); - $writer = new ArrayWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new Config(include $this->_tempName); - $this->assertEquals('foo', $config->test); - } - - public function testArgumentOverride() - { - $config = new Config(array('test' => 'foo')); - $writer = new ArrayWriter(); - $writer->write($this->_tempName, $config); - - $config = new Config(include $this->_tempName); - $this->assertEquals('foo', $config->test); - } - - /** - * @group ZF-8234 - */ - public function testRender() - { - $config = new Config(array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo'))); - - $writer = new ArrayWriter(); - $configString = $writer->setConfig($config)->render(); - - - // build string line by line as we are trailing-whitespace sensitive. - $expected = " 'foo',\n"; - $expected .= " 'bar' => \n"; - $expected .= " array (\n"; - $expected .= " 0 => 'baz',\n"; - $expected .= " 1 => 'foo',\n"; - $expected .= " ),\n"; - $expected .= ");\n"; - - $this->assertEquals($expected, $configString); - } -} diff --git a/test/Writer/IniTest.php b/test/Writer/IniTest.php index c193796..7447d01 100644 --- a/test/Writer/IniTest.php +++ b/test/Writer/IniTest.php @@ -15,15 +15,15 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace ZendTest\Config\Writer; -use \Zend\Config\Writer\Ini, +use \Zend\Config\Writer\Ini as IniWriter, \Zend\Config\Config, - \Zend\Config\Ini as IniConfig; + \Zend\Config\Reader\Ini as IniReader; /** * @category Zend @@ -33,222 +33,38 @@ * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ -class IniTest extends \PHPUnit_Framework_TestCase +class IniTest extends AbstractWriterTestCase { - protected $_tempName; public function setUp() { - $this->_tempName = tempnam(__DIR__ . '/temp', 'tmp'); - } - - public function tearDown() - { - @unlink($this->_tempName); + $this->reader = new IniReader(); + $this->writer = new IniWriter(); } - public function testNoFilenameSet() - { - $writer = new Ini(array('config' => new Config(array()))); - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No filename was set'); - $writer->write(); - } - - public function testNoConfigSet() - { - $writer = new Ini(array('filename' => $this->_tempName)); - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No config was set'); - $writer->write(); - } - - public function testFileNotWritable() - { - $writer = new Ini(array('config' => new Config(array()), 'filename' => '/../../../')); - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Could not write to file'); - $writer->write(); - } - - public function testWriteAndRead() - { - $config = new Config(array('default' => array('test' => 'foo'))); - - $writer = new Ini(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new IniConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->default->test); - } + public function testNoSection() { $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); - $writer = new Ini(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); + $this->writer->toFile($this->getTestAssetFileName(), $config); - $config = new IniConfig($this->_tempName, null); + $config = $this->reader->fromFile($this->getTestAssetFileName()); - $this->assertEquals('foo', $config->test); - $this->assertEquals('bar', $config->test2->test3); + $this->assertEquals('foo', $config['test']); + $this->assertEquals('bar', $config['test2']['test3']); } public function testWriteAndReadOriginalFile() { - $config = new IniConfig(__DIR__ . '/files/allsections.ini', null, array('skipExtends' => true)); - - $writer = new Ini(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new IniConfig($this->_tempName, null); - $this->assertEquals('multi', $config->staging->one->two->three); - - $config = new IniConfig($this->_tempName, null, array('skipExtends' => true)); - $this->assertFalse(isset($config->staging->one)); - } - - - public function testWriteAndReadSingleSection() - { - $config = new IniConfig(__DIR__ . '/files/allsections.ini', 'staging', array('skipExtends' => true)); - - $writer = new Ini(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new IniConfig($this->_tempName, null); - - $this->assertEquals('staging', $config->staging->hostname); - $this->assertEquals('', $config->staging->debug); - $this->assertEquals(null, @$config->production); - } - - public function testArgumentOverride() - { - $config = new Config(array('default' => array('test' => 'foo'))); - - $writer = new Ini(); - $writer->write($this->_tempName, $config); - - $config = new IniConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->default->test); - } - - /** - * @group ZF-8234 - */ - public function testRender() - { - $config = new Config(array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo'))); - - $writer = new Ini(); - $iniString = $writer->setConfig($config)->render(); - - $expected = <<assertEquals($expected, $iniString); - } - - public function testRenderWithoutSections() - { - $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); - - $writer = new Ini(); - $writer->setRenderWithoutSections(); - $iniString = $writer->setConfig($config)->render(); - - $expected = <<assertEquals($expected, $iniString); - } - - public function testRenderWithoutSections2() - { - $config = new IniConfig(__DIR__ . '/files/allsections.ini', null, array('skipExtends' => true)); - - $writer = new Ini(); - $writer->setRenderWithoutSections(); - $iniString = $writer->setConfig($config)->render(); + $config = $this->reader->fromFile(__DIR__ . '/files/allsections.ini'); - $expected = <<assertEquals($expected, $iniString); - } - - /** - * @group ZF-6521 - */ - public function testNoDoubleQuoutesInValue() - { - $config = new Config(array('default' => array('test' => 'fo"o'))); - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Value can not contain double quotes'); - $writer = new Ini(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - } - - /** - * @group ZF-6289 - */ - public function testZF6289_NonSectionElementsAndSectionJumbling() - { - $config = new \Zend\Config\Config(array( - 'one' => 'element', - 'two' => array('type' => 'section'), - 'three' => 'element', - 'four' => array('type' => 'section'), - 'five' => 'element' - )); - - $writer = new \Zend\Config\Writer\Ini; - $iniString = $writer->setConfig($config)->render($config); - - $expected = <<writer->toFile($this->getTestAssetFileName(), $config); -[four] -type = "section" + $config = $this->reader->fromFile($this->getTestAssetFileName()); + $this->assertEquals('multi', $config['all']['one']['two']['three']); -ECS; - - $this->assertEquals( - $expected, - $iniString - ); } } diff --git a/test/Writer/JsonTest.php b/test/Writer/JsonTest.php deleted file mode 100644 index 8b31627..0000000 --- a/test/Writer/JsonTest.php +++ /dev/null @@ -1,150 +0,0 @@ -_tempName = tempnam(__DIR__ . '/temp', 'tmp'); - } - - public function tearDown() - { - @unlink($this->_tempName); - } - - public function testNoFilenameSet() - { - $writer = new JsonWriter(array('config' => new Config(array()))); - - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No filename was set'); - $writer->write(); - } - - public function testNoConfigSet() - { - $writer = new JsonWriter(array('filename' => $this->_tempName)); - - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No config was set'); - $writer->write(); - } - - public function testFileNotWritable() - { - $writer = new JsonWriter(array('config' => new Config(array()), 'filename' => '/../../../')); - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Could not write to file'); - $writer->write(); - } - - public function testWriteAndRead() - { - $config = new Config(array('default' => array('test' => 'foo'))); - - $writer = new JsonWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new JsonConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->default->test); - } - - public function testNoSection() - { - $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); - - $writer = new JsonWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new JsonConfig($this->_tempName); - - $this->assertEquals('foo', $config->test); - $this->assertEquals('bar', $config->test2->test3); - } - - public function testWriteAndReadOriginalFile() - { - $config = new JsonConfig(__DIR__ . '/files/allsections.json', null, array('skip_extends' => true)); - - $writer = new JsonWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new JsonConfig($this->_tempName, null); - $this->assertEquals('multi', $config->staging->one->two->three, var_export($config->toArray(), 1)); - - $config = new JsonConfig($this->_tempName, null, array('skip_extends' => true)); - $this->assertFalse(isset($config->staging->one)); - } - - - public function testWriteAndReadSingleSection() - { - $config = new JsonConfig(__DIR__ . '/files/allsections.json', 'staging', array('skip_extends' => true)); - - $writer = new JsonWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new JsonConfig($this->_tempName, null); - - $this->assertEquals('staging', $config->staging->hostname); - $this->assertEquals('', $config->staging->debug); - $this->assertEquals(null, @$config->production); - } - - public function testArgumentOverride() - { - $config = new Config(array('default' => array('test' => 'foo'))); - - $writer = new JsonWriter(); - $writer->write($this->_tempName, $config); - - $config = new JsonConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->default->test); - } - - public function testCanWritePrettyPrintedVersion() - { - $config = new JsonConfig(__DIR__ . '/files/allsections-pretty.json'); - - $writer = new JsonWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->setPrettyPrint(true); - $writer->write(); - $testOutput = file_get_contents($this->_tempName); - $this->assertRegExp('/^\s+/m', $testOutput); - } -} diff --git a/test/Writer/PhpArrayTest.php b/test/Writer/PhpArrayTest.php new file mode 100644 index 0000000..bb19846 --- /dev/null +++ b/test/Writer/PhpArrayTest.php @@ -0,0 +1,68 @@ +writer = new PhpArray(); + $this->reader = new PhpReader(); + } + + /** + * @group ZF-8234 + */ + public function testRender() + { + $config = new Config(array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo'))); + + $configString = $this->writer->toString($config); + + // build string line by line as we are trailing-whitespace sensitive. + $expected = " 'foo',\n"; + $expected .= " 'bar' => \n"; + $expected .= " array (\n"; + $expected .= " 0 => 'baz',\n"; + $expected .= " 1 => 'foo',\n"; + $expected .= " ),\n"; + $expected .= ");\n"; + + $this->assertEquals($expected, $configString); + } +} diff --git a/test/Writer/XmlTest.php b/test/Writer/XmlTest.php index 46bcd47..12f8806 100644 --- a/test/Writer/XmlTest.php +++ b/test/Writer/XmlTest.php @@ -15,15 +15,15 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace ZendTest\Config\Writer; -use \Zend\Config\Writer\Xml, +use \Zend\Config\Writer\Xml as XmlWriter, \Zend\Config\Config, - \Zend\Config\Xml as XmlConfig; + \Zend\Config\Reader\Xml as XmlReader; /** * @category Zend @@ -39,168 +39,62 @@ class XmlTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->_tempName = tempnam(__DIR__ . '/temp', 'tmp'); - } - - public function tearDown() - { - @unlink($this->_tempName); - } - - public function testNoFilenameSet() - { - $writer = new Xml(array('config' => new Config(array()))); - - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No filename was set'); - $writer->write(); - } - - public function testNoConfigSet() - { - $writer = new Xml(array('filename' => $this->_tempName)); - - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No config was set'); - $writer->write(); - } - - public function testFileNotWritable() - { - $writer = new Xml(array('config' => new Config(array()), 'filename' => '/../../../')); - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Could not write to file'); - $writer->write(); - } - - public function testWriteAndRead() - { - $config = new Config(array('default' => array('test' => 'foo'))); - - $writer = new Xml(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new XmlConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->default->test); - } - - public function testNoSection() - { - $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); - - $writer = new Xml(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new XmlConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->test); - $this->assertEquals('bar', $config->test2->test3); - } - - public function testWriteAndReadOriginalFile() - { - $config = new XmlConfig(__DIR__ . '/files/allsections.xml', null, array('skipExtends' => true)); - - $writer = new Xml(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new XmlConfig($this->_tempName, null); - $this->assertEquals('multi', $config->staging->one->two->three); - - $config = new XmlConfig($this->_tempName, null, array('skipExtends' => true)); - $this->assertFalse(isset($config->staging->one)); - } - - public function testWriteAndReadSingleSection() - { - $config = new XmlConfig(__DIR__ . '/files/allsections.xml', 'staging', array('skipExtends' => true)); - - $writer = new Xml(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new XmlConfig($this->_tempName, null); - - $this->assertEquals('staging', $config->staging->hostname); - $this->assertEquals('false', $config->staging->debug); - $this->assertEquals(null, @$config->production); - } - - /** - * @group ZF-6773 - */ - public function testWriteMultidimensionalArrayWithNumericKeys() - { - $writer = new Xml; - $writer->write($this->_tempName, new Config(array( - 'notification' => array( - 'adress' => array( - 0 => array( - 'name' => 'Matthew', - 'mail' => 'matthew@example.com' - ), - 1 => array( - 'name' => 'Thomas', - 'mail' => 'thomas@example.com' - ) - ) - ) - ))); + $this->writer = new XmlWriter(); + $this->reader = new XmlReader(); } - public function testNumericArray() + public function testToString() { - $config = new Config(array('foo' => array('bar' => array(1 => 'a', 2 => 'b', 5 => 'c')))); - - $writer = new Xml(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new XmlConfig($this->_tempName, null); - - $this->assertEquals('a', $config->foo->bar->{0}); - $this->assertEquals('b', $config->foo->bar->{1}); - $this->assertEquals('c', $config->foo->bar->{2}); - } - - public function testMixedArrayFailure() - { - $config = new Config(array('foo' => array('bar' => array('a', 'b', 'c' => 'd')))); - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Mixing of string and numeric keys is not allowed'); - $writer = new Xml(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - } + $config = new Config(array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo'))); - public function testArgumentOverride() - { - $config = new Config(array('default' => array('test' => 'foo'))); + $configString = $this->writer->toString($config); - $writer = new Xml(); - $writer->write($this->_tempName, $config); + $expected = << + + foo + baz + foo + - $config = new XmlConfig($this->_tempName, null); +ECS; - $this->assertEquals('foo', $config->default->test); + $this->assertEquals($expected, $configString); } - - /** - * @group ZF-8234 - */ - public function testRender() + + public function testSectionsToString() { - $config = new Config(array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo'))); - - $writer = new Xml(); - $configString = $writer->setConfig($config)->render(); - + $config = new Config(array(), true); + $config->production = array(); + + $config->production->webhost = 'www.example.com'; + $config->production->database = array(); + $config->production->database->params = array(); + $config->production->database->params->host = 'localhost'; + $config->production->database->params->username = 'production'; + $config->production->database->params->password = 'secret'; + $config->production->database->params->dbname = 'dbproduction'; + + $configString = $this->writer->toString($config); + $expected = << - - foo - baz - foo + + + + www.example.com + + + localhost + production + secret + dbproduction + + + ECS; - + $this->assertEquals($expected, $configString); } } diff --git a/test/Writer/YamlTest.php b/test/Writer/YamlTest.php deleted file mode 100644 index ded44dc..0000000 --- a/test/Writer/YamlTest.php +++ /dev/null @@ -1,139 +0,0 @@ -_tempName = tempnam(__DIR__ . '/temp', 'tmp'); - } - - public function tearDown() - { - @unlink($this->_tempName); - } - - public function testNoFilenameSet() - { - $writer = new YamlWriter(array('config' => new Config(array()))); - - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No filename was set'); - $writer->write(); - } - - public function testNoConfigSet() - { - $writer = new YamlWriter(array('filename' => $this->_tempName)); - - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No config was set'); - $writer->write(); - } - - public function testFileNotWritable() - { - $writer = new YamlWriter(array('config' => new Config(array()), 'filename' => '/../../../')); - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Could not write'); - $writer->write(); - } - - public function testWriteAndRead() - { - $config = new Config(array('default' => array('test' => 'foo'))); - - $writer = new YamlWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new YamlConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->default->test); - } - - public function testNoSection() - { - $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); - - $writer = new YamlWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new YamlConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->test); - $this->assertEquals('bar', $config->test2->test3); - } - - public function testWriteAndReadOriginalFile() - { - $config = new YamlConfig(__DIR__ . '/files/allsections.yaml', null, array('skip_extends' => true)); - - $writer = new YamlWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new YamlConfig($this->_tempName, null); - $this->assertEquals('multi', $config->staging->one->two->three, var_export($config->toArray(), 1)); - - $config = new YamlConfig($this->_tempName, null, array('skip_extends' => true)); - $this->assertFalse(isset($config->staging->one)); - } - - - public function testWriteAndReadSingleSection() - { - $config = new YamlConfig(__DIR__ . '/files/allsections.yaml', 'staging', array('skip_extends' => true)); - - $writer = new YamlWriter(array('config' => $config, 'filename' => $this->_tempName)); - $writer->write(); - - $config = new YamlConfig($this->_tempName, null); - - $this->assertEquals('staging', $config->staging->hostname); - $this->assertEquals('', $config->staging->debug); - $this->assertEquals(null, @$config->production); - } - - public function testArgumentOverride() - { - $config = new Config(array('default' => array('test' => 'foo'))); - - $writer = new YamlWriter(); - $writer->write($this->_tempName, $config); - - $config = new YamlConfig($this->_tempName, null); - - $this->assertEquals('foo', $config->default->test); - } -} diff --git a/test/Writer/files/PhpReader.php b/test/Writer/files/PhpReader.php new file mode 100644 index 0000000..6a72bcb --- /dev/null +++ b/test/Writer/files/PhpReader.php @@ -0,0 +1,9 @@ +_xmlFileConfig = __DIR__ . '/_files/config.xml'; - $this->_xmlFileAllSectionsConfig = __DIR__ . '/_files/allsections.xml'; - $this->_xmlFileCircularConfig = __DIR__ . '/_files/circular.xml'; - $this->_xmlFileTopLevelStringConfig = __DIR__ . '/_files/toplevelstring.xml'; - $this->_xmlFileOneTopLevelStringConfig = __DIR__ . '/_files/onetoplevelstring.xml'; - $this->_nonReadableConfig = __DIR__ . '/_files/nonreadable.xml'; - $this->_xmlFileSameNameKeysConfig = __DIR__ . '/_files/array.xml'; - $this->_xmlFileShortParamsOneConfig = __DIR__ . '/_files/shortparamsone.xml'; - $this->_xmlFileShortParamsTwoConfig = __DIR__ . '/_files/shortparamstwo.xml'; - $this->_xmlFileInvalid = __DIR__ . '/_files/invalid.xml'; - } - - public function testLoadSingleSection() - { - $config = new Xml($this->_xmlFileConfig, 'all'); - $this->assertEquals('all', $config->hostname); - $this->assertEquals('live', $config->db->name); - $this->assertEquals('multi', $config->one->two->three); - $this->assertNull(@$config->nonexistent); // property doesn't exist - } - - public function testSectionInclude() - { - $config = new Xml($this->_xmlFileConfig, 'staging'); - $this->assertEquals('false', $config->debug); // only in staging - $this->assertEquals('thisname', $config->name); // only in all - $this->assertEquals('username', $config->db->user); // only in all (nested version) - $this->assertEquals('staging', $config->hostname); // inherited and overridden - $this->assertEquals('dbstaging', $config->db->name); // inherited and overridden - } - - public function testMultiDepthExtends() - { - $config = new Xml($this->_xmlFileConfig, 'other_staging'); - - $this->assertEquals('otherStaging', $config->only_in); // only in other_staging - $this->assertEquals('false', $config->debug); // 1 level down: only in staging - $this->assertEquals('thisname', $config->name); // 2 levels down: only in all - $this->assertEquals('username', $config->db->user); // 2 levels down: only in all (nested version) - $this->assertEquals('staging', $config->hostname); // inherited from two to one and overridden - $this->assertEquals('dbstaging', $config->db->name); // inherited from two to one and overridden - $this->assertEquals('anotherpwd', $config->db->pass); // inherited from two to other_staging and overridden - } - - public function testErrorNoInitialSection() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'cannot be found in'); - $config = @new Xml($this->_xmlFileConfig, 'notthere'); - } - - public function testErrorNoInitialSectionWhenArrayOfSectionsSpecified() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'cannot be found in'); - $config = @new Xml($this->_xmlFileConfig, array('notthere', 'all')); - } - - public function testErrorNoExtendsSection() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'cannot be found'); - $config = new Xml($this->_xmlFileConfig, 'extendserror'); - } - - /** - * @group ZF-413 - */ - public function testMultiSections() - { - $config = new Xml($this->_xmlFileAllSectionsConfig, array('staging','other_staging')); - - $this->assertEquals('otherStaging', $config->only_in); - $this->assertEquals('staging', $config->hostname); - } - - /** - * @group ZF-413 - */ - public function testAllSections() - { - $config = new Xml($this->_xmlFileAllSectionsConfig, null); - $this->assertEquals('otherStaging', $config->other_staging->only_in); - $this->assertEquals('staging', $config->staging->hostname); - } - - /** - * @group ZF-414 - */ - public function testGetSectionNameAndAreAllSectionsLoaded() - { - $config = new Xml($this->_xmlFileAllSectionsConfig, null); - $this->assertEquals(null, $config->getSectionName()); - $this->assertEquals(true, $config->areAllSectionsLoaded()); - - $config = new Xml($this->_xmlFileAllSectionsConfig, 'all'); - $this->assertEquals('all', $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - - $config = new Xml($this->_xmlFileAllSectionsConfig, array('staging','other_staging')); - $this->assertEquals(array('staging','other_staging'), $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - } - - /** - * @group ZF-415 - */ - public function testErrorCircularInheritance() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'circular inheritance'); - $config = new Xml($this->_xmlFileCircularConfig, null); - } - - public function testErrorNoFile() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Filename is not set'); - $config = new Xml('',null); - } - - /** - * @group ZF-2162 - */ - public function testTopLevelString() - { - $config = new Xml($this->_xmlFileTopLevelStringConfig, null); - $this->assertEquals('one', $config->one); - $this->assertEquals('three', $config->two->three); - $this->assertEquals('five', $config->two->four->five); - $this->assertEquals('three', $config->six->three); - - $config = new Xml($this->_xmlFileOneTopLevelStringConfig); - $this->assertEquals('one', $config->one); - $config = new Xml($this->_xmlFileOneTopLevelStringConfig, 'one'); - $this->assertEquals('one', $config->one); - - } - - /** - * @group ZF-2285 - */ - public function testMultipleKeysOfTheSameName() - { - $config = new Xml($this->_xmlFileSameNameKeysConfig, null); - $this->assertEquals('2a', $config->one->two->{0}); - $this->assertEquals('2b', $config->one->two->{1}); - $this->assertEquals('4', $config->three->four->{1}); - $this->assertEquals('5', $config->three->four->{0}->five); - } - - /** - * @group ZF-2437 - */ - public function testArraysWithMultipleChildren() - { - $config = new Xml($this->_xmlFileSameNameKeysConfig, null); - $this->assertEquals('1', $config->six->seven->{0}->eight); - $this->assertEquals('2', $config->six->seven->{1}->eight); - $this->assertEquals('3', $config->six->seven->{2}->eight); - $this->assertEquals('1', $config->six->seven->{0}->nine); - $this->assertEquals('2', $config->six->seven->{1}->nine); - $this->assertEquals('3', $config->six->seven->{2}->nine); - } - - /** - * @group ZF-3578 - * @group ZF2-13 - */ - public function testInvalidXmlFile() - { - try { - $config = new Xml($this->_xmlFileInvalid); - $this->fail('Missing expected exception'); - } catch (\Zend\Config\Exception\RuntimeException $e) { - // read exception stack - do { - $stack[] = $e; - } while ( ($e = $e->getPrevious()) ); - - // test two thrown xml errors - $this->assertEquals(2, count($stack)); - $this->assertContains('tag mismatch', $stack[0]->getMessage()); - $this->assertContains('undefined', $stack[1]->getMessage()); - } - } - - /** - * @group ZF-3578 - */ - public function testMissingXmlFile() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'failed to load'); - $config = new Xml('I/dont/exist'); - } - - public function testShortParamsOne() - { - $config = new Xml($this->_xmlFileShortParamsOneConfig, 'all'); - $this->assertEquals('all', $config->hostname); - $this->assertEquals('thisname', $config->name); - $this->assertEquals('username', $config->db->user); - $this->assertEquals('live', $config->db->name); - $this->assertEquals('multi', $config->one->two->three); - } - - public function testShortParamsTwo() - { - $config = new Xml($this->_xmlFileShortParamsTwoConfig, 'all'); - $this->assertEquals('all', $config->hostname); - $this->assertEquals('thisname', $config->name); - $this->assertEquals('username', $config->db->user); - $this->assertEquals('live', $config->db->name); - $this->assertEquals('multi', $config->one->two->three); - } - - public function testConstants() - { - if (!defined('ZEND_CONFIG_XML_TEST_CONSTANT')) { - define('ZEND_CONFIG_XML_TEST_CONSTANT', 'test'); - } - - $string = << - - - foo--bar- - - - -EOT; - - $config = new Xml($string, 'all'); - - $this->assertEquals('foo-test-bar-test', $config->foo); - $this->assertEquals('ZEND_CONFIG_XML_TEST_CONSTANT', $config->bar->const->name); - } - - public function testNonExistentConstant() - { - $string = << - - - foo- - - -EOT; - - $this->setExpectedException('Zend\Config\Exception\RuntimeException', "Constant with name 'ZEND_CONFIG_XML_TEST_NON_EXISTENT_CONSTANT' was not defined"); - $config = new Xml($string, 'all'); - } - - public function testNamespacedExtends() - { - $string = << - - - bar - - - -EOT; - - $config = new Xml($string); - - $this->assertEquals('bar', $config->staging->foo); - } - - /** - * @group ZF-3702 - */ - public function testLoadAnXMLString() - { - $string = << - - - all - - 127.0.0.1 - live - - - - - staging - - dbstaging - - false - - - - -EOT; - - $config = new Xml($string, 'staging'); - $this->assertEquals('staging', $config->hostname); - - } - - /** - * @group ZF-5800 - */ - public function testArraysOfKeysCreatedUsingAttributesAndKeys() - { - $string = << - - - - user1@company.com - User Name - 1 - - - - - - - -EOT; - - $config = new Xml($string, 'dev'); - $this->assertEquals('nice.guy@company.com', $config->receiver->{0}->mail); - $this->assertEquals('1', $config->receiver->{0}->html); - $this->assertNull($config->receiver->mail); - } -} diff --git a/test/YamlTest.php b/test/YamlTest.php deleted file mode 100644 index 86415f5..0000000 --- a/test/YamlTest.php +++ /dev/null @@ -1,340 +0,0 @@ -_iniFileConfig = __DIR__ . '/_files/config.yaml'; - $this->_iniFileAllSectionsConfig = __DIR__ . '/_files/allsections.yaml'; - $this->_iniFileCircularConfig = __DIR__ . '/_files/circular.yaml'; - $this->_nonReadableConfig = __DIR__ . '/_files/nonreadable.yaml'; - $this->_iniFileInvalid = __DIR__ . '/_files/invalid.yaml'; - $this->_iniFileSameNameKeysConfig = __DIR__ . '/_files/array.yaml'; - $this->_badIndentationConfig = __DIR__ . '/_files/badindentation.yaml'; - $this->_booleansConfig = __DIR__ . '/_files/booleans.yaml'; - $this->_constantsConfig = __DIR__ . '/_files/constants.yaml'; - } - - public function testLoadSingleSection() - { - $config = new YamlConfig($this->_iniFileConfig, 'all'); - - $this->assertEquals('all', $config->hostname); - $this->assertEquals('live', $config->db->name); - $this->assertEquals('multi', $config->one->two->three); - $this->assertNull(@$config->nonexistent); // property doesn't exist - } - - public function testSectionInclude() - { - $config = new YamlConfig($this->_iniFileConfig, 'staging'); - - $this->assertEquals('', $config->debug); // only in staging - $this->assertEquals('thisname', $config->name); // only in all - $this->assertEquals('username', $config->db->user); // only in all (nested version) - $this->assertEquals('staging', $config->hostname); // inherited and overridden - $this->assertEquals('dbstaging', $config->db->name); // inherited and overridden - } - - public function testTrueValues() - { - $config = new YamlConfig($this->_iniFileConfig, 'debug'); - - $this->assertInternalType('string', $config->debug); - $this->assertEquals('1', $config->debug); - $this->assertInternalType('string', $config->values->changed); - $this->assertEquals('1', $config->values->changed); - } - - public function testEmptyValues() - { - $config = new YamlConfig($this->_iniFileConfig, 'debug'); - - $this->assertInternalType('string', $config->special->no); - $this->assertEquals('', $config->special->no); - $this->assertInternalType('string', $config->special->null); - $this->assertEquals('', $config->special->null); - $this->assertInternalType('string', $config->special->false); - $this->assertEquals('', $config->special->false); - $this->assertInternalType('string', $config->special->zero); - $this->assertEquals('0', $config->special->zero); - } - - public function testMultiDepthExtends() - { - $config = new YamlConfig($this->_iniFileConfig, 'other_staging'); - - $this->assertEquals('otherStaging', $config->only_in); // only in other_staging - $this->assertEquals('', $config->debug); // 1 level down: only in staging - $this->assertEquals('thisname', $config->name); // 2 levels down: only in all - $this->assertEquals('username', $config->db->user); // 2 levels down: only in all (nested version) - $this->assertEquals('staging', $config->hostname); // inherited from two to one and overridden - $this->assertEquals('dbstaging', $config->db->name); // inherited from two to one and overridden - $this->assertEquals('anotherpwd', $config->db->pass); // inherited from two to other_staging and overridden - } - - public function testErrorNoExtendsSection() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'cannot be found'); - $config = new YamlConfig($this->_iniFileConfig, 'extendserror'); - } - - /** - * @group ZF-413 - */ - public function testMultiSections() - { - $config = new YamlConfig($this->_iniFileAllSectionsConfig, array('staging','other_staging')); - - $this->assertEquals('otherStaging', $config->only_in); - $this->assertEquals('staging', $config->hostname); - - } - - /** - * @group ZF-413 - */ - public function testAllSections() - { - $config = new YamlConfig($this->_iniFileAllSectionsConfig, null); - $this->assertEquals('otherStaging', $config->other_staging->only_in); - $this->assertEquals('staging', $config->staging->hostname); - } - - /** - * @group ZF-414 - */ - public function testGetSectionNameAndAreAllSectionsLoaded() - { - $config = new YamlConfig($this->_iniFileAllSectionsConfig, null); - $this->assertEquals(null, $config->getSectionName()); - $this->assertEquals(true, $config->areAllSectionsLoaded()); - - $config = new YamlConfig($this->_iniFileAllSectionsConfig, 'all'); - $this->assertEquals('all', $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - - $config = new YamlConfig($this->_iniFileAllSectionsConfig, array('staging','other_staging')); - $this->assertEquals(array('staging','other_staging'), $config->getSectionName()); - $this->assertEquals(false, $config->areAllSectionsLoaded()); - } - - /** - * @group ZF-415 - */ - public function testErrorCircularInheritance() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'circular inheritance'); - $config = new YamlConfig($this->_iniFileCircularConfig, null); - } - - public function testErrorNoFile() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Filename is not set'); - $config = new YamlConfig('',''); - } - - public function testErrorNoSectionFound() - { - try { - $config = new YamlConfig($this->_iniFileConfig,array('all', 'notthere')); - $this->fail('An expected exception has not been raised'); - } catch (Exception\RuntimeException $expected) { - $this->assertContains('cannot be found', $expected->getMessage()); - } - - try { - $config = new YamlConfig($this->_iniFileConfig,'notthere'); - $this->fail('An expected exception has not been raised'); - } catch (Exception\RuntimeException $expected) { - $this->assertContains('cannot be found', $expected->getMessage()); - } - - } - - /** - * @group ZF-3196 - */ - public function testInvalidIniFile() - { - try { - $config = new YamlConfig($this->_iniFileInvalid); - $this->fail('An expected exception has not been raised'); - } catch (Exception\RuntimeException $expected) { - $this->assertRegexp('/(Error parsing|syntax error, unexpected)/', $expected->getMessage()); - } - - } - - /** - * @group ZF-2285 - */ - public function testMultipleKeysOfTheSameName() - { - $config = new YamlConfig($this->_iniFileSameNameKeysConfig, null); - $this->assertEquals('2a', $config->one->two->{0}); - $this->assertEquals('2b', $config->one->two->{1}); - $this->assertEquals('4', $config->three->four->{1}); - $this->assertEquals('5', $config->three->four->{0}->five); - } - - /** - * @group ZF-2437 - */ - public function testArraysWithMultipleChildren() - { - $config = new YamlConfig($this->_iniFileSameNameKeysConfig, null); - $this->assertEquals('1', $config->six->seven->{0}->eight); - $this->assertEquals('2', $config->six->seven->{1}->eight); - $this->assertEquals('3', $config->six->seven->{2}->eight); - $this->assertEquals('1', $config->six->seven->{0}->nine); - $this->assertEquals('2', $config->six->seven->{1}->nine); - $this->assertEquals('3', $config->six->seven->{2}->nine); - } - - public function yamlDecoder($string) - { - return YamlConfig::decode($string); - } - - public function testHonorsOptionsProvidedToConstructor() - { - $config = new YamlConfig($this->_iniFileAllSectionsConfig, 'debug', array( - 'allow_modifications' => true, - 'skip_extends' => true, - 'yaml_decoder' => array($this, 'yamlDecoder'), - 'foo' => 'bar', // ignored - )); - $this->assertNull($config->name); // verifies extends were skipped - $config->foo = 'bar'; - $this->assertEquals('bar', $config->foo); // verifies allows modifications - $this->assertEquals(array($this, 'yamlDecoder'), $config->getYamlDecoder()); - } - - public function testFileNotFound() - { - try { - $file = '__foo__'; - $config = new YamlConfig($file); - $this->fail('Missing expected exception'); - } catch (Exception\RuntimeException $e) { - // read exception stack - do { - $stack[] = $e; - } while ( ($e = $e->getPrevious()) ); - - // test two thrown exceptions - $this->assertEquals(2, count($stack)); - $this->assertContains($file, $stack[0]->getMessage()); - $this->assertContains('file_get_contents', $stack[1]->getMessage()); - } - } - - public function testBadIndentationRaisesException() - { - $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'unsupported syntax'); - $config = new YamlConfig($this->_badIndentationConfig, 'all'); - } - - public function testPassingBadYamlDecoderRaisesException() - { - $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'must be callable'); - $config = new YamlConfig($this->_iniFileAllSectionsConfig, 'debug', array( - 'yaml_decoder' => '__foo__', - )); - } - - public function testParsesBooleansAccordingToOneDotOneSpecification() - { - $config = new YamlConfig($this->_booleansConfig, 'production'); - - $this->assertTrue($config->usingLowerCasedYes); - $this->assertTrue($config->usingTitleCasedYes); - $this->assertTrue($config->usingCapitalYes); - $this->assertTrue($config->usingLowerY); - $this->assertTrue($config->usingUpperY); - - $this->assertFalse($config->usingLowerCasedNo); - $this->assertFalse($config->usingTitleCasedNo); - $this->assertFalse($config->usingCapitalNo); - $this->assertFalse($config->usingLowerN); - $this->assertFalse($config->usingUpperN); - - $this->assertTrue($config->usingLowerCasedTrue); - $this->assertTrue($config->usingTitleCasedTrue); - $this->assertTrue($config->usingCapitalTrue); - - $this->assertFalse($config->usingLowerCasedFalse); - $this->assertFalse($config->usingTitleCasedFalse); - $this->assertFalse($config->usingCapitalFalse); - - $this->assertTrue($config->usingLowerCasedOn); - $this->assertTrue($config->usingTitleCasedOn); - $this->assertTrue($config->usingCapitalOn); - - $this->assertFalse($config->usingLowerCasedOff); - $this->assertFalse($config->usingTitleCasedOff); - $this->assertFalse($config->usingCapitalOff); - } - - public function testHonorsPhpConstants() - { - if (!defined('ZEND_CONFIG_YAML_ENV')) { - define('ZEND_CONFIG_YAML_ENV', 'testing'); - } - if (!defined('ZEND_CONFIG_YAML_ENV_PATH')) { - define('ZEND_CONFIG_YAML_ENV_PATH', __DIR__); - } - $config = new YamlConfig($this->_constantsConfig, 'production'); - $this->assertEquals(ZEND_CONFIG_YAML_ENV, $config->env); - $this->assertEquals(ZEND_CONFIG_YAML_ENV_PATH . '/test/this', $config->path); - } - - public function testAllowsIgnoringConstantStrings() - { - if (!defined('ZEND_CONFIG_YAML_ENV')) { - define('ZEND_CONFIG_YAML_ENV', 'testing'); - } - if (!defined('ZEND_CONFIG_YAML_ENV_PATH')) { - define('ZEND_CONFIG_YAML_ENV_PATH', __DIR__); - } - $config = new YamlConfig( - $this->_constantsConfig, 'production', array('ignore_constants' => true) - ); - $this->assertEquals('ZEND_CONFIG_YAML_ENV', $config->env); - $this->assertEquals('ZEND_CONFIG_YAML_ENV_PATH/test/this', $config->path); - } -} diff --git a/test/_files/booleans.ini b/test/_files/booleans.ini deleted file mode 100644 index a4490b5..0000000 --- a/test/_files/booleans.ini +++ /dev/null @@ -1,6 +0,0 @@ -[all] -trueValue = true -falseValue = false -trueString = "true" -falseString = "false" - From d2701db148f1c3b65506b0bd4dbffc23dd23eceb Mon Sep 17 00:00:00 2001 From: Evan Coury Date: Mon, 27 Feb 2012 18:27:40 -0700 Subject: [PATCH 17/18] [Zend\Config\Factory] Throw exception for unrecognized config extension Also added unit tests for expected exceptions. --- src/Factory.php | 2 +- test/FactoryTest.php | 12 ++++++++++++ test/TestAssets/bad.ext | 0 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/TestAssets/bad.ext diff --git a/src/Factory.php b/src/Factory.php index 6dd1e14..667d51f 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -71,7 +71,7 @@ public static function fromFile($filename) break; } - return null; + throw new Exception\RuntimeException(sprintf('Unsupported config file extension: .%s', $pathinfo['extension'])); } /** diff --git a/test/FactoryTest.php b/test/FactoryTest.php index ddeef0b..9e67929 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -85,5 +85,17 @@ public function testFromIniAndXmlFiles() $this->assertEquals('bar', $config['base']['foo']); $this->assertEquals('baz', $config['test']['bar']); } + + public function testNonExistentFileThrowsRuntimeException() + { + $this->setExpectedException('RuntimeException'); + $config = Factory::fromFile('foo.bar'); + } + + public function testInvalidFileExtensionThrowsInvalidArgumentException() + { + $this->setExpectedException('RuntimeException'); + $config = Factory::fromFile(__DIR__ . '/TestAssets/bad.ext'); + } } diff --git a/test/TestAssets/bad.ext b/test/TestAssets/bad.ext new file mode 100644 index 0000000..e69de29 From a10e1fd49a5e3f4c2f6a6540ed88de5290198edf Mon Sep 17 00:00:00 2001 From: Ben Scholzen Date: Wed, 29 Feb 2012 23:59:31 +0100 Subject: [PATCH 18/18] Updated config factory to allow easier addition of new readers --- src/Factory.php | 60 ++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index 667d51f..6bdf2e0 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -29,11 +29,14 @@ class Factory { /** - * Reader instances used for files. + * Readers used for config files. * * @var array */ - protected static $readers = array(); + protected static $readers = array( + 'ini' => 'Ini', + 'xml' => 'Xml' + ); /** * Read a config from a file. @@ -43,35 +46,36 @@ class Factory */ public static function fromFile($filename) { - if (!file_exists($filename)) { - throw new Exception\RuntimeException("The file $filename doesn't exists."); + $pathinfo = pathinfo($filename); + + if (!isset($pathinfo['extension'])) { + throw new Exception\RuntimeException(sprintf( + 'Filename "%s" is missing an extension and cannot be auto-detected', + $filename + )); } - $pathinfo = pathinfo($filename); - - switch (strtolower($pathinfo['extension'])) { - case 'php': - return include $filename; - break; - - case 'ini': - if (!isset(self::$readers['ini'])) { - self::$readers['ini'] = new Reader\Ini(); - } - - return self::$readers['ini']->fromFile($filename); - break; - - case 'xml': - if (!isset(self::$readers['xml'])) { - self::$readers['xml'] = new Reader\Xml(); - } - - return self::$readers['xml']->fromFile($filename); - break; + $extension = strtolower($pathinfo['extension']); + + if ($extension === 'php') { + if (!is_file($filename) || !is_readable($filename)) { + throw new Exception\RuntimeException(sprintf('Filename "%s" is either not a file or not readable', $filename)); + } + + return include $filename; + } elseif (isset(self::$readers[$extension])) { + if (is_string(self::$readers[$extension])) { + $classname = __NAMESPACE__ . '\\Reader\\' . self::$readers[$extension]; + self::$readers[$extension] = new $classname(); + } + + return self::$readers[$extension]->fromFile($filename); + } else { + throw new Exception\RuntimeException(sprintf( + 'Unsupported config file extension: .%s', + $pathinfo['extension'] + )); } - - throw new Exception\RuntimeException(sprintf('Unsupported config file extension: .%s', $pathinfo['extension'])); } /**