From edde7a45adfdb74ec3a5829ff338e12eb0537f05 Mon Sep 17 00:00:00 2001 From: Maks3w Date: Mon, 9 Jul 2012 16:19:42 +0200 Subject: [PATCH 01/12] [CS][Library] Set File Header http://framework.zend.com/wiki/display/ZFDEV2/Coding+Standards#CodingStandards-Files The following script replaces the content between PHP open tag and namespace declaration. for COMPONENT in $(ls -d *) do for FILE in $(find $COMPONENT -name "*.php") do BLOCK="\/\*\*\n \* Zend Framework \(http:\/\/framework\.zend\.com\/\)\n \*\n \* \@link http:\/\/github\.com\/zendframework\/zf2 for the canonical source repository\n \* \@copyright Copyright \(c\) 2005-2012 Zend Technologies USA Inc\. \(http:\/\/www\.zend\.com\)\n \* \@license http:\/\/framework\.zend\.com\/license\/new-bsd New BSD License\n \* \@package Zend_$COMPONENT\n \*\/" perl -0777 -i -pe "s/(<\?php(\s*.*)*\nn)/ Date: Mon, 9 Jul 2012 16:34:21 +0200 Subject: [PATCH 02/12] [CS][test] Remove @copyright & @license for fl in $(find . -name "*.php"); do mv $fl $fl.old; sed '/@copyright/d' $fl.old > $fl; rm -f $fl.old; done; for fl in $(find . -name "*.php"); do mv $fl $fl.old; sed '/@license/d' $fl.old > $fl; rm -f $fl.old; done; --- test/ConfigTest.php | 4 ---- test/FactoryTest.php | 4 ---- test/ProcessorTest.php | 4 ---- test/Reader/AbstractReaderTestCase.php | 4 ---- test/Reader/IniTest.php | 4 ---- test/Reader/JsonTest.php | 4 ---- test/Reader/XmlTest.php | 4 ---- test/Reader/YamlTest.php | 4 ---- test/Writer/AbstractWriterTestCase.php | 4 ---- test/Writer/IniTest.php | 4 ---- test/Writer/JsonTest.php | 4 ---- test/Writer/PhpArrayTest.php | 4 ---- test/Writer/XmlTest.php | 4 ---- test/Writer/YamlTest.php | 4 ---- 14 files changed, 56 deletions(-) diff --git a/test/ConfigTest.php b/test/ConfigTest.php index e5ea31c..8969e7d 100644 --- a/test/ConfigTest.php +++ b/test/ConfigTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -27,8 +25,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class ConfigTest extends \PHPUnit_Framework_TestCase diff --git a/test/FactoryTest.php b/test/FactoryTest.php index 29f91f9..d34a045 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -27,8 +25,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class FactoryTest extends \PHPUnit_Framework_TestCase diff --git a/test/ProcessorTest.php b/test/ProcessorTest.php index 196ed07..91cb319 100644 --- a/test/ProcessorTest.php +++ b/test/ProcessorTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -37,8 +35,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class ProcessorTest extends \PHPUnit_Framework_TestCase diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php index 55644b8..d0429c3 100644 --- a/test/Reader/AbstractReaderTestCase.php +++ b/test/Reader/AbstractReaderTestCase.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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\Reader; @@ -29,8 +27,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ abstract class AbstractReaderTestCase extends TestCase diff --git a/test/Reader/IniTest.php b/test/Reader/IniTest.php index f0d5edb..c975c35 100644 --- a/test/Reader/IniTest.php +++ b/test/Reader/IniTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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\Reader; @@ -27,8 +25,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class IniTest extends AbstractReaderTestCase diff --git a/test/Reader/JsonTest.php b/test/Reader/JsonTest.php index 522cdb7..34b9b3b 100644 --- a/test/Reader/JsonTest.php +++ b/test/Reader/JsonTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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\Reader; @@ -27,8 +25,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class JsonTest extends AbstractReaderTestCase diff --git a/test/Reader/XmlTest.php b/test/Reader/XmlTest.php index 556ba6f..c80b333 100644 --- a/test/Reader/XmlTest.php +++ b/test/Reader/XmlTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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\Reader; @@ -27,8 +25,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class XmlTest extends AbstractReaderTestCase diff --git a/test/Reader/YamlTest.php b/test/Reader/YamlTest.php index 0e08d0b..f90d510 100644 --- a/test/Reader/YamlTest.php +++ b/test/Reader/YamlTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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\Reader; @@ -27,8 +25,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class YamlTest extends AbstractReaderTestCase diff --git a/test/Writer/AbstractWriterTestCase.php b/test/Writer/AbstractWriterTestCase.php index 7319703..78eb49c 100644 --- a/test/Writer/AbstractWriterTestCase.php +++ b/test/Writer/AbstractWriterTestCase.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -28,8 +26,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ abstract class AbstractWriterTestCase extends TestCase diff --git a/test/Writer/IniTest.php b/test/Writer/IniTest.php index 94a0401..41dea5e 100644 --- a/test/Writer/IniTest.php +++ b/test/Writer/IniTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -29,8 +27,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class IniTest extends AbstractWriterTestCase diff --git a/test/Writer/JsonTest.php b/test/Writer/JsonTest.php index 44656bc..91887e0 100644 --- a/test/Writer/JsonTest.php +++ b/test/Writer/JsonTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -29,8 +27,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class JsonTest extends AbstractWriterTestCase diff --git a/test/Writer/PhpArrayTest.php b/test/Writer/PhpArrayTest.php index 8caf8e3..b850cd3 100644 --- a/test/Writer/PhpArrayTest.php +++ b/test/Writer/PhpArrayTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -29,8 +27,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class PhpArrayTest extends AbstractWriterTestCase diff --git a/test/Writer/XmlTest.php b/test/Writer/XmlTest.php index ed8ad5a..700fa5c 100644 --- a/test/Writer/XmlTest.php +++ b/test/Writer/XmlTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -29,8 +27,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class XmlTest extends AbstractWriterTestCase diff --git a/test/Writer/YamlTest.php b/test/Writer/YamlTest.php index b21886c..ed71928 100644 --- a/test/Writer/YamlTest.php +++ b/test/Writer/YamlTest.php @@ -15,8 +15,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @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; @@ -29,8 +27,6 @@ * @category Zend * @package Zend_Config * @subpackage UnitTests - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License * @group Zend_Config */ class YamlTest extends AbstractWriterTestCase From 391092327935930491946581319038e333d2ca87 Mon Sep 17 00:00:00 2001 From: Maks3w Date: Mon, 9 Jul 2012 16:41:27 +0200 Subject: [PATCH 03/12] [CS][Tests] Set File Header http://framework.zend.com/wiki/display/ZFDEV2/Coding+Standards#CodingStandards-Files The following script replaces the content between PHP open tag and namespace declaration. for COMPONENT in $(ls -d *) do for FILE in $(find $COMPONENT -name "*.php") do BLOCK="\/\*\*\n \* Zend Framework \(http:\/\/framework\.zend\.com\/\)\n \*\n \* \@link http:\/\/github\.com\/zendframework\/zf2 for the canonical source repository\n \* \@copyright Copyright \(c\) 2005-2012 Zend Technologies USA Inc\. \(http:\/\/www\.zend\.com\)\n \* \@license http:\/\/framework\.zend\.com\/license\/new-bsd New BSD License\n \* \@package Zend_$COMPONENT\n \*\/" perl -0777 -i -pe "s/(<\?php(\s*.*)*\nn)/ Date: Mon, 9 Jul 2012 16:46:59 -0500 Subject: [PATCH 04/12] [zen-49] Correct import statements across framework - Ran a script that would create multiple import statements out of multi-line import statements, and which would sort all import statements in alphabetic order. Script is at https://gist.github.com/3079222 and was run by dropping into the library/Zend folder and typing (in zsh) "for file in **/*.php;do php /path/to/replace-uses.php $file; done" --- src/Config.php | 2 +- src/Processor/Queue.php | 2 +- src/Processor/Token.php | 2 +- src/Reader/Json.php | 2 +- src/Writer/AbstractWriter.php | 2 +- src/Writer/Xml.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Config.php b/src/Config.php index 70fa03a..ece2b09 100644 --- a/src/Config.php +++ b/src/Config.php @@ -10,9 +10,9 @@ namespace Zend\Config; +use ArrayAccess; use Countable; use Iterator; -use ArrayAccess; use Zend\Stdlib\ArrayUtils; /** diff --git a/src/Processor/Queue.php b/src/Processor/Queue.php index e369149..fb276ba 100644 --- a/src/Processor/Queue.php +++ b/src/Processor/Queue.php @@ -11,8 +11,8 @@ namespace Zend\Config\Processor; use Zend\Config\Config; -use Zend\Stdlib\PriorityQueue; use Zend\Config\Exception; +use Zend\Stdlib\PriorityQueue; /** * @category Zend diff --git a/src/Processor/Token.php b/src/Processor/Token.php index cf725ba..022daf5 100644 --- a/src/Processor/Token.php +++ b/src/Processor/Token.php @@ -10,9 +10,9 @@ namespace Zend\Config\Processor; +use Traversable; use Zend\Config\Config; use Zend\Config\Exception; -use Traversable; /** * @category Zend diff --git a/src/Reader/Json.php b/src/Reader/Json.php index 01a5f9e..a84b7e4 100644 --- a/src/Reader/Json.php +++ b/src/Reader/Json.php @@ -11,8 +11,8 @@ namespace Zend\Config\Reader; use Zend\Config\Exception; -use Zend\Json\Json as JsonFormat; use Zend\Json\Exception as JsonException; +use Zend\Json\Json as JsonFormat; /** * JSON config reader. diff --git a/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php index 1d6df80..b2817ec 100644 --- a/src/Writer/AbstractWriter.php +++ b/src/Writer/AbstractWriter.php @@ -11,8 +11,8 @@ namespace Zend\Config\Writer; use Traversable; -use Zend\Config\Exception; use Zend\Config\Config; +use Zend\Config\Exception; use Zend\Stdlib\ArrayUtils; /** diff --git a/src/Writer/Xml.php b/src/Writer/Xml.php index 1e6ec03..c4e0827 100644 --- a/src/Writer/Xml.php +++ b/src/Writer/Xml.php @@ -10,8 +10,8 @@ namespace Zend\Config\Writer; -use Zend\Config\Exception; use XMLWriter; +use Zend\Config\Exception; /** * @category Zend From 24c143c990aa0d8b28acfab233d02da94311eac2 Mon Sep 17 00:00:00 2001 From: Maks3w Date: Thu, 12 Jul 2012 21:11:36 +0200 Subject: [PATCH 05/12] [PSR-2] fixers=braces,elseif,short_tag,php_closing_tag,trailing_spaces,linefeed Applied php-cs-fixer --fixers=braces,elseif,short_tag,php_closing_tag,trailing_spaces,linefeed --- src/Factory.php | 12 ++++----- src/Processor/Filter.php | 2 +- src/Reader/Ini.php | 4 +-- src/Reader/Json.php | 18 ++++++------- src/Reader/Xml.php | 8 +++--- src/Reader/Yaml.php | 24 ++++++++--------- src/ReaderPluginManager.php | 4 +-- src/Writer/AbstractWriter.php | 4 +-- src/Writer/Xml.php | 2 +- src/Writer/Yaml.php | 8 +++--- test/ConfigTest.php | 12 ++++----- test/FactoryTest.php | 16 ++++++------ test/ProcessorTest.php | 36 +++++++++++++------------- test/Reader/AbstractReaderTestCase.php | 12 ++++----- test/Reader/IniTest.php | 16 ++++++------ test/Reader/JsonTest.php | 20 +++++++------- test/Reader/XmlTest.php | 12 ++++----- test/Reader/YamlTest.php | 18 ++++++------- test/Writer/AbstractWriterTestCase.php | 14 +++++----- test/Writer/PhpArrayTest.php | 4 +-- test/Writer/XmlTest.php | 8 +++--- test/Writer/YamlTest.php | 6 ++--- 22 files changed, 129 insertions(+), 131 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index e18b2d1..4631562 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -43,7 +43,7 @@ class Factory * Read a config from a file. * * @param string $filename - * @param boolean $returnConfigObject + * @param boolean $returnConfigObject * @return array|Config * @throws Exception\InvalidArgumentException * @throws Exception\RuntimeException @@ -51,16 +51,16 @@ class Factory public static function fromFile($filename, $returnConfigObject = false) { $pathinfo = pathinfo($filename); - + if (!isset($pathinfo['extension'])) { throw new Exception\RuntimeException(sprintf( 'Filename "%s" is missing an extension and cannot be auto-detected', $filename )); } - + $extension = strtolower($pathinfo['extension']); - + if ($extension === 'php') { if (!is_file($filename) || !is_readable($filename)) { throw new Exception\RuntimeException(sprintf( @@ -68,7 +68,7 @@ public static function fromFile($filename, $returnConfigObject = false) $filename )); } - + $config = include $filename; } elseif (isset(self::$extensions[$extension])) { $reader = self::$extensions[$extension]; @@ -93,7 +93,7 @@ public static function fromFile($filename, $returnConfigObject = false) * Read configuration from multiple files and merge them. * * @param array $files - * @param boolean $returnConfigObject + * @param boolean $returnConfigObject * @return array|Config */ public static function fromFiles(array $files, $returnConfigObject = false) diff --git a/src/Processor/Filter.php b/src/Processor/Filter.php index e8154da..1ed0f31 100644 --- a/src/Processor/Filter.php +++ b/src/Processor/Filter.php @@ -56,7 +56,7 @@ public function getFilter() /** * Process - * + * * @param Config $config * @return Config * @throws Exception\InvalidArgumentException diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php index b02df3b..6498c0f 100644 --- a/src/Reader/Ini.php +++ b/src/Reader/Ini.php @@ -86,7 +86,7 @@ function($error, $message = '', $file = '', $line = 0) use ($filename) { ); $ini = parse_ini_file($filename, true); restore_error_handler(); - + return $this->process($ini); } @@ -114,7 +114,7 @@ function($error, $message = '', $file = '', $line = 0) { ); $ini = parse_ini_string($string, true); restore_error_handler(); - + return $this->process($ini); } diff --git a/src/Reader/Json.php b/src/Reader/Json.php index a84b7e4..5d6b7bd 100644 --- a/src/Reader/Json.php +++ b/src/Reader/Json.php @@ -46,15 +46,15 @@ public function fromFile($filename) $filename )); } - + $this->directory = dirname($filename); - + try { $config = JsonFormat::decode(file_get_contents($filename), JsonFormat::TYPE_ARRAY); } catch (JsonException\RuntimeException $e) { throw new Exception\RuntimeException($e->getMessage()); - } - + } + return $this->process($config); } @@ -73,19 +73,19 @@ public function fromString($string) } $this->directory = null; - + try { $config = JsonFormat::decode($string, JsonFormat::TYPE_ARRAY); } catch (JsonException\RuntimeException $e) { throw new Exception\RuntimeException($e->getMessage()); - } - + } + return $this->process($config); } /** * Process the array for @include - * + * * @param array $data * @return array * @throws Exception\RuntimeException @@ -103,7 +103,7 @@ protected function process(array $data) $reader = clone $this; unset($data[$key]); $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value)); - } + } } return $data; } diff --git a/src/Reader/Xml.php b/src/Reader/Xml.php index ed6ebe8..98a1d0f 100644 --- a/src/Reader/Xml.php +++ b/src/Reader/Xml.php @@ -80,7 +80,7 @@ function($error, $message = '', $file = '', $line = 0) use ($filename) { ); $return = $this->process(); restore_error_handler(); - + return $return; } @@ -98,7 +98,7 @@ public function fromString($string) return array(); } $this->reader = new XMLReader(); - + $this->reader->xml($string, null, LIBXML_XINCLUDE); $this->directory = null; @@ -113,7 +113,7 @@ function($error, $message = '', $file = '', $line = 0) { ); $return = $this->process(); restore_error_handler(); - + return $return; } @@ -175,7 +175,7 @@ protected function processNextElement() $text .= $this->reader->value; } } - + return $children ?: $text; } diff --git a/src/Reader/Yaml.php b/src/Reader/Yaml.php index 5c638cc..c33ef29 100644 --- a/src/Reader/Yaml.php +++ b/src/Reader/Yaml.php @@ -23,21 +23,21 @@ class Yaml implements ReaderInterface { /** * Directory of the YAML file - * + * * @var string */ protected $directory; /** * YAML decoder callback - * + * * @var callable */ protected $yamlDecoder; /** * Constructor - * + * * @param callable $yamlDecoder */ public function __construct($yamlDecoder = null) @@ -99,14 +99,14 @@ public function fromFile($filename) if (null === $this->getYamlDecoder()) { throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder"); } - + $this->directory = dirname($filename); - + $config = call_user_func($this->getYamlDecoder(), file_get_contents($filename)); if (null === $config) { throw new Exception\RuntimeException("Error parsing YAML data"); - } - + } + return $this->process($config); } @@ -126,14 +126,14 @@ public function fromString($string) if (empty($string)) { return array(); } - + $this->directory = null; - + $config = call_user_func($this->getYamlDecoder(), $string); if (null === $config) { throw new Exception\RuntimeException("Error parsing YAML data"); - } - + } + return $this->process($config); } @@ -157,7 +157,7 @@ protected function process(array $data) $reader = clone $this; unset($data[$key]); $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value)); - } + } } return $data; } diff --git a/src/ReaderPluginManager.php b/src/ReaderPluginManager.php index c059725..2614fd0 100644 --- a/src/ReaderPluginManager.php +++ b/src/ReaderPluginManager.php @@ -20,7 +20,7 @@ class ReaderPluginManager extends AbstractPluginManager { /** * Default set of readers - * + * * @var array */ protected $invokableClasses = array( @@ -33,7 +33,7 @@ class ReaderPluginManager extends AbstractPluginManager /** * Validate the plugin * Checks that the reader loaded is an instance of Reader\ReaderInterface. - * + * * @param Reader\ReaderInterface $plugin * @return void * @throws Exception\InvalidArgumentException if invalid diff --git a/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php index b2817ec..4726075 100644 --- a/src/Writer/AbstractWriter.php +++ b/src/Writer/AbstractWriter.php @@ -38,12 +38,12 @@ public function toFile($filename, $config, $exclusiveLock = true) 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( diff --git a/src/Writer/Xml.php b/src/Writer/Xml.php index c4e0827..844a38f 100644 --- a/src/Writer/Xml.php +++ b/src/Writer/Xml.php @@ -71,7 +71,7 @@ protected function addBranch($branchName, array $config, XMLWriter $writer) $writer->startElement($branchName); $branchType = 'string'; } - } else if ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) { + } elseif ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) { throw new Exception\RuntimeException('Mixing of string and numeric keys is not allowed'); } diff --git a/src/Writer/Yaml.php b/src/Writer/Yaml.php index fc4e8e8..9d4c309 100644 --- a/src/Writer/Yaml.php +++ b/src/Writer/Yaml.php @@ -21,14 +21,14 @@ class Yaml extends AbstractWriter { /** * YAML encoder callback - * + * * @var callable */ protected $yamlEncoder; /** * Constructor - * + * * @param callable|string|null $yamlEncoder */ public function __construct($yamlEncoder = null) @@ -80,12 +80,12 @@ public function processConfig(array $config) if (null === $this->getYamlEncoder()) { throw new Exception\RuntimeException("You didn't specify a Yaml callback encoder"); } - + $config = call_user_func($this->getYamlEncoder(), $config); if (null === $config) { throw new Exception\RuntimeException("Error generating YAML data"); } - + return $config; } } diff --git a/test/ConfigTest.php b/test/ConfigTest.php index fb91052..25eac99 100644 --- a/test/ConfigTest.php +++ b/test/ConfigTest.php @@ -483,8 +483,7 @@ public function testUnsettingFirstElementDuringForeachDoesNotSkipAnElement() ), true); $keyList = array(); - foreach ($config as $key => $value) - { + foreach ($config as $key => $value) { $keyList[] = $key; if ($key == 'first') { unset($config->$key); // uses magic Zend\Config\Config::__unset() method @@ -509,8 +508,7 @@ public function testUnsettingAMiddleElementDuringForeachDoesNotSkipAnElement() ), true); $keyList = array(); - foreach ($config as $key => $value) - { + foreach ($config as $key => $value) { $keyList[] = $key; if ($key == 'second') { unset($config->$key); // uses magic Zend\Config\Config::__unset() method @@ -535,8 +533,7 @@ public function testUnsettingLastElementDuringForeachDoesNotSkipAnElement() ), true); $keyList = array(); - foreach ($config as $key => $value) - { + foreach ($config as $key => $value) { $keyList[] = $key; if ($key == 'third') { unset($config->$key); // uses magic Zend\Config\Config::__unset() method @@ -576,7 +573,8 @@ public function testZF6995_toArrayDoesNotDisturbInternalIterator() * @depends testMerge * @link http://framework.zend.com/issues/browse/ZF2-186 */ - public function testZF2_186_mergeReplacingUnnamedConfigSettings(){ + public function testZF2_186_mergeReplacingUnnamedConfigSettings() + { $arrayA = array( 'flag' => true, 'text' => 'foo', diff --git a/test/FactoryTest.php b/test/FactoryTest.php index 466c90f..ffd4836 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -23,17 +23,17 @@ class FactoryTest extends \PHPUnit_Framework_TestCase public function testFromIni() { $config = Factory::fromFile(__DIR__ . '/TestAssets/Ini/include-base.ini'); - + $this->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 ( @@ -45,7 +45,7 @@ public function testFromIniFiles() $this->assertEquals('bar', $config['base']['foo']); $this->assertEquals('baz', $config['test']['bar']); } - + public function testFromXmlFiles() { $files = array ( @@ -57,7 +57,7 @@ public function testFromXmlFiles() $this->assertEquals('bar', $config['base']['foo']); $this->assertEquals('baz', $config['test']['bar']); } - + public function testFromPhpFiles() { $files = array ( @@ -69,7 +69,7 @@ public function testFromPhpFiles() $this->assertEquals('bar', $config['base']['foo']); $this->assertEquals('baz', $config['test']['bar']); } - + public function testFromIniAndXmlAndPhpFiles() { $files = array ( @@ -89,7 +89,7 @@ public function testReturnsConfigObjectIfRequestedAndArrayOtherwise() $files = array ( __DIR__ . '/TestAssets/Ini/include-base.ini', ); - + $configArray = Factory::fromFile($files[0]); $this->assertTrue(is_array($configArray)); diff --git a/test/ProcessorTest.php b/test/ProcessorTest.php index 9adc3fe..aaeb368 100644 --- a/test/ProcessorTest.php +++ b/test/ProcessorTest.php @@ -181,7 +181,7 @@ public function testAddInvalidToken() 'Cannot use ' . gettype(array()) . ' as token name.'); $processor->addToken(array(), 'bar'); } - + public function testSingleValueToken() { $processor = new TokenProcessor(); @@ -190,18 +190,18 @@ public function testSingleValueToken() $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 process config because it is read-only'); $processor->process($config); } - + public function testTokenPrefix() { $config = new Config($this->tokenPrefix, true); @@ -287,7 +287,7 @@ public function testUserConstants() $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); @@ -305,17 +305,17 @@ public function testUserOnlyConstants() $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 */ @@ -358,7 +358,7 @@ public function testTranslatorReadOnly() } public function testTranslatorSingleValue() - { + { $translator = new Translator(); $translator->addTranslationFile('phparray', $this->translatorFile); $processor = new TranslatorProcessor($translator); @@ -371,7 +371,7 @@ public function testFilter() $config = new Config($this->filter, true); $filter = new StringToLower(); $processor = new FilterProcessor($filter); - + $this->assertTrue($processor->getFilter() instanceof StringToLower); $processor->process($config); @@ -384,21 +384,21 @@ public function testFilterReadOnly() $config = new Config($this->filter, false); $filter = new StringToLower(); $processor = new FilterProcessor($filter); - + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Cannot process 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 */ @@ -421,7 +421,7 @@ public function testQueueFIFO() $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); @@ -433,7 +433,7 @@ public function testQueueReadOnly() */ $queue = new Queue(); $queue->insert($lowerProcessor); - + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'Cannot process config because it is read-only'); $queue->process($config); @@ -452,10 +452,10 @@ public function testQueueSingleValue() $queue = new Queue(); $queue->insert($upperProcessor); $queue->insert($lowerProcessor); - + $data ='TeSt'; $this->assertEquals('test', $queue->processValue($data)); - + } /** diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php index 05db52c..1e45a5c 100644 --- a/test/Reader/AbstractReaderTestCase.php +++ b/test/Reader/AbstractReaderTestCase.php @@ -26,28 +26,28 @@ abstract class AbstractReaderTestCase extends TestCase * @var ReaderInterface */ protected $reader; - + /** * Get test asset name for current test case. - * + * * @param string $name * @return string */ abstract protected function getTestAssetPath($name); - + public function testMissingFile() { $filename = $this->getTestAssetPath('no-file'); $this->setExpectedException('Zend\Config\Exception\RuntimeException', "doesn't exist or not readable"); - $config = $this->reader->fromFile($filename); + $config = $this->reader->fromFile($filename); } - + public function testFromFile() { $config = $this->reader->fromFile($this->getTestAssetPath('include-base')); $this->assertEquals('foo', $config['foo']); } - + public function testFromEmptyString() { $config = $this->reader->fromString(''); diff --git a/test/Reader/IniTest.php b/test/Reader/IniTest.php index e17452a..f814218 100644 --- a/test/Reader/IniTest.php +++ b/test/Reader/IniTest.php @@ -24,10 +24,10 @@ public function setUp() { $this->reader = new Ini(); } - + /** * getTestAssetPath(): defined by AbstractReaderTestCase. - * + * * @see AbstractReaderTestCase::getTestAssetPath() * @return string */ @@ -35,14 +35,14 @@ protected function getTestAssetPath($name) { return __DIR__ . '/TestAssets/Ini/' . $name . '.ini'; } - + public function testInvalidIniFile() { $this->reader = new Ini(); $this->setExpectedException('Zend\Config\Exception\RuntimeException'); $arrayIni = $this->reader->fromFile($this->getTestAssetPath('invalid')); } - + public function testFromString() { $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 = <<reader->fromString($ini); $this->assertEquals($arrayIni['all']['test'], 'foo'); $this->assertEquals($arrayIni['all']['bar'][0], 'baz'); diff --git a/test/Reader/JsonTest.php b/test/Reader/JsonTest.php index 0832624..20cc681 100644 --- a/test/Reader/JsonTest.php +++ b/test/Reader/JsonTest.php @@ -24,10 +24,10 @@ public function setUp() { $this->reader = new Json(); } - + /** * getTestAssetPath(): defined by AbstractReaderTestCase. - * + * * @see AbstractReaderTestCase::getTestAssetPath() * @return string */ @@ -35,36 +35,36 @@ protected function getTestAssetPath($name) { return __DIR__ . '/TestAssets/Json/' . $name . '.json'; } - + public function testInvalidJsonFile() { $this->setExpectedException('Zend\Config\Exception\RuntimeException'); $arrayJson = $this->reader->fromFile($this->getTestAssetPath('invalid')); } - + public function testIncludeAsElement() { $arrayJson = $this->reader->fromFile($this->getTestAssetPath('include-base_nested')); $this->assertEquals($arrayJson['bar']['foo'], 'foo'); } - + public function testFromString() { $json = '{ "test" : "foo", "bar" : [ "baz", "foo" ] }'; - + $arrayJson = $this->reader->fromString($json); - + $this->assertEquals($arrayJson['test'], 'foo'); $this->assertEquals($arrayJson['bar'][0], 'baz'); $this->assertEquals($arrayJson['bar'][1], 'foo'); } - + public function testInvalidString() { $json = '{"foo":"bar"'; - + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); $arrayIni = $this->reader->fromString($json); } - + } diff --git a/test/Reader/XmlTest.php b/test/Reader/XmlTest.php index 066a1eb..9258a74 100644 --- a/test/Reader/XmlTest.php +++ b/test/Reader/XmlTest.php @@ -24,10 +24,10 @@ public function setUp() { $this->reader = new Xml(); } - + /** * getTestAssetPath(): defined by AbstractReaderTestCase. - * + * * @see AbstractReaderTestCase::getTestAssetPath() * @return string */ @@ -35,14 +35,14 @@ protected function getTestAssetPath($name) { return __DIR__ . '/TestAssets/Xml/' . $name . '.xml'; } - + public function testInvalidXmlFile() { $this->reader = new Xml(); $this->setExpectedException('Zend\Config\Exception\RuntimeException'); $arrayXml = $this->reader->fromFile($this->getTestAssetPath('invalid')); } - + public function testFromString() { $xml = << 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 = <<markTestSkipped('Yaml test for Zend\Config skipped'); } - + if (constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE')) { require_once constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE'); } - + $yamlReader = explode('::', constant('TESTS_ZEND_CONFIG_READER_YAML_CALLBACK')); if (isset($yamlReader[1])) { $this->reader = new YamlReader(array($yamlReader[0], $yamlReader[1])); @@ -38,10 +38,10 @@ public function setUp() $this->reader = new YamlReader(array($yamlReader[0])); } } - + /** * getTestAssetPath(): defined by AbstractReaderTestCase. - * + * * @see AbstractReaderTestCase::getTestAssetPath() * @return string */ @@ -49,13 +49,13 @@ protected function getTestAssetPath($name) { return __DIR__ . '/TestAssets/Yaml/' . $name . '.yaml'; } - + public function testInvalidIniFile() { $this->setExpectedException('Zend\Config\Exception\RuntimeException'); $arrayIni = $this->reader->fromFile($this->getTestAssetPath('invalid')); } - + public function testFromString() { $yaml = <<reader->fromString($yaml); $this->assertEquals($arrayYaml['test'], 'foo'); $this->assertEquals($arrayYaml['bar'][0], 'baz'); $this->assertEquals($arrayYaml['bar'][1], 'foo'); } - + public function testFromStringWithSection() { $yaml = <<tmpfile; } - + public function tearDown() { if (file_exists($this->getTestAssetFileName())) { @@ -60,7 +60,7 @@ public function tearDown() @unlink($this->getTestAssetFileName()); } } - + public function testNoFilenameSet() { $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'No file name specified'); @@ -72,7 +72,7 @@ public function testFileNotValid() $this->setExpectedException('Zend\Config\Exception\RuntimeException'); $this->writer->toFile('.', new Config(array())); } - + public function testFileNotWritable() { $this->setExpectedException('Zend\Config\Exception\RuntimeException'); diff --git a/test/Writer/PhpArrayTest.php b/test/Writer/PhpArrayTest.php index 80d2e80..2dae349 100644 --- a/test/Writer/PhpArrayTest.php +++ b/test/Writer/PhpArrayTest.php @@ -36,7 +36,7 @@ public function setUp() 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. @@ -49,7 +49,7 @@ public function testRender() $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 f2a8a7d..16f0c70 100644 --- a/test/Writer/XmlTest.php +++ b/test/Writer/XmlTest.php @@ -48,7 +48,7 @@ public function testToString() $this->assertEquals($expected, $configString); } - + public function testSectionsToString() { $config = new Config(array(), true); @@ -61,9 +61,9 @@ public function testSectionsToString() $config->production->database->params->username = 'production'; $config->production->database->params->password = 'secret'; $config->production->database->params->dbname = 'dbproduction'; - + $configString = $this->writer->toString($config); - + $expected = << @@ -81,7 +81,7 @@ public function testSectionsToString() ECS; - + $this->assertEquals($expected, $configString); } } diff --git a/test/Writer/YamlTest.php b/test/Writer/YamlTest.php index cc2c864..d0d9db1 100644 --- a/test/Writer/YamlTest.php +++ b/test/Writer/YamlTest.php @@ -27,18 +27,18 @@ public function setUp() if (!constant('TESTS_ZEND_CONFIG_YAML_ENABLED')) { $this->markTestSkipped('Yaml test for Zend\Config skipped'); } - + if (constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE')) { require_once constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE'); } - + $yamlReader = explode('::', constant('TESTS_ZEND_CONFIG_READER_YAML_CALLBACK')); if (isset($yamlReader[1])) { $this->reader = new YamlReader(array($yamlReader[0], $yamlReader[1])); } else { $this->reader = new YamlReader(array($yamlReader[0])); } - + $yamlWriter = explode('::', constant('TESTS_ZEND_CONFIG_WRITER_YAML_CALLBACK')); if (isset($yamlWriter[1])) { $this->writer = new YamlWriter(array($yamlWriter[0], $yamlWriter[1])); From 9de26ba1138f2321aa92102849d928409fc97ded Mon Sep 17 00:00:00 2001 From: Robert Boloc Date: Fri, 24 Aug 2012 12:25:30 +0200 Subject: [PATCH 06/12] removed extra spaces from test file --- test/Reader/IniTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Reader/IniTest.php b/test/Reader/IniTest.php index 3ddd24f..7c7a316 100644 --- a/test/Reader/IniTest.php +++ b/test/Reader/IniTest.php @@ -84,7 +84,7 @@ public function testFromStringWithSection() $this->assertEquals($arrayIni['all']['bar'][1], 'foo'); } - public function testFromStringNested() + public function testFromStringNested() { $ini = << Date: Fri, 24 Aug 2012 12:37:01 +0200 Subject: [PATCH 07/12] removed trailing spaces --- test/Reader/IniTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Reader/IniTest.php b/test/Reader/IniTest.php index 7c7a316..66484b9 100644 --- a/test/Reader/IniTest.php +++ b/test/Reader/IniTest.php @@ -83,7 +83,7 @@ public function testFromStringWithSection() $this->assertEquals($arrayIni['all']['bar'][0], 'baz'); $this->assertEquals($arrayIni['all']['bar'][1], 'foo'); } - + public function testFromStringNested() { $ini = <<assertEquals($arrayIni['foobar'][0], 'foobarArray'); $this->assertEquals($arrayIni['foo']['baz'][0], 'foobaz1'); $this->assertEquals($arrayIni['foo']['baz'][1], 'foobaz2'); - } + } } From 1a420ec08d6b0d205fdc171bfd05623dca0e1fc0 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Fri, 31 Aug 2012 14:44:59 -0500 Subject: [PATCH 08/12] [zendframework/zf2#2284][ZF2-507] Updated README - Notice about Date header --- .coveralls.yml | 3 + .gitattributes | 6 + .gitignore | 14 + .php_cs | 43 ++ .travis.yml | 35 + CONTRIBUTING.md | 229 +++++++ LICENSE.txt | 27 + README.md | 10 + composer.json | 45 ++ phpunit.xml.dist | 42 ++ phpunit.xml.travis | 45 ++ src/Config.php | 404 +++++++++++ src/Exception/ExceptionInterface.php | 19 + src/Exception/InvalidArgumentException.php | 19 + src/Exception/RuntimeException.php | 19 + src/Factory.php | 155 +++++ src/Processor/Constant.php | 89 +++ src/Processor/Filter.php | 94 +++ src/Processor/ProcessorInterface.php | 37 + src/Processor/Queue.php | 58 ++ src/Processor/Token.php | 247 +++++++ src/Processor/Translator.php | 146 ++++ src/Reader/Ini.php | 207 ++++++ src/Reader/Json.php | 110 +++ src/Reader/ReaderInterface.php | 35 + src/Reader/Xml.php | 201 ++++++ src/Reader/Yaml.php | 164 +++++ src/ReaderPluginManager.php | 54 ++ src/Writer/AbstractWriter.php | 83 +++ src/Writer/Ini.php | 189 ++++++ src/Writer/Json.php | 32 + src/Writer/PhpArray.php | 33 + src/Writer/WriterInterface.php | 37 + src/Writer/Xml.php | 97 +++ src/Writer/Yaml.php | 91 +++ test/ConfigTest.php | 635 ++++++++++++++++++ test/FactoryTest.php | 143 ++++ test/ProcessorTest.php | 495 ++++++++++++++ test/Reader/AbstractReaderTestCase.php | 56 ++ test/Reader/IniTest.php | 103 +++ test/Reader/JsonTest.php | 70 ++ test/Reader/TestAssets/DummyReader.php | 35 + test/Reader/TestAssets/Ini/include-base.ini | 1 + test/Reader/TestAssets/Ini/include-target.ini | 1 + test/Reader/TestAssets/Ini/invalid.ini | 2 + test/Reader/TestAssets/Json/include-base.json | 3 + .../TestAssets/Json/include-base_nested.json | 3 + .../TestAssets/Json/include-target.json | 3 + test/Reader/TestAssets/Json/invalid.json | 3 + test/Reader/TestAssets/Xml/array.xml | 31 + test/Reader/TestAssets/Xml/include-base.xml | 4 + test/Reader/TestAssets/Xml/include-target.xml | 2 + test/Reader/TestAssets/Xml/invalid.xml | 4 + test/Reader/TestAssets/Yaml/include-base.yaml | 1 + .../TestAssets/Yaml/include-target.yaml | 1 + test/Reader/XmlTest.php | 98 +++ test/Reader/YamlTest.php | 91 +++ test/TestAssets/Ini/include-base.ini | 2 + test/TestAssets/Ini/include-base2.ini | 2 + test/TestAssets/Php/include-base.php | 6 + test/TestAssets/Php/include-base2.php | 6 + test/TestAssets/Php/include-base3.php | 6 + test/TestAssets/Xml/include-base.xml | 6 + test/TestAssets/Xml/include-base2.xml | 6 + test/TestAssets/bad.ext | 0 test/TestAssets/dummy.dum | 1 + test/Writer/AbstractWriterTestCase.php | 93 +++ test/Writer/IniTest.php | 53 ++ test/Writer/JsonTest.php | 54 ++ test/Writer/PhpArrayTest.php | 55 ++ test/Writer/TestAssets/PhpReader.php | 19 + test/Writer/XmlTest.php | 87 +++ test/Writer/YamlTest.php | 73 ++ test/Writer/_files/allsections.ini | 26 + test/Writer/_files/allsections.json | 45 ++ test/Writer/_files/allsections.xml | 35 + test/Writer/_files/allsections.yaml | 35 + test/_files/indentedcomments.yaml | 4 + test/_files/inlinecomments.yaml | 3 + test/_files/listbooleans.yaml | 51 ++ test/_files/listconstants.yaml | 4 + test/_files/translations-de_DE.php | 5 + test/bootstrap.php | 34 + 83 files changed, 5615 insertions(+) create mode 100644 .coveralls.yml create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .php_cs create mode 100644 .travis.yml create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 phpunit.xml.travis create mode 100644 src/Config.php create mode 100644 src/Exception/ExceptionInterface.php create mode 100644 src/Exception/InvalidArgumentException.php create mode 100644 src/Exception/RuntimeException.php create mode 100644 src/Factory.php create mode 100644 src/Processor/Constant.php create mode 100644 src/Processor/Filter.php create mode 100644 src/Processor/ProcessorInterface.php create mode 100644 src/Processor/Queue.php create mode 100644 src/Processor/Token.php create mode 100644 src/Processor/Translator.php create mode 100644 src/Reader/Ini.php create mode 100644 src/Reader/Json.php create mode 100644 src/Reader/ReaderInterface.php create mode 100644 src/Reader/Xml.php create mode 100644 src/Reader/Yaml.php create mode 100644 src/ReaderPluginManager.php create mode 100644 src/Writer/AbstractWriter.php create mode 100644 src/Writer/Ini.php create mode 100644 src/Writer/Json.php create mode 100644 src/Writer/PhpArray.php create mode 100644 src/Writer/WriterInterface.php create mode 100644 src/Writer/Xml.php create mode 100644 src/Writer/Yaml.php create mode 100644 test/ConfigTest.php create mode 100644 test/FactoryTest.php create mode 100644 test/ProcessorTest.php create mode 100644 test/Reader/AbstractReaderTestCase.php create mode 100644 test/Reader/IniTest.php create mode 100644 test/Reader/JsonTest.php create mode 100644 test/Reader/TestAssets/DummyReader.php 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/invalid.ini create mode 100644 test/Reader/TestAssets/Json/include-base.json create mode 100644 test/Reader/TestAssets/Json/include-base_nested.json create mode 100644 test/Reader/TestAssets/Json/include-target.json create mode 100644 test/Reader/TestAssets/Json/invalid.json create mode 100644 test/Reader/TestAssets/Xml/array.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/invalid.xml create mode 100644 test/Reader/TestAssets/Yaml/include-base.yaml create mode 100644 test/Reader/TestAssets/Yaml/include-target.yaml create mode 100644 test/Reader/XmlTest.php create mode 100644 test/Reader/YamlTest.php create mode 100644 test/TestAssets/Ini/include-base.ini create mode 100644 test/TestAssets/Ini/include-base2.ini create mode 100644 test/TestAssets/Php/include-base.php create mode 100644 test/TestAssets/Php/include-base2.php create mode 100644 test/TestAssets/Php/include-base3.php create mode 100644 test/TestAssets/Xml/include-base.xml create mode 100644 test/TestAssets/Xml/include-base2.xml create mode 100644 test/TestAssets/bad.ext create mode 100644 test/TestAssets/dummy.dum create mode 100644 test/Writer/AbstractWriterTestCase.php create mode 100644 test/Writer/IniTest.php create mode 100644 test/Writer/JsonTest.php create mode 100644 test/Writer/PhpArrayTest.php create mode 100644 test/Writer/TestAssets/PhpReader.php create mode 100644 test/Writer/XmlTest.php create mode 100644 test/Writer/YamlTest.php create mode 100644 test/Writer/_files/allsections.ini create mode 100644 test/Writer/_files/allsections.json create mode 100644 test/Writer/_files/allsections.xml create mode 100644 test/Writer/_files/allsections.yaml create mode 100644 test/_files/indentedcomments.yaml create mode 100644 test/_files/inlinecomments.yaml create mode 100644 test/_files/listbooleans.yaml create mode 100644 test/_files/listconstants.yaml create mode 100644 test/_files/translations-de_DE.php create mode 100644 test/bootstrap.php diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..53bda82 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,3 @@ +coverage_clover: clover.xml +json_path: coveralls-upload.json +src_dir: src diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..85dc9a8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +/test export-ignore +/vendor export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.travis.yml export-ignore +.php_cs export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4cac0a2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.buildpath +.DS_Store +.idea +.project +.settings/ +.*.sw* +.*.un~ +nbproject +tmp/ + +clover.xml +coveralls-upload.json +phpunit.xml +vendor diff --git a/.php_cs b/.php_cs new file mode 100644 index 0000000..bf4b799 --- /dev/null +++ b/.php_cs @@ -0,0 +1,43 @@ +notPath('TestAsset') + ->notPath('_files') + ->filter(function (SplFileInfo $file) { + if (strstr($file->getPath(), 'compatibility')) { + return false; + } + }); +$config = Symfony\CS\Config\Config::create(); +$config->level(null); +$config->fixers( + array( + 'braces', + 'duplicate_semicolon', + 'elseif', + 'empty_return', + 'encoding', + 'eof_ending', + 'function_call_space', + 'function_declaration', + 'indentation', + 'join_function', + 'line_after_namespace', + 'linefeed', + 'lowercase_keywords', + 'parenthesis', + 'multiple_use', + 'method_argument_space', + 'object_operator', + 'php_closing_tag', + 'psr0', + 'remove_lines_between_uses', + 'short_tag', + 'standardize_not_equal', + 'trailing_spaces', + 'unused_use', + 'visibility', + 'whitespacy_lines', + ) +); +$config->finder($finder); +return $config; diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..fe909ec --- /dev/null +++ b/.travis.yml @@ -0,0 +1,35 @@ +sudo: false + +language: php + +matrix: + fast_finish: true + include: + - php: 5.5 + - php: 5.6 + env: + - EXECUTE_TEST_COVERALLS=true + - EXECUTE_CS_CHECK=true + - php: 7 + - php: hhvm + allow_failures: + - php: 7 + - php: hhvm + +notifications: + irc: "irc.freenode.org#zftalk.dev" + email: false + +before_install: + - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then phpenv config-rm xdebug.ini || return 0 ; fi + +install: + - composer install --no-interaction --prefer-source + +script: + - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/phpunit -c phpunit.xml.travis --coverage-clover clover.xml ; fi + - if [[ $EXECUTE_TEST_COVERALLS != 'true' ]]; then ./vendor/bin/phpunit -c phpunit.xml.travis ; fi + - if [[ $EXECUTE_CS_CHECK == 'true' ]]; then ./vendor/bin/php-cs-fixer fix -v --diff --dry-run --config-file=.php_cs ; fi + +after_script: + - if [[ $EXECUTE_TEST_COVERALLS == 'true' ]]; then ./vendor/bin/coveralls ; fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3682dfe --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,229 @@ +# CONTRIBUTING + +## RESOURCES + +If you wish to contribute to Zend Framework, please be sure to +read/subscribe to the following resources: + + - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) + - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) + - ZF Contributor's mailing list: + Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html + Subscribe: zf-contributors-subscribe@lists.zend.com + - ZF Contributor's IRC channel: + #zftalk.dev on Freenode.net + +If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-config/issues/new). + +## Reporting Potential Security Issues + +If you have encountered a potential security vulnerability, please **DO NOT** report it on the public +issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. +We will work with you to verify the vulnerability and patch it as soon as possible. + +When reporting issues, please provide the following information: + +- Component(s) affected +- A description indicating how to reproduce the issue +- A summary of the security vulnerability and impact + +We request that you contact us via the email address above and give the project +contributors a chance to resolve the vulnerability and issue a new release prior +to any public exposure; this helps protect users and provides them with a chance +to upgrade and/or update in order to protect their applications. + +For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). + +## RUNNING TESTS + +> ### Note: testing versions prior to 2.4 +> +> This component originates with Zend Framework 2. During the lifetime of ZF2, +> testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no +> changes were necessary. However, due to the migration, tests may not run on +> versions < 2.4. As such, you may need to change the PHPUnit dependency if +> attempting a fix on such a version. + +To run tests: + +- Clone the repository: + + ```console + $ git clone git@github.com:zendframework/zend-config.git + $ cd + ``` + +- Install dependencies via composer: + + ```console + $ curl -sS https://getcomposer.org/installer | php -- + $ ./composer.phar install + ``` + + If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ + +- Run the tests via `phpunit` and the provided PHPUnit config, like in this example: + + ```console + $ ./vendor/bin/phpunit + ``` + +You can turn on conditional tests with the phpunit.xml file. +To do so: + + - Copy `phpunit.xml.dist` file to `phpunit.xml` + - Edit `phpunit.xml` to enable any specific functionality you + want to test, as well as to provide test values to utilize. + +## Running Coding Standards Checks + +This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding +standards checks, and provides configuration for our selected checks. +`php-cs-fixer` is installed by default via Composer. + +To run checks only: + +```console +$ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs +``` + +To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` +flag: + +```console +$ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs +``` + +If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure +they pass, and make sure you add and commit the changes after verification. + +## Recommended Workflow for Contributions + +Your first step is to establish a public repository from which we can +pull your work into the master repository. We recommend using +[GitHub](https://github.com), as that is where the component is already hosted. + +1. Setup a [GitHub account](http://github.com/), if you haven't yet +2. Fork the repository (http://github.com/zendframework/zend-config) +3. Clone the canonical repository locally and enter it. + + ```console + $ git clone git://github.com:zendframework/zend-config.git + $ cd zend-config + ``` + +4. Add a remote to your fork; substitute your GitHub username in the command + below. + + ```console + $ git remote add {username} git@github.com:{username}/zend-config.git + $ git fetch {username} + ``` + +### Keeping Up-to-Date + +Periodically, you should update your fork or personal repository to +match the canonical ZF repository. Assuming you have setup your local repository +per the instructions above, you can do the following: + + +```console +$ git checkout master +$ git fetch origin +$ git rebase origin/master +# OPTIONALLY, to keep your remote up-to-date - +$ git push {username} master:master +``` + +If you're tracking other branches -- for example, the "develop" branch, where +new feature development occurs -- you'll want to do the same operations for that +branch; simply substitute "develop" for "master". + +### Working on a patch + +We recommend you do each new feature or bugfix in a new branch. This simplifies +the task of code review as well as the task of merging your changes into the +canonical repository. + +A typical workflow will then consist of the following: + +1. Create a new local branch based off either your master or develop branch. +2. Switch to your new local branch. (This step can be combined with the + previous step with the use of `git checkout -b`.) +3. Do some work, commit, repeat as necessary. +4. Push the local branch to your remote repository. +5. Send a pull request. + +The mechanics of this process are actually quite trivial. Below, we will +create a branch for fixing an issue in the tracker. + +```console +$ git checkout -b hotfix/9295 +Switched to a new branch 'hotfix/9295' +``` + +... do some work ... + + +```console +$ git commit +``` + +... write your log message ... + + +```console +$ git push {username} hotfix/9295:hotfix/9295 +Counting objects: 38, done. +Delta compression using up to 2 threads. +Compression objects: 100% (18/18), done. +Writing objects: 100% (20/20), 8.19KiB, done. +Total 20 (delta 12), reused 0 (delta 0) +To ssh://git@github.com/{username}/zend-config.git + b5583aa..4f51698 HEAD -> master +``` + +To send a pull request, you have two options. + +If using GitHub, you can do the pull request from there. Navigate to +your repository, select the branch you just created, and then select the +"Pull Request" button in the upper right. Select the user/organization +"zendframework" as the recipient. + +If using your own repository - or even if using GitHub - you can use `git +format-patch` to create a patchset for us to apply; in fact, this is +**recommended** for security-related patches. If you use `format-patch`, please +send the patches as attachments to: + +- zf-devteam@zend.com for patches without security implications +- zf-security@zend.com for security patches + +#### What branch to issue the pull request against? + +Which branch should you issue a pull request against? + +- For fixes against the stable release, issue the pull request against the + "master" branch. +- For new features, or fixes that introduce new elements to the public API (such + as new public methods or properties), issue the pull request against the + "develop" branch. + +### Branch Cleanup + +As you might imagine, if you are a frequent contributor, you'll start to +get a ton of branches both locally and on your remote. + +Once you know that your changes have been accepted to the master +repository, we suggest doing some cleanup of these branches. + +- Local branch cleanup + + ```console + $ git branch -d + ``` + +- Remote branch removal + + ```console + $ git push {username} : + ``` diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..6eab5aa --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2005-2015, Zend Technologies USA, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Zend Technologies USA, Inc. nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f3ff252 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# zend-config + +`Zend\Config` is designed to simplify access to configuration data within +applications. It provides a nested object property-based user interface for +accessing this configuration data within application code. The configuration +data may come from a variety of media supporting hierarchical data storage. + + +- File issues at https://github.com/zendframework/zend-code/issues +- Documentation is at http://framework.zend.com/manual/current/en/index.html#zend-code diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..29d2be1 --- /dev/null +++ b/composer.json @@ -0,0 +1,45 @@ +{ + "name": "zendframework/zend-config", + "description": "provides a nested object property based user interface for accessing this configuration data within application code", + "license": "BSD-3-Clause", + "keywords": [ + "zf2", + "config" + ], + "homepage": "https://github.com/zendframework/zend-config", + "autoload": { + "psr-4": { + "Zend\\Config": "src/" + } + }, + "require": { + "php": ">=5.3.3", + "zendframework/zend-stdlib": "self.version" + }, + "require-dev": { + "zendframework/zend-filter": "self.version", + "zendframework/zend-i18n": "self.version", + "zendframework/zend-json": "self.version", + "zendframework/zend-servicemanager": "self.version", + "fabpot/php-cs-fixer": "1.7.*", + "satooshi/php-coveralls": "dev-master", + "phpunit/PHPUnit": "~4.0" + }, + "suggest": { + "zendframework/zend-filter": "Zend\\Filter component", + "zendframework/zend-i18n": "Zend\\I18n component", + "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes", + "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances" + }, + "extra": { + "branch-alias": { + "dev-master": "2.4-dev", + "dev-develop": "2.5-dev" + } + }, + "autoload-dev": { + "psr-4": { + "ZendTest\\Config\\": "test/" + } + } +} \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..d6be5e8 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,42 @@ + + + + + ./test/ + + + + + + disable + + + + + + ./src + + + + + + + + + + + + + + + + + diff --git a/phpunit.xml.travis b/phpunit.xml.travis new file mode 100644 index 0000000..cdfc92d --- /dev/null +++ b/phpunit.xml.travis @@ -0,0 +1,45 @@ + + + + + ./test/ + + + + + + disable + + + + + + ./src + + + + + + + + + + + + + + + + + + diff --git a/src/Config.php b/src/Config.php new file mode 100644 index 0000000..11ec759 --- /dev/null +++ b/src/Config.php @@ -0,0 +1,404 @@ +allowModifications = (boolean) $allowModifications; + + foreach ($array as $key => $value) { + if (is_array($value)) { + $this->data[$key] = new self($value, $this->allowModifications); + } else { + $this->data[$key] = $value; + } + + $this->count++; + } + } + + /** + * Retrieve a value and return $default if there is no element set. + * + * @param string $name + * @param mixed $default + * @return mixed + */ + public function get($name, $default = null) + { + if (array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + + return $default; + } + + /** + * Magic function so that $obj->value will work. + * + * @param string $name + * @return mixed + */ + public function __get($name) + { + return $this->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. + * + * @param string $name + * @param mixed $value + * @return void + * @throws Exception\RuntimeException + */ + public function __set($name, $value) + { + if ($this->allowModifications) { + + if (is_array($value)) { + $value = new self($value, true); + } + + if (null === $name) { + $this->data[] = $value; + } else { + $this->data[$name] = $value; + } + + $this->count++; + } else { + throw new Exception\RuntimeException('Config is read only'); + } + } + + /** + * Deep clone of this instance to ensure that nested Zend\Configs are also + * cloned. + * + * @return void + */ + public function __clone() + { + $array = array(); + + foreach ($this->data as $key => $value) { + if ($value instanceof self) { + $array[$key] = clone $value; + } else { + $array[$key] = $value; + } + } + + $this->data = $array; + } + + /** + * Return an associative array of the stored data. + * + * @return array + */ + public function toArray() + { + $array = array(); + $data = $this->data; + + /** @var self $value */ + foreach ($data as $key => $value) { + if ($value instanceof self) { + $array[$key] = $value->toArray(); + } else { + $array[$key] = $value; + } + } + + return $array; + } + + /** + * isset() overloading + * + * @param string $name + * @return boolean + */ + public function __isset($name) + { + return isset($this->data[$name]); + } + + /** + * unset() overloading + * + * @param string $name + * @return void + * @throws Exception\InvalidArgumentException + */ + public function __unset($name) + { + if (!$this->allowModifications) { + throw new Exception\InvalidArgumentException('Config is read only'); + } elseif (isset($this->data[$name])) { + unset($this->data[$name]); + $this->count--; + $this->skipNextIteration = true; + } + } + + /** + * count(): defined by Countable interface. + * + * @see Countable::count() + * @return integer + */ + public function count() + { + return $this->count; + } + + /** + * current(): defined by Iterator interface. + * + * @see Iterator::current() + * @return mixed + */ + public function current() + { + $this->skipNextIteration = false; + return current($this->data); + } + + /** + * key(): defined by Iterator interface. + * + * @see Iterator::key() + * @return mixed + */ + public function key() + { + return key($this->data); + } + + /** + * next(): defined by Iterator interface. + * + * @see Iterator::next() + * @return void + */ + public function next() + { + if ($this->skipNextIteration) { + $this->skipNextIteration = false; + return; + } + + next($this->data); + } + + /** + * rewind(): defined by Iterator interface. + * + * @see Iterator::rewind() + * @return void + */ + public function rewind() + { + $this->skipNextIteration = false; + reset($this->data); + } + + /** + * valid(): defined by Iterator interface. + * + * @see Iterator::valid() + * @return boolean + */ + public function valid() + { + return ($this->key() !== null); + } + + /** + * offsetExists(): defined by ArrayAccess interface. + * + * @see ArrayAccess::offsetExists() + * @param mixed $offset + * @return boolean + */ + public function offsetExists($offset) + { + return $this->__isset($offset); + } + + /** + * offsetGet(): defined by ArrayAccess interface. + * + * @see ArrayAccess::offsetGet() + * @param mixed $offset + * @return mixed + */ + public function offsetGet($offset) + { + return $this->__get($offset); + } + + /** + * offsetSet(): defined by ArrayAccess interface. + * + * @see ArrayAccess::offsetSet() + * @param mixed $offset + * @param mixed $value + * @return void + */ + public function offsetSet($offset, $value) + { + $this->__set($offset, $value); + } + + /** + * offsetUnset(): defined by ArrayAccess interface. + * + * @see ArrayAccess::offsetUnset() + * @param mixed $offset + * @return void + */ + public function offsetUnset($offset) + { + $this->__unset($offset); + } + + /** + * Merge another Config with this one. + * + * For duplicate keys, the following will be performed: + * - Nested Configs will be recursively merged. + * - Items in $merge with INTEGER keys will be appended. + * - Items in $merge with STRING keys will overwrite current values. + * + * @param Config $merge + * @return Config + */ + public function merge(self $merge) + { + /** @var Config $value */ + foreach ($merge as $key => $value) { + if (array_key_exists($key, $this->data)) { + if (is_int($key)) { + $this->data[] = $value; + } elseif ($value instanceof self && $this->data[$key] instanceof self) { + $this->data[$key]->merge($value); + } else { + if ($value instanceof self) { + $this->data[$key] = new self($value->toArray(), $this->allowModifications); + } else { + $this->data[$key] = $value; + } + } + } else { + if ($value instanceof self) { + $this->data[$key] = new self($value->toArray(), $this->allowModifications); + } else { + $this->data[$key] = $value; + } + } + } + + return $this; + } + + /** + * 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. + * + * @return void + */ + public function setReadOnly() + { + $this->allowModifications = false; + + /** @var Config $value */ + foreach ($this->data as $value) { + if ($value instanceof self) { + $value->setReadOnly(); + } + } + } + + /** + * Returns whether this Config object is read only or not. + * + * @return boolean + */ + public function isReadOnly() + { + return !$this->allowModifications; + } +} diff --git a/src/Exception/ExceptionInterface.php b/src/Exception/ExceptionInterface.php new file mode 100644 index 0000000..81b0132 --- /dev/null +++ b/src/Exception/ExceptionInterface.php @@ -0,0 +1,19 @@ + 'ini', + 'json' => 'json', + 'xml' => 'xml', + 'yaml' => 'yaml', + ); + + + /** + * Read a config from a file. + * + * @param string $filename + * @param boolean $returnConfigObject + * @return array|Config + * @throws Exception\InvalidArgumentException + * @throws Exception\RuntimeException + */ + public static function fromFile($filename, $returnConfigObject = false) + { + $pathinfo = pathinfo($filename); + + if (!isset($pathinfo['extension'])) { + throw new Exception\RuntimeException(sprintf( + 'Filename "%s" is missing an extension and cannot be auto-detected', + $filename + )); + } + + $extension = strtolower($pathinfo['extension']); + + if ($extension === 'php') { + if (!is_file($filename) || !is_readable($filename)) { + throw new Exception\RuntimeException(sprintf( + "File '%s' doesn't exist or not readable", + $filename + )); + } + + $config = include $filename; + } elseif (isset(self::$extensions[$extension])) { + $reader = self::$extensions[$extension]; + if (!$reader instanceof Reader\ReaderInterface) { + $reader = self::getReaderPluginManager()->get($reader); + self::$extensions[$extension] = $reader; + } + + /** @var Reader\ReaderInterface $reader */ + $config = $reader->fromFile($filename); + } else { + throw new Exception\RuntimeException(sprintf( + 'Unsupported config file extension: .%s', + $pathinfo['extension'] + )); + } + + return ($returnConfigObject) ? new Config($config) : $config; + } + + /** + * Read configuration from multiple files and merge them. + * + * @param array $files + * @param boolean $returnConfigObject + * @return array|Config + */ + public static function fromFiles(array $files, $returnConfigObject = false) + { + $config = array(); + + foreach ($files as $file) { + $config = ArrayUtils::merge($config, self::fromFile($file)); + } + + return ($returnConfigObject) ? new Config($config) : $config; + } + + /** + * Set reader plugin manager + * + * @param ReaderPluginManager $readers + */ + public static function setReaderPluginManager(ReaderPluginManager $readers) + { + self::$readers = $readers; + } + + /** + * Get the reader plugin manager + * + * @return ReaderPluginManager + */ + public static function getReaderPluginManager() + { + if (static::$readers === null) { + static::$readers = new ReaderPluginManager(); + } + return static::$readers; + } + + /** + * Set config reader for file extension + * + * @param string $extension + * @param string|Reader\ReaderInterface $reader + * @throws Exception\InvalidArgumentException + */ + public static function registerReader($extension, $reader) + { + $extension = strtolower($extension); + + if (!is_string($reader) && !$reader instanceof Reader\ReaderInterface) { + throw new Exception\InvalidArgumentException(sprintf( + 'Reader should be plugin name, class name or ' . + 'instance of %s\Reader\ReaderInterface; received "%s"', + __NAMESPACE__, + (is_object($reader) ? get_class($reader) : gettype($reader)) + )); + } + + self::$extensions[$extension] = $reader; + } +} diff --git a/src/Processor/Constant.php b/src/Processor/Constant.php new file mode 100644 index 0000000..9fbae8d --- /dev/null +++ b/src/Processor/Constant.php @@ -0,0 +1,89 @@ +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 bool $userOnly + * @return Constant + */ + public function setUserOnly($userOnly) + { + $this->userOnly = (bool) $userOnly; + return $this; + } + + /** + * 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/src/Processor/Filter.php b/src/Processor/Filter.php new file mode 100644 index 0000000..1ed0f31 --- /dev/null +++ b/src/Processor/Filter.php @@ -0,0 +1,94 @@ +setFilter($filter); + } + + /** + * @param ZendFilter $filter + * @return Filter + */ + public function setFilter(ZendFilter $filter) + { + $this->filter = $filter; + return $this; + } + + /** + * @return ZendFilter + */ + public function getFilter() + { + return $this->filter; + } + + /** + * Process + * + * @param Config $config + * @return Config + * @throws Exception\InvalidArgumentException + */ + public function process(Config $config) + { + if ($config->isReadOnly()) { + throw new Exception\InvalidArgumentException('Cannot process config because it is read-only'); + } + + /** + * Walk through config and replace values + */ + foreach ($config as $key => $val) { + if ($val instanceof Config) { + $this->process($val); + } else { + $config->$key = $this->filter->filter($val); + } + } + + return $config; + } + + /** + * Process a single value + * + * @param mixed $value + * @return mixed + */ + public function processValue($value) + { + return $this->filter->filter($value); + } +} diff --git a/src/Processor/ProcessorInterface.php b/src/Processor/ProcessorInterface.php new file mode 100644 index 0000000..520a18b --- /dev/null +++ b/src/Processor/ProcessorInterface.php @@ -0,0 +1,37 @@ +isReadOnly()) { + throw new Exception\InvalidArgumentException('Cannot process config because it is read-only'); + } + + foreach ($this as $parser) { + /** @var $parser ProcessorInterface */ + $parser->process($config); + } + } + + /** + * Process a single value + * + * @param mixed $value + * @return mixed + */ + public function processValue($value) + { + foreach ($this as $parser) { + /** @var $parser ProcessorInterface */ + $value = $parser->processValue($value); + } + + return $value; + } +} diff --git a/src/Processor/Token.php b/src/Processor/Token.php new file mode 100644 index 0000000..0ba34a7 --- /dev/null +++ b/src/Processor/Token.php @@ -0,0 +1,247 @@ + value + * to replace it with + * @param string $prefix + * @param string $suffix + * @internal param array $options + * @return Token + */ + public function __construct($tokens = array(), $prefix = '', $suffix = '') + { + $this->setTokens($tokens); + $this->setPrefix($prefix); + $this->setSuffix($suffix); + } + + /** + * @param string $prefix + * @return Token + */ + public function setPrefix($prefix) + { + // reset map + $this->map = null; + $this->prefix = $prefix; + return $this; + } + + /** + * @return string + */ + public function getPrefix() + { + return $this->prefix; + } + + /** + * @param string $suffix + * @return Token + */ + public function setSuffix($suffix) + { + // reset map + $this->map = null; + $this->suffix = $suffix; + + return $this; + } + + /** + * @return string + */ + public function getSuffix() + { + return $this->suffix; + } + + /** + * Set token registry. + * + * @param array|Config|Traversable $tokens Associative array of TOKEN => value + * to replace it with + * @return Token + * @throws 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 Exception\InvalidArgumentException('Cannot use ' . gettype($tokens) . ' as token registry.'); + } + + // reset map + $this->map = null; + + return $this; + } + + /** + * Get current token registry. + * + * @return array + */ + public function getTokens() + { + return $this->tokens; + } + + /** + * Add new token. + * + * @param string $token + * @param mixed $value + * @return Token + * @throws Exception\InvalidArgumentException + */ + public function addToken($token, $value) + { + if (!is_scalar($token)) { + throw new Exception\InvalidArgumentException('Cannot use ' . gettype($token) . ' as token name.'); + } + $this->tokens[$token] = $value; + + // reset map + $this->map = null; + + return $this; + } + + /** + * Add new token. + * + * @param string $token + * @param mixed $value + * @return Token + */ + 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; + } + } + } + + /** + * Process + * + * @param Config $config + * @return Config + * @throws InvalidArgumentException + */ + public function process(Config $config) + { + if ($config->isReadOnly()) { + throw new Exception\InvalidArgumentException('Cannot process config because it is read-only'); + } + + if ($this->map === null) { + $this->buildMap(); + } + + /** + * 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->process($val); + } else { + $config->$key = str_replace($keys, $values, $val); + } + } + + 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); + } +} diff --git a/src/Processor/Translator.php b/src/Processor/Translator.php new file mode 100644 index 0000000..bb2c623 --- /dev/null +++ b/src/Processor/Translator.php @@ -0,0 +1,146 @@ +setTranslator($translator); + $this->setTextDomain($textDomain); + $this->setLocale($locale); + } + + /** + * @param ZendTranslator $translator + * @return Translator + */ + public function setTranslator(ZendTranslator $translator) + { + $this->translator = $translator; + return $this; + } + + /** + * @return ZendTranslator + */ + public function getTranslator() + { + return $this->translator; + } + + /** + * @param string|null $locale + * @return Translator + */ + public function setLocale($locale) + { + $this->locale = $locale; + return $this; + } + + /** + * @return string|null + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $textDomain + * @return Translator + */ + public function setTextDomain($textDomain) + { + $this->textDomain = $textDomain; + return $this; + } + + /** + * @return string + */ + public function getTextDomain() + { + return $this->textDomain; + } + + /** + * Process + * + * @param Config $config + * @return Config + * @throws Exception\InvalidArgumentException + */ + public function process(Config $config) + { + if ($config->isReadOnly()) { + throw new Exception\InvalidArgumentException('Cannot process config because it is read-only'); + } + + /** + * Walk through config and replace values + */ + foreach ($config as $key => $val) { + if ($val instanceof Config) { + $this->process($val); + } else { + $config->{$key} = $this->translator->translate($val, $this->textDomain, $this->locale); + } + } + + return $config; + } + + /** + * Process a single value + * + * @param $value + * @return mixed + */ + public function processValue($value) + { + return $this->translator->translate($value, $this->textDomain, $this->locale); + } + +} diff --git a/src/Reader/Ini.php b/src/Reader/Ini.php new file mode 100644 index 0000000..fa431f6 --- /dev/null +++ b/src/Reader/Ini.php @@ -0,0 +1,207 @@ +nestSeparator = $separator; + return $this; + } + + /** + * Get nest separator. + * + * @return string + */ + public function getNestSeparator() + { + return $this->nestSeparator; + } + + /** + * fromFile(): defined by Reader interface. + * + * @see ReaderInterface::fromFile() + * @param string $filename + * @return array + * @throws Exception\InvalidArgumentException + */ + public function fromFile($filename) + { + if (!is_file($filename) || !is_readable($filename)) { + throw new Exception\RuntimeException(sprintf( + "File '%s' doesn't exist or not readable", + $filename + )); + } + + $this->directory = dirname($filename); + + 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); + } + + /** + * fromString(): defined by Reader interface. + * + * @param string $string + * @return array|bool + * @throws Exception\RuntimeException + */ + public function fromString($string) + { + if (empty($string)) { + return array(); + } + $this->directory = null; + + 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); + } + + /** + * Process data from the parsed ini file. + * + * @param array $data + * @return array + */ + protected function process(array $data) + { + $config = array(); + + foreach ($data as $section => $value) { + if (is_array($value)) { + if (strpos($section, $this->nestSeparator) !== false) { + $section = explode($this->nestSeparator, $section, 2); + $config[$section[0]][$section[1]] = $this->processSection($value); + } else { + $config[$section] = $this->processSection($value); + } + } else { + $this->processKey($section, $value, $config); + } + } + + 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 + * @throws Exception\RuntimeException + */ + 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') { + 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); + $config = array_replace_recursive($config, $include); + } else { + $config[$key] = $value; + } + } + } +} diff --git a/src/Reader/Json.php b/src/Reader/Json.php new file mode 100644 index 0000000..5d6b7bd --- /dev/null +++ b/src/Reader/Json.php @@ -0,0 +1,110 @@ +directory = dirname($filename); + + try { + $config = JsonFormat::decode(file_get_contents($filename), JsonFormat::TYPE_ARRAY); + } catch (JsonException\RuntimeException $e) { + throw new Exception\RuntimeException($e->getMessage()); + } + + return $this->process($config); + } + + /** + * fromString(): defined by Reader interface. + * + * @see ReaderInterface::fromString() + * @param string $string + * @return array|bool + * @throws Exception\RuntimeException + */ + public function fromString($string) + { + if (empty($string)) { + return array(); + } + + $this->directory = null; + + try { + $config = JsonFormat::decode($string, JsonFormat::TYPE_ARRAY); + } catch (JsonException\RuntimeException $e) { + throw new Exception\RuntimeException($e->getMessage()); + } + + return $this->process($config); + } + + /** + * Process the array for @include + * + * @param array $data + * @return array + * @throws Exception\RuntimeException + */ + protected function process(array $data) + { + foreach ($data as $key => $value) { + if (is_array($value)) { + $data[$key] = $this->process($value); + } + if (trim($key) === '@include') { + if ($this->directory === null) { + throw new Exception\RuntimeException('Cannot process @include statement for a JSON string'); + } + $reader = clone $this; + unset($data[$key]); + $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value)); + } + } + return $data; + } +} diff --git a/src/Reader/ReaderInterface.php b/src/Reader/ReaderInterface.php new file mode 100644 index 0000000..4ecaf8d --- /dev/null +++ b/src/Reader/ReaderInterface.php @@ -0,0 +1,35 @@ +reader = new XMLReader(); + $this->reader->open($filename, null, LIBXML_XINCLUDE); + + $this->directory = dirname($filename); + + 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; + } + + /** + * fromString(): defined by Reader interface. + * + * @see ReaderInterface::fromString() + * @param string $string + * @return array|bool + * @throws Exception\RuntimeException + */ + public function fromString($string) + { + if (empty($string)) { + return array(); + } + $this->reader = new XMLReader(); + + $this->reader->xml($string, null, LIBXML_XINCLUDE); + + $this->directory = null; + + 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; + } + + /** + * Process data from the created XMLReader. + * + * @return array + */ + protected function process() + { + return $this->processNextElement(); + } + + /** + * Process the next inner element. + * + * @return mixed + */ + protected function processNextElement() + { + $children = array(); + $text = ''; + + while ($this->reader->read()) { + if ($this->reader->nodeType === XMLReader::ELEMENT) { + if ($this->reader->depth === 0) { + return $this->processNextElement(); + } + + $attributes = $this->getAttributes(); + $name = $this->reader->name; + + if ($this->reader->isEmptyElement) { + $child = array(); + } else { + $child = $this->processNextElement(); + } + + if ($attributes) { + if (!is_array($child)) { + $child = array(); + } + + $child = array_merge($child, $attributes); + } + + if (isset($children[$name])) { + if (!is_array($children[$name]) || !array_key_exists(0, $children[$name])) { + $children[$name] = array($children[$name]); + } + + $children[$name][] = $child; + } else { + $children[$name] = $child; + } + } elseif ($this->reader->nodeType === XMLReader::END_ELEMENT) { + break; + } elseif (in_array($this->reader->nodeType, $this->textNodes)) { + $text .= $this->reader->value; + } + } + + return $children ?: $text; + } + + /** + * Get all attributes on the current node. + * + * @return array + */ + protected function getAttributes() + { + $attributes = array(); + + if ($this->reader->hasAttributes) { + while ($this->reader->moveToNextAttribute()) { + $attributes[$this->reader->localName] = $this->reader->value; + } + + $this->reader->moveToElement(); + } + + return $attributes; + } +} diff --git a/src/Reader/Yaml.php b/src/Reader/Yaml.php new file mode 100644 index 0000000..c33ef29 --- /dev/null +++ b/src/Reader/Yaml.php @@ -0,0 +1,164 @@ +setYamlDecoder($yamlDecoder); + } else { + if (function_exists('yaml_parse')) { + $this->setYamlDecoder('yaml_parse'); + } + } + } + + /** + * Set callback for decoding YAML + * + * @param string|callable $yamlDecoder the decoder to set + * @return Yaml + * @throws Exception\InvalidArgumentException + */ + public function setYamlDecoder($yamlDecoder) + { + if (!is_callable($yamlDecoder)) { + throw new Exception\RuntimeException( + 'Invalid parameter to setYamlDecoder() - must be callable' + ); + } + $this->yamlDecoder = $yamlDecoder; + return $this; + } + + /** + * Get callback for decoding YAML + * + * @return callable + */ + public function getYamlDecoder() + { + return $this->yamlDecoder; + } + + /** + * fromFile(): defined by Reader interface. + * + * @see ReaderInterface::fromFile() + * @param string $filename + * @return array + * @throws Exception\RuntimeException + */ + public function fromFile($filename) + { + if (!is_file($filename) || !is_readable($filename)) { + throw new Exception\RuntimeException(sprintf( + "File '%s' doesn't exist or not readable", + $filename + )); + } + + if (null === $this->getYamlDecoder()) { + throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder"); + } + + $this->directory = dirname($filename); + + $config = call_user_func($this->getYamlDecoder(), file_get_contents($filename)); + if (null === $config) { + throw new Exception\RuntimeException("Error parsing YAML data"); + } + + return $this->process($config); + } + + /** + * fromString(): defined by Reader interface. + * + * @see ReaderInterface::fromString() + * @param string $string + * @return array|bool + * @throws Exception\RuntimeException + */ + public function fromString($string) + { + if (null === $this->getYamlDecoder()) { + throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder"); + } + if (empty($string)) { + return array(); + } + + $this->directory = null; + + $config = call_user_func($this->getYamlDecoder(), $string); + if (null === $config) { + throw new Exception\RuntimeException("Error parsing YAML data"); + } + + return $this->process($config); + } + + /** + * Process the array for @include + * + * @param array $data + * @return array + * @throws Exception\RuntimeException + */ + protected function process(array $data) + { + foreach ($data as $key => $value) { + if (is_array($value)) { + $data[$key] = $this->process($value); + } + if (trim($key) === '@include') { + if ($this->directory === null) { + throw new Exception\RuntimeException('Cannot process @include statement for a json string'); + } + $reader = clone $this; + unset($data[$key]); + $data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value)); + } + } + return $data; + } +} diff --git a/src/ReaderPluginManager.php b/src/ReaderPluginManager.php new file mode 100644 index 0000000..2614fd0 --- /dev/null +++ b/src/ReaderPluginManager.php @@ -0,0 +1,54 @@ + 'Zend\Config\Reader\Ini', + 'json' => 'Zend\Config\Reader\Json', + 'xml' => 'Zend\Config\Reader\Xml', + 'yaml' => 'Zend\Config\Reader\Yaml', + ); + + /** + * Validate the plugin + * Checks that the reader loaded is an instance of Reader\ReaderInterface. + * + * @param Reader\ReaderInterface $plugin + * @return void + * @throws Exception\InvalidArgumentException if invalid + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof Reader\ReaderInterface) { + // we're okay + return; + } + + throw new Exception\InvalidArgumentException(sprintf( + 'Plugin of type %s is invalid; must implement %s\Reader\ReaderInterface', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)), + __NAMESPACE__ + )); + } +} diff --git a/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php new file mode 100644 index 0000000..4726075 --- /dev/null +++ b/src/Writer/AbstractWriter.php @@ -0,0 +1,83 @@ +toString($config), $flags); + restore_error_handler(); + } + + /** + * toString(): defined by Writer interface. + * + * @see WriterInterface::toString() + * @param mixed $config + * @return string + * @throws Exception\InvalidArgumentException + */ + public function toString($config) + { + if ($config instanceof Traversable) { + $config = ArrayUtils::iteratorToArray($config); + } elseif (!is_array($config)) { + throw new Exception\InvalidArgumentException(__METHOD__ . ' expects an array or Traversable config'); + } + + return $this->processConfig($config); + } + + /** + * @param array $config + * @return string + */ + abstract protected function processConfig(array $config); +} diff --git a/src/Writer/Ini.php b/src/Writer/Ini.php new file mode 100644 index 0000000..b641d62 --- /dev/null +++ b/src/Writer/Ini.php @@ -0,0 +1,189 @@ +nestSeparator = $separator; + return $this; + } + + /** + * Get nest separator. + * + * @return string + */ + public function getNestSeparator() + { + return $this->nestSeparator; + } + + /** + * Set if rendering should occur without sections or not. + * + * If set to true, the INI file is rendered without sections completely + * into the global namespace of the INI file. + * + * @param bool $withoutSections + * @return Ini + */ + public function setRenderWithoutSectionsFlags($withoutSections) + { + $this->renderWithoutSections = (bool) $withoutSections; + return $this; + } + + /** + * Return whether the writer should render without sections. + * + * @return boolean + */ + public function shouldRenderWithoutSections() + { + return $this->renderWithoutSections; + } + + /** + * processConfig(): defined by AbstractWriter. + * + * @param array $config + * @return string + */ + public function processConfig(array $config) + { + $iniString = ''; + + if ($this->shouldRenderWithoutSections()) { + $iniString .= $this->addBranch($config); + } else { + $config = $this->sortRootElements($config); + + foreach ($config as $sectionName => $data) { + if (!is_array($data)) { + $iniString .= $sectionName + . ' = ' + . $this->prepareValue($data) + . "\n"; + } else { + $iniString .= '[' . $sectionName . ']' . "\n" + . $this->addBranch($data) + . "\n"; + } + } + } + + return $iniString; + } + + /** + * Add a branch to an INI string recursively. + * + * @param array $config + * @param array $parents + * @return string + */ + protected function addBranch(array $config, $parents = array()) + { + $iniString = ''; + + foreach ($config as $key => $value) { + $group = array_merge($parents, array($key)); + + if (is_array($value)) { + $iniString .= $this->addBranch($value, $group); + } else { + $iniString .= implode($this->nestSeparator, $group) + . ' = ' + . $this->prepareValue($value) + . "\n"; + } + } + + return $iniString; + } + + /** + * Prepare a value for INI. + * + * @param mixed $value + * @return string + * @throws Exception\RuntimeException + */ + protected function prepareValue($value) + { + if (is_integer($value) || is_float($value)) { + return $value; + } elseif (is_bool($value)) { + return ($value ? 'true' : 'false'); + } elseif (false === strpos($value, '"')) { + return '"' . $value . '"'; + } else { + 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. + * + * @param array $config + * @return array + */ + protected function sortRootElements(array $config) + { + $sections = array(); + + // Remove sections from config array. + foreach ($config as $key => $value) { + if (is_array($value)) { + $sections[$key] = $value; + unset($config[$key]); + } + } + + // Read sections to the end. + foreach ($sections as $key => $value) { + $config[$key] = $value; + } + + return $config; + } +} diff --git a/src/Writer/Json.php b/src/Writer/Json.php new file mode 100644 index 0000000..3d544ab --- /dev/null +++ b/src/Writer/Json.php @@ -0,0 +1,32 @@ +openMemory(); + $writer->setIndent(true); + $writer->setIndentString(str_repeat(' ', 4)); + + $writer->startDocument('1.0', 'UTF-8'); + $writer->startElement('zend-config'); + + foreach ($config as $sectionName => $data) { + if (!is_array($data)) { + $writer->writeElement($sectionName, (string) $data); + } else { + $this->addBranch($sectionName, $data, $writer); + } + } + + $writer->endElement(); + $writer->endDocument(); + + return $writer->outputMemory(); + } + + /** + * Add a branch to an XML object recursively. + * + * @param string $branchName + * @param array $config + * @param XMLWriter $writer + * @return void + * @throws Exception\RuntimeException + */ + protected function addBranch($branchName, array $config, XMLWriter $writer) + { + $branchType = null; + + foreach ($config as $key => $value) { + if ($branchType === null) { + if (is_numeric($key)) { + $branchType = 'numeric'; + } else { + $writer->startElement($branchName); + $branchType = 'string'; + } + } elseif ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) { + throw new Exception\RuntimeException('Mixing of string and numeric keys is not allowed'); + } + + if ($branchType === 'numeric') { + if (is_array($value)) { + $this->addBranch($value, $value, $writer); + } else { + $writer->writeElement($branchName, (string) $value); + } + } else { + if (is_array($value)) { + $this->addBranch($key, $value, $writer); + } else { + $writer->writeElement($key, (string) $value); + } + } + } + + if ($branchType === 'string') { + $writer->endElement(); + } + } +} diff --git a/src/Writer/Yaml.php b/src/Writer/Yaml.php new file mode 100644 index 0000000..9d4c309 --- /dev/null +++ b/src/Writer/Yaml.php @@ -0,0 +1,91 @@ +setYamlEncoder($yamlEncoder); + } else { + if (function_exists('yaml_emit')) { + $this->setYamlEncoder('yaml_emit'); + } + } + } + + /** + * Get callback for decoding YAML + * + * @return callable + */ + public function getYamlEncoder() + { + return $this->yamlEncoder; + } + + /** + * Set callback for decoding YAML + * + * @param callable $yamlEncoder the decoder to set + * @return Yaml + * @throws Exception\InvalidArgumentException + */ + public function setYamlEncoder($yamlEncoder) + { + if (!is_callable($yamlEncoder)) { + throw new Exception\InvalidArgumentException('Invalid parameter to setYamlEncoder() - must be callable'); + } + $this->yamlEncoder = $yamlEncoder; + return $this; + } + + /** + * processConfig(): defined by AbstractWriter. + * + * @param array $config + * @return string + * @throws Exception\RuntimeException + */ + public function processConfig(array $config) + { + if (null === $this->getYamlEncoder()) { + throw new Exception\RuntimeException("You didn't specify a Yaml callback encoder"); + } + + $config = call_user_func($this->getYamlEncoder(), $config); + if (null === $config) { + throw new Exception\RuntimeException("Error generating YAML data"); + } + + return $config; + } +} diff --git a/test/ConfigTest.php b/test/ConfigTest.php new file mode 100644 index 0000000..cdb2dfa --- /dev/null +++ b/test/ConfigTest.php @@ -0,0 +1,635 @@ +all = array( + 'hostname' => 'all', + 'name' => 'thisname', + 'db' => array( + 'host' => '127.0.0.1', + 'user' => 'username', + 'pass' => 'password', + 'name' => 'live' + ), + 'one' => array( + 'two' => array( + 'three' => 'multi' + ) + ) + ); + + $this->numericData = array( + 0 => 34, + 1 => 'test', + ); + + $this->menuData1 = array( + 'button' => array( + 'b0' => array( + 'L1' => 'button0-1', + 'L2' => 'button0-2', + 'L3' => 'button0-3' + ), + 'b1' => array( + 'L1' => 'button1-1', + 'L2' => 'button1-2' + ), + 'b2' => array( + 'L1' => 'button2-1' + ) + ) + ); + + $this->toCombineA = array( + 'foo' => 1, + 'bar' => 2, + 'text' => 'foo', + 'numerical' => array( + 'first', + 'second', + array( + 'third' + ) + ), + 'misaligned' => array( + 2 => 'foo', + 3 => 'bar' + ), + 'mixed' => array( + 'foo' => 'bar' + ), + 'replaceAssoc' => array( + 'foo' => 'bar' + ), + 'replaceNumerical' => array( + 'foo' + ) + ); + + $this->toCombineB = array( + 'foo' => 3, + 'text' => 'bar', + 'numerical' => array( + 'fourth', + 'fifth', + array( + 'sixth' + ) + ), + 'misaligned' => array( + 3 => 'baz' + ), + 'mixed' => array( + false + ), + 'replaceAssoc' => null, + 'replaceNumerical' => true + ); + + $this->leadingdot = array('.test' => 'dot-test'); + $this->invalidkey = array(' ' => 'test', ''=>'test2'); + + } + + public function testLoadSingleSection() + { + $config = new Config($this->all, false); + + $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 testIsset() + { + $config = new Config($this->all, false); + + $this->assertFalse(isset($config->notarealkey)); + $this->assertTrue(isset($config->hostname)); // top level + $this->assertTrue(isset($config->db->name)); // one level down + } + + public function testModification() + { + $config = new Config($this->all, true); + + // overwrite an existing key + $this->assertEquals('thisname', $config->name); + $config->name = 'anothername'; + $this->assertEquals('anothername', $config->name); + + // overwrite an existing multi-level key + $this->assertEquals('multi', $config->one->two->three); + $config->one->two->three = 'anothername'; + $this->assertEquals('anothername', $config->one->two->three); + + // create a new multi-level key + $config->does = array('not'=> array('exist' => 'yet')); + $this->assertEquals('yet', $config->does->not->exist); + + } + + public function testNoModifications() + { + $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\RuntimeException', 'Config is read only'); + $config = new Config($this->all); + $config->db->host = 'test'; + } + + public function testNumericKeys() + { + $data = new Config($this->numericData); + $this->assertEquals('test', $data->{1}); + $this->assertEquals(34, $data->{0}); + } + + public function testCount() + { + $data = new Config($this->menuData1); + $this->assertEquals(3, count($data->button)); + } + + public function testIterator() + { + // top level + $config = new Config($this->all); + $var = ''; + foreach ($config as $key=>$value) { + if (is_string($value)) { + $var .= "\nkey = $key, value = $value"; + } + } + $this->assertContains('key = name, value = thisname', $var); + + // 1 nest + $var = ''; + foreach ($config->db as $key=>$value) { + $var .= "\nkey = $key, value = $value"; + } + $this->assertContains('key = host, value = 127.0.0.1', $var); + + // 2 nests + $config = new Config($this->menuData1); + $var = ''; + foreach ($config->button->b1 as $key=>$value) { + $var .= "\nkey = $key, value = $value"; + } + $this->assertContains('key = L1, value = button1-1', $var); + } + + public function testArray() + { + $config = new Config($this->all); + + ob_start(); + print_r($config->toArray()); + $contents = ob_get_contents(); + ob_end_clean(); + + $this->assertContains('Array', $contents); + $this->assertContains('[hostname] => all', $contents); + $this->assertContains('[user] => username', $contents); + } + + public function testErrorWriteToReadOnly() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Config is read only'); + $config = new Config($this->all); + $config->test = '32'; + } + + public function testZF343() + { + $config_array = array( + 'controls' => array( + 'visible' => array( + 'name' => 'visible', + 'type' => 'checkbox', + 'attribs' => array(), // empty array + ), + ), + ); + $form_config = new Config($config_array, true); + $this->assertSame(array(), $form_config->controls->visible->attribs->toArray()); + } + + public function testZF402() + { + $configArray = array( + 'data1' => 'someValue', + 'data2' => 'someValue', + 'false1' => false, + 'data3' => 'someValue' + ); + $config = new Config($configArray); + $this->assertTrue(count($config) === count($configArray)); + $count = 0; + foreach ($config as $key => $value) { + if ($key === 'false1') { + $this->assertTrue($value === false); + } else { + $this->assertTrue($value === 'someValue'); + } + $count++; + } + $this->assertTrue($count === 4); + } + + public function testZf1019_HandlingInvalidKeyNames() + { + $config = new Config($this->leadingdot); + $array = $config->toArray(); + $this->assertContains('dot-test', $array['.test']); + } + + public function testZF1019_EmptyKeys() + { + $config = new Config($this->invalidkey); + $array = $config->toArray(); + $this->assertContains('test', $array[' ']); + $this->assertContains('test', $array['']); + } + + public function testZF1417_DefaultValues() + { + $config = new Config($this->all); + $value = $config->get('notthere', 'default'); + $this->assertTrue($value === 'default'); + $this->assertTrue($config->notThere === null); + + } + + public function testUnsetException() + { + // allow modifications is off - expect an exception + $config = new Config($this->all, false); + + $this->assertTrue(isset($config->hostname)); // top level + + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', 'is read only'); + unset($config->hostname); + } + + public function testUnset() + { + // allow modifications is on + $config = new Config($this->all, true); + + $this->assertTrue(isset($config->hostname)); + $this->assertTrue(isset($config->db->name)); + + unset($config->hostname); + unset($config->db->name); + + $this->assertFalse(isset($config->hostname)); + $this->assertFalse(isset($config->db->name)); + + } + + public function testMerge() + { + $configA = new Config($this->toCombineA); + $configB = new Config($this->toCombineB); + $configA->merge($configB); + + // config-> + $this->assertEquals(3, $configA->foo); + $this->assertEquals(2, $configA->bar); + $this->assertEquals('bar', $configA->text); + + // config->numerical-> ... + $this->assertInstanceOf('\Zend\Config\Config',$configA->numerical); + $this->assertEquals('first',$configA->numerical->{0}); + $this->assertEquals('second',$configA->numerical->{1}); + + // config->numerical->{2}-> ... + $this->assertInstanceOf('\Zend\Config\Config',$configA->numerical->{2}); + $this->assertEquals('third',$configA->numerical->{2}->{0}); + $this->assertEquals(null,$configA->numerical->{2}->{1}); + + // config->numerical-> ... + $this->assertEquals('fourth',$configA->numerical->{3}); + $this->assertEquals('fifth',$configA->numerical->{4}); + + // config->numerical->{5} + $this->assertInstanceOf('\Zend\Config\Config',$configA->numerical->{5}); + $this->assertEquals('sixth',$configA->numerical->{5}->{0}); + $this->assertEquals(null,$configA->numerical->{5}->{1}); + + // config->misaligned + $this->assertInstanceOf('\Zend\Config\Config',$configA->misaligned); + $this->assertEquals('foo',$configA->misaligned->{2}); + $this->assertEquals('bar',$configA->misaligned->{3}); + $this->assertEquals('baz',$configA->misaligned->{4}); + $this->assertEquals(null,$configA->misaligned->{0}); + + // config->mixed + $this->assertInstanceOf('\Zend\Config\Config',$configA->mixed); + $this->assertEquals('bar',$configA->mixed->foo); + $this->assertSame(false,$configA->mixed->{0}); + $this->assertSame(null,$configA->mixed->{1}); + + // config->replaceAssoc + $this->assertSame(null,$configA->replaceAssoc); + + // config->replaceNumerical + $this->assertSame(true,$configA->replaceNumerical); + + } + + public function testArrayAccess() + { + $config = new Config($this->all, true); + + $this->assertEquals('thisname', $config['name']); + $config['name'] = 'anothername'; + $this->assertEquals('anothername', $config['name']); + $this->assertEquals('multi', $config['one']['two']['three']); + + $this->assertTrue(isset($config['hostname'])); + $this->assertTrue(isset($config['db']['name'])); + + unset($config['hostname']); + unset($config['db']['name']); + + $this->assertFalse(isset($config['hostname'])); + $this->assertFalse(isset($config['db']['name'])); + } + + public function testArrayAccessModification() + { + $config = new Config($this->numericData, true); + + // Define some values we'll be using + $poem = array( + 'poem' => array ( + 'line 1' => 'Roses are red, bacon is also red,', + 'line 2' => 'Poems are hard,', + 'line 3' => 'Bacon.', + ), + ); + + $bacon = 'Bacon'; + + // Add a value + $config[] = $bacon; + + // Check if bacon now has a key that equals to 2 + $this->assertEquals($bacon, $config[2]); + + // Now let's try setting an array with no key supplied + $config[] = $poem; + + // This should now be set with key 3 + $this->assertEquals($poem, $config[3]->toArray()); + } + + /** + * Ensures that toArray() supports objects of types other than Zend_Config + * + * @return void + */ + public function testToArraySupportsObjects() + { + $configData = array( + 'a' => new \stdClass(), + 'b' => array( + 'c' => new \stdClass(), + 'd' => new \stdClass() + ) + ); + $config = new Config($configData); + $this->assertEquals($config->toArray(), $configData); + $this->assertInstanceOf('stdClass', $config->a); + $this->assertInstanceOf('stdClass', $config->b->c); + $this->assertInstanceOf('stdClass', $config->b->d); + } + + /** + * ensure that modification is not allowed after calling setReadOnly() + * + */ + public function testSetReadOnly() + { + $configData = array( + 'a' => 'a' + ); + $config = new Config($configData, true); + $config->b = 'b'; + + $config->setReadOnly(); + $this->setExpectedException('Zend\Config\Exception\RuntimeException', 'Config is read only'); + $config->c = 'c'; + } + + public function testZF3408_countNotDecreasingOnUnset() + { + $configData = array( + 'a' => 'a', + 'b' => 'b', + 'c' => 'c', + ); + $config = new Config($configData, true); + $this->assertEquals(count($config), 3); + unset($config->b); + $this->assertEquals(count($config), 2); + } + + public function testZF4107_ensureCloneDoesNotKeepNestedReferences() + { + $parent = new Config(array('key' => array('nested' => 'parent')), true); + $newConfig = clone $parent; + $newConfig->merge(new Config(array('key' => array('nested' => 'override')), true)); + + $this->assertEquals('override', $newConfig->key->nested, '$newConfig is not overridden'); + $this->assertEquals('parent', $parent->key->nested, '$parent has been overridden'); + + } + + /** + * @group ZF-3575 + * + */ + public function testMergeHonoursAllowModificationsFlagAtAllLevels() + { + $config = new Config(array('key' => array('nested' => 'yes'), 'key2'=>'yes'), false); + $config2 = new Config(array(), true); + + $config2->merge($config); + + $config2->key2 = 'no'; + + $this->assertEquals('no', $config2->key2); + + $config2->key->nested = 'no'; + + $this->assertEquals('no', $config2->key->nested); + } + + /** + * @group ZF-5771a + * + */ + public function testUnsettingFirstElementDuringForeachDoesNotSkipAnElement() + { + $config = new Config(array( + 'first' => array(1), + 'second' => array(2), + 'third' => array(3) + ), true); + + $keyList = array(); + foreach ($config as $key => $value) { + $keyList[] = $key; + if ($key == 'first') { + unset($config->$key); // uses magic Zend\Config\Config::__unset() method + } + } + + $this->assertEquals('first', $keyList[0]); + $this->assertEquals('second', $keyList[1]); + $this->assertEquals('third', $keyList[2]); + } + + /** + * @group ZF-5771 + * + */ + public function testUnsettingAMiddleElementDuringForeachDoesNotSkipAnElement() + { + $config = new Config(array( + 'first' => array(1), + 'second' => array(2), + 'third' => array(3) + ), true); + + $keyList = array(); + foreach ($config as $key => $value) { + $keyList[] = $key; + if ($key == 'second') { + unset($config->$key); // uses magic Zend\Config\Config::__unset() method + } + } + + $this->assertEquals('first', $keyList[0]); + $this->assertEquals('second', $keyList[1]); + $this->assertEquals('third', $keyList[2]); + } + + /** + * @group ZF-5771 + * + */ + public function testUnsettingLastElementDuringForeachDoesNotSkipAnElement() + { + $config = new Config(array( + 'first' => array(1), + 'second' => array(2), + 'third' => array(3) + ), true); + + $keyList = array(); + foreach ($config as $key => $value) { + $keyList[] = $key; + if ($key == 'third') { + unset($config->$key); // uses magic Zend\Config\Config::__unset() method + } + } + + $this->assertEquals('first', $keyList[0]); + $this->assertEquals('second', $keyList[1]); + $this->assertEquals('third', $keyList[2]); + } + + /** + * @group ZF-4728 + * + */ + public function testSetReadOnlyAppliesToChildren() + { + $config = new Config($this->all, true); + + $config->setReadOnly(); + $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() + { + $config = new Config(range(1,10)); + $config->rewind(); + $this->assertEquals(1, $config->current()); + + $config->toArray(); + $this->assertEquals(1, $config->current()); + } + + /** + * @depends testMerge + * @link http://framework.zend.com/issues/browse/ZF2-186 + */ + public function testZF2_186_mergeReplacingUnnamedConfigSettings() + { + $arrayA = array( + 'flag' => true, + 'text' => 'foo', + 'list' => array( 'a', 'b', 'c' ), + 'aSpecific' => 12 + ); + + $arrayB = array( + 'flag' => false, + 'text' => 'bar', + 'list' => array( 'd', 'e' ), + 'bSpecific' => 100 + ); + + $mergeResult = array( + 'flag' => false, + 'text' => 'bar', + 'list' => array( 'a', 'b', 'c', 'd', 'e' ), + 'aSpecific' => 12, + 'bSpecific' => 100 + ); + + $configA = new Config($arrayA); + $configB = new Config($arrayB); + + $configA->merge($configB); // merge B onto A + $this->assertEquals($mergeResult, $configA->toArray()); + } +} + diff --git a/test/FactoryTest.php b/test/FactoryTest.php new file mode 100644 index 0000000..ffd4836 --- /dev/null +++ b/test/FactoryTest.php @@ -0,0 +1,143 @@ +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 testFromPhpFiles() + { + $files = array ( + __DIR__ . '/TestAssets/Php/include-base.php', + __DIR__ . '/TestAssets/Php/include-base2.php' + ); + $config = Factory::fromFiles($files); + + $this->assertEquals('bar', $config['base']['foo']); + $this->assertEquals('baz', $config['test']['bar']); + } + + public function testFromIniAndXmlAndPhpFiles() + { + $files = array ( + __DIR__ . '/TestAssets/Ini/include-base.ini', + __DIR__ . '/TestAssets/Xml/include-base2.xml', + __DIR__ . '/TestAssets/Php/include-base3.php', + ); + $config = Factory::fromFiles($files); + + $this->assertEquals('bar', $config['base']['foo']); + $this->assertEquals('baz', $config['test']['bar']); + $this->assertEquals('baz', $config['last']['bar']); + } + + public function testReturnsConfigObjectIfRequestedAndArrayOtherwise() + { + $files = array ( + __DIR__ . '/TestAssets/Ini/include-base.ini', + ); + + $configArray = Factory::fromFile($files[0]); + $this->assertTrue(is_array($configArray)); + + $configArray = Factory::fromFiles($files); + $this->assertTrue(is_array($configArray)); + + $configObject = Factory::fromFile($files[0], true); + $this->assertInstanceOf('Zend\Config\Config', $configObject); + + $configObject = Factory::fromFiles($files, true); + $this->assertInstanceOf('Zend\Config\Config', $configObject); + } + + public function testNonExistentFileThrowsRuntimeException() + { + $this->setExpectedException('RuntimeException'); + $config = Factory::fromFile('foo.bar'); + } + + public function testUnsupportedFileExtensionThrowsRuntimeException() + { + $this->setExpectedException('RuntimeException'); + $config = Factory::fromFile(__DIR__ . '/TestAssets/bad.ext'); + } + + public function testFactoryCanRegisterCustomReaderInstance() + { + Factory::registerReader('dum', new Reader\TestAssets\DummyReader()); + + $configObject = Factory::fromFile(__DIR__ . '/TestAssets/dummy.dum', true); + $this->assertInstanceOf('Zend\Config\Config', $configObject); + + $this->assertEquals($configObject['one'], 1); + } + + public function testFactoryCanRegisterCustomReaderPlugn() + { + $dummyReader = new Reader\TestAssets\DummyReader(); + Factory::getReaderPluginManager()->setService('DummyReader',$dummyReader); + + Factory::registerReader('dum', 'DummyReader'); + + $configObject = Factory::fromFile(__DIR__ . '/TestAssets/dummy.dum', true); + $this->assertInstanceOf('Zend\Config\Config', $configObject); + + $this->assertEquals($configObject['one'], 1); + } + + +} + diff --git a/test/ProcessorTest.php b/test/ProcessorTest.php new file mode 100644 index 0000000..aaeb368 --- /dev/null +++ b/test/ProcessorTest.php @@ -0,0 +1,495 @@ +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 ##', + 'nested' => array( + 'simple' => '@@TOKEN@@', + 'inside' => '@@ some text with @@TOKEN@@ inside @@', + ), + ); + + $this->translatorData = array( + 'pages' => array( + array( + 'id' => 'oneDog', + 'label' => 'one dog', + 'route' => 'app-one-dog' + ), + array( + 'id' => 'twoDogs', + 'label' => 'two dogs', + 'route' => 'app-two-dogs' + ), + ) + ); + + $this->translatorFile = realpath(__DIR__ . '/_files/translations-de_DE.php'); + + $this->filter = array( + 'simple' => 'some MixedCase VALue', + 'nested' => array( + 'simple' => 'OTHER mixed Case Value', + ), + ); + + $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 testProcessorsQueue() + { + $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); + $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 process config because it is read-only'); + $processor->process($config); + } + + public function testTokenPrefix() + { + $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); + $this->assertEquals('some replaced value', $config->nested->simple); + $this->assertEquals(':: some text with some replaced value inside ::', $config->nested->inside); + } + + public function testTokenSuffix() + { + $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); + $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() + { + $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); + $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() + { + $config = new Config($this->tokenSurroundMixed, 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); + $this->assertEquals('@@TOKEN@@', $config->nested->simple); + $this->assertEquals('@@ some text with @@TOKEN@@ inside @@', $config->nested->inside); + + /** + * Now change prefix and suffix on the processor + */ + $processor->setPrefix('@@'); + $processor->setSuffix('@@'); + + /** + * Parse the config again + */ + $processor->process($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); + } + + /** + * @depends testTokenSurround + */ + public function testUserConstants() + { + define('SOME_USERLAND_CONSTANT', 'some constant value'); + + $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); + $processor = new ConstantProcessor(false); + $processor->process($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() + { + $config = new Config($this->translatorData, true); + $translator = new Translator(); + $translator->addTranslationFile('phparray', $this->translatorFile); + $processor = new TranslatorProcessor($translator); + + $processor->process($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 testTranslatorReadOnly() + { + $config = new Config($this->translatorData, false); + $translator = new Translator(); + $processor = new TranslatorProcessor($translator); + + $this->setExpectedException('Zend\Config\Exception\InvalidArgumentException', + 'Cannot process config because it is read-only'); + $processor->process($config); + } + + public function testTranslatorSingleValue() + { + $translator = new Translator(); + $translator->addTranslationFile('phparray', $this->translatorFile); + $processor = new TranslatorProcessor($translator); + + $this->assertEquals('ein Hund', $processor->processValue('one dog')); + } + + public function testFilter() + { + $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 process 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 testQueueFIFO() + { + $config = new Config($this->filter, true); + $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); + $queue->process($config); + + $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 process 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 testQueueFIFO + */ + public function testQueuePriorities() + { + $config = new Config($this->filter, 1); + $lower = new StringToLower(); + $upper = new StringToUpper(); + $replace = new PregReplace('/[a-z]/', ''); + $lowerProcessor = new FilterProcessor($lower); + $upperProcessor = new FilterProcessor($upper); + $replaceProcessor = new FilterProcessor($replace); + $queue = new Queue(); + + /** + * Insert lower case filter with higher priority + */ + $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 processor that will remove all lowercase letters + */ + $queue->insert($replaceProcessor, 10000); + $config->newValue = 'THIRD mixed CASE value'; + $queue->process($config); + $this->assertEquals('THIRD CASE ', $config->newValue); + } + +} + diff --git a/test/Reader/AbstractReaderTestCase.php b/test/Reader/AbstractReaderTestCase.php new file mode 100644 index 0000000..1e45a5c --- /dev/null +++ b/test/Reader/AbstractReaderTestCase.php @@ -0,0 +1,56 @@ +getTestAssetPath('no-file'); + $this->setExpectedException('Zend\Config\Exception\RuntimeException', "doesn't exist or not readable"); + $config = $this->reader->fromFile($filename); + } + + public function testFromFile() + { + $config = $this->reader->fromFile($this->getTestAssetPath('include-base')); + $this->assertEquals('foo', $config['foo']); + } + + public function testFromEmptyString() + { + $config = $this->reader->fromString(''); + $this->assertTrue(!$config); + } +} diff --git a/test/Reader/IniTest.php b/test/Reader/IniTest.php new file mode 100644 index 0000000..66484b9 --- /dev/null +++ b/test/Reader/IniTest.php @@ -0,0 +1,103 @@ +reader = new Ini(); + } + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) + { + return __DIR__ . '/TestAssets/Ini/' . $name . '.ini'; + } + + public function testInvalidIniFile() + { + $this->reader = new Ini(); + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayIni = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testFromString() + { + $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 = <<reader->fromString($ini); + $this->assertEquals($arrayIni['all']['test'], 'foo'); + $this->assertEquals($arrayIni['all']['bar'][0], 'baz'); + $this->assertEquals($arrayIni['all']['bar'][1], 'foo'); + } + + public function testFromStringNested() + { + $ini = <<reader->fromString($ini); + $this->assertEquals($arrayIni['foo']['bar'], 'foobar'); + $this->assertEquals($arrayIni['foobar'][0], 'foobarArray'); + $this->assertEquals($arrayIni['foo']['baz'][0], 'foobaz1'); + $this->assertEquals($arrayIni['foo']['baz'][1], 'foobaz2'); + } +} diff --git a/test/Reader/JsonTest.php b/test/Reader/JsonTest.php new file mode 100644 index 0000000..20cc681 --- /dev/null +++ b/test/Reader/JsonTest.php @@ -0,0 +1,70 @@ +reader = new Json(); + } + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) + { + return __DIR__ . '/TestAssets/Json/' . $name . '.json'; + } + + public function testInvalidJsonFile() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayJson = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testIncludeAsElement() + { + $arrayJson = $this->reader->fromFile($this->getTestAssetPath('include-base_nested')); + $this->assertEquals($arrayJson['bar']['foo'], 'foo'); + } + + public function testFromString() + { + $json = '{ "test" : "foo", "bar" : [ "baz", "foo" ] }'; + + $arrayJson = $this->reader->fromString($json); + + $this->assertEquals($arrayJson['test'], 'foo'); + $this->assertEquals($arrayJson['bar'][0], 'baz'); + $this->assertEquals($arrayJson['bar'][1], 'foo'); + } + + public function testInvalidString() + { + $json = '{"foo":"bar"'; + + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayIni = $this->reader->fromString($json); + } + +} diff --git a/test/Reader/TestAssets/DummyReader.php b/test/Reader/TestAssets/DummyReader.php new file mode 100644 index 0000000..95d24d5 --- /dev/null +++ b/test/Reader/TestAssets/DummyReader.php @@ -0,0 +1,35 @@ + + + + 2a + 2b + + + + 5 + + 4 + + 5 + + + + + 1 + 1 + + + 2 + 2 + + + 3 + 3 + + + + diff --git a/test/Reader/TestAssets/Xml/include-base.xml b/test/Reader/TestAssets/Xml/include-base.xml new file mode 100644 index 0000000..3c52f34 --- /dev/null +++ b/test/Reader/TestAssets/Xml/include-base.xml @@ -0,0 +1,4 @@ + + + + \ 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/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/Yaml/include-base.yaml b/test/Reader/TestAssets/Yaml/include-base.yaml new file mode 100644 index 0000000..4f891f2 --- /dev/null +++ b/test/Reader/TestAssets/Yaml/include-base.yaml @@ -0,0 +1 @@ +@include: include-target.yaml \ No newline at end of file diff --git a/test/Reader/TestAssets/Yaml/include-target.yaml b/test/Reader/TestAssets/Yaml/include-target.yaml new file mode 100644 index 0000000..d867783 --- /dev/null +++ b/test/Reader/TestAssets/Yaml/include-target.yaml @@ -0,0 +1 @@ +foo: foo \ No newline at end of file diff --git a/test/Reader/XmlTest.php b/test/Reader/XmlTest.php new file mode 100644 index 0000000..9258a74 --- /dev/null +++ b/test/Reader/XmlTest.php @@ -0,0 +1,98 @@ +reader = new Xml(); + } + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) + { + return __DIR__ . '/TestAssets/Xml/' . $name . '.xml'; + } + + public function testInvalidXmlFile() + { + $this->reader = new Xml(); + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayXml = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testFromString() + { + $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); + } + + public function testZF300_MultipleKeysOfTheSameName() + { + $config = $this->reader->fromFile($this->getTestAssetPath('array')); + + $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']); + } + + public function testZF300_ArraysWithMultipleChildren() + { + $config = $this->reader->fromFile($this->getTestAssetPath('array')); + + $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']); + } +} diff --git a/test/Reader/YamlTest.php b/test/Reader/YamlTest.php new file mode 100644 index 0000000..cf9be60 --- /dev/null +++ b/test/Reader/YamlTest.php @@ -0,0 +1,91 @@ +markTestSkipped('Yaml test for Zend\Config skipped'); + } + + if (constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE')) { + require_once constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE'); + } + + $yamlReader = explode('::', constant('TESTS_ZEND_CONFIG_READER_YAML_CALLBACK')); + if (isset($yamlReader[1])) { + $this->reader = new YamlReader(array($yamlReader[0], $yamlReader[1])); + } else { + $this->reader = new YamlReader(array($yamlReader[0])); + } + } + + /** + * getTestAssetPath(): defined by AbstractReaderTestCase. + * + * @see AbstractReaderTestCase::getTestAssetPath() + * @return string + */ + protected function getTestAssetPath($name) + { + return __DIR__ . '/TestAssets/Yaml/' . $name . '.yaml'; + } + + public function testInvalidIniFile() + { + $this->setExpectedException('Zend\Config\Exception\RuntimeException'); + $arrayIni = $this->reader->fromFile($this->getTestAssetPath('invalid')); + } + + public function testFromString() + { + $yaml = <<reader->fromString($yaml); + $this->assertEquals($arrayYaml['test'], 'foo'); + $this->assertEquals($arrayYaml['bar'][0], 'baz'); + $this->assertEquals($arrayYaml['bar'][1], 'foo'); + } + + public function testFromStringWithSection() + { + $yaml = <<reader->fromString($yaml); + $this->assertEquals($arrayYaml['all']['test'], 'foo'); + $this->assertEquals($arrayYaml['all']['bar'][0], 'baz'); + $this->assertEquals($arrayYaml['all']['bar'][1], 'foo'); + } +} diff --git a/test/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/Php/include-base.php b/test/TestAssets/Php/include-base.php new file mode 100644 index 0000000..f773522 --- /dev/null +++ b/test/TestAssets/Php/include-base.php @@ -0,0 +1,6 @@ + array( + 'bar' => 'baz', + ), +); diff --git a/test/TestAssets/Php/include-base2.php b/test/TestAssets/Php/include-base2.php new file mode 100644 index 0000000..a870592 --- /dev/null +++ b/test/TestAssets/Php/include-base2.php @@ -0,0 +1,6 @@ + array( + 'foo' => 'bar', + ), +); diff --git a/test/TestAssets/Php/include-base3.php b/test/TestAssets/Php/include-base3.php new file mode 100644 index 0000000..04fa19b --- /dev/null +++ b/test/TestAssets/Php/include-base3.php @@ -0,0 +1,6 @@ + array( + '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/TestAssets/bad.ext b/test/TestAssets/bad.ext new file mode 100644 index 0000000..e69de29 diff --git a/test/TestAssets/dummy.dum b/test/TestAssets/dummy.dum new file mode 100644 index 0000000..3379326 --- /dev/null +++ b/test/TestAssets/dummy.dum @@ -0,0 +1 @@ +a:3:{s:3:"one";i:1;s:3:"two";i:2;s:5:"three";i:3;} \ No newline at end of file diff --git a/test/Writer/AbstractWriterTestCase.php b/test/Writer/AbstractWriterTestCase.php new file mode 100644 index 0000000..921a89b --- /dev/null +++ b/test/Writer/AbstractWriterTestCase.php @@ -0,0 +1,93 @@ +tmpfile)) { + $this->tmpfile = tempnam(sys_get_temp_dir(), 'zend-config-writer'); + } + return $this->tmpfile; + } + + public function tearDown() + { + if (file_exists($this->getTestAssetFileName())) { + if (!is_writable($this->getTestAssetFileName())) { + chmod($this->getTestAssetFileName(), 0777); + } + @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/IniTest.php b/test/Writer/IniTest.php new file mode 100644 index 0000000..287ad4d --- /dev/null +++ b/test/Writer/IniTest.php @@ -0,0 +1,53 @@ +reader = new IniReader(); + $this->writer = new IniWriter(); + } + + public function testNoSection() + { + $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('foo', $config['test']); + $this->assertEquals('bar', $config['test2']['test3']); + } + + public function testWriteAndReadOriginalFile() + { + $config = $this->reader->fromFile(__DIR__ . '/_files/allsections.ini'); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('multi', $config['all']['one']['two']['three']); + } +} diff --git a/test/Writer/JsonTest.php b/test/Writer/JsonTest.php new file mode 100644 index 0000000..a37ba6a --- /dev/null +++ b/test/Writer/JsonTest.php @@ -0,0 +1,54 @@ +reader = new JsonReader(); + $this->writer = new JsonWriter(); + } + + public function testNoSection() + { + $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('foo', $config['test']); + $this->assertEquals('bar', $config['test2']['test3']); + } + + public function testWriteAndReadOriginalFile() + { + $config = $this->reader->fromFile(__DIR__ . '/_files/allsections.json'); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('multi', $config['all']['one']['two']['three']); + + } +} diff --git a/test/Writer/PhpArrayTest.php b/test/Writer/PhpArrayTest.php new file mode 100644 index 0000000..2dae349 --- /dev/null +++ b/test/Writer/PhpArrayTest.php @@ -0,0 +1,55 @@ +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/TestAssets/PhpReader.php b/test/Writer/TestAssets/PhpReader.php new file mode 100644 index 0000000..909ff1e --- /dev/null +++ b/test/Writer/TestAssets/PhpReader.php @@ -0,0 +1,19 @@ +writer = new XmlWriter(); + $this->reader = new XmlReader(); + } + + public function testToString() + { + $config = new Config(array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo'))); + + $configString = $this->writer->toString($config); + + $expected = << + + foo + baz + foo + + +ECS; + + $this->assertEquals($expected, $configString); + } + + public function testSectionsToString() + { + $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 = << + + + www.example.com + + + localhost + production + secret + dbproduction + + + + + +ECS; + + $this->assertEquals($expected, $configString); + } +} diff --git a/test/Writer/YamlTest.php b/test/Writer/YamlTest.php new file mode 100644 index 0000000..d0d9db1 --- /dev/null +++ b/test/Writer/YamlTest.php @@ -0,0 +1,73 @@ +markTestSkipped('Yaml test for Zend\Config skipped'); + } + + if (constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE')) { + require_once constant('TESTS_ZEND_CONFIG_YAML_LIB_INCLUDE'); + } + + $yamlReader = explode('::', constant('TESTS_ZEND_CONFIG_READER_YAML_CALLBACK')); + if (isset($yamlReader[1])) { + $this->reader = new YamlReader(array($yamlReader[0], $yamlReader[1])); + } else { + $this->reader = new YamlReader(array($yamlReader[0])); + } + + $yamlWriter = explode('::', constant('TESTS_ZEND_CONFIG_WRITER_YAML_CALLBACK')); + if (isset($yamlWriter[1])) { + $this->writer = new YamlWriter(array($yamlWriter[0], $yamlWriter[1])); + } else { + $this->writer = new YamlWriter(array($yamlWriter[0])); + } + } + + public function testNoSection() + { + $config = new Config(array('test' => 'foo', 'test2' => array('test3' => 'bar'))); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('foo', $config['test']); + $this->assertEquals('bar', $config['test2']['test3']); + } + + public function testWriteAndReadOriginalFile() + { + $config = $this->reader->fromFile(__DIR__ . '/_files/allsections.yaml'); + + $this->writer->toFile($this->getTestAssetFileName(), $config); + + $config = $this->reader->fromFile($this->getTestAssetFileName()); + + $this->assertEquals('multi', $config['all']['one']['two']['three']); + + } +} diff --git a/test/Writer/_files/allsections.ini b/test/Writer/_files/allsections.ini new file mode 100644 index 0000000..4eaa75b --- /dev/null +++ b/test/Writer/_files/allsections.ini @@ -0,0 +1,26 @@ +[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] +hostname = staging +db.name = dbstaging +debug = false + +[debug] +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/Writer/_files/allsections.json b/test/Writer/_files/allsections.json new file mode 100644 index 0000000..d47bd4e --- /dev/null +++ b/test/Writer/_files/allsections.json @@ -0,0 +1,45 @@ +{ +"all" : { + "hostname" : "all", + "name" : "thisname", + "db" : { + "host" : "127.0.0.1", + "user" : "username", + "pass" : "password", + "name" : "live" + }, + "one" : { + "two" : { + "three" : "multi" + } + } +}, +"staging" : { + "hostname" : "staging", + "db" : { + "name" : "dbstaging" + }, + "debug" : "false" +}, +"debug" : { + "hostname" : "debug", + "debug" : "true", + "values" : { + "changed" : "yes" + }, + "db" : { + "name" : "dbdebug" + }, + "special" : { + "no" : "no", + "null" : "null", + "false" : "false" + } +}, +"other_staging" : { + "only_in" : "otherStaging", + "db" : { + "pass" : "anotherpwd" + } +} +} \ No newline at end of file diff --git a/test/Writer/_files/allsections.xml b/test/Writer/_files/allsections.xml new file mode 100644 index 0000000..1abb816 --- /dev/null +++ b/test/Writer/_files/allsections.xml @@ -0,0 +1,35 @@ + + + + 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/Writer/_files/allsections.yaml b/test/Writer/_files/allsections.yaml new file mode 100644 index 0000000..1dafe98 --- /dev/null +++ b/test/Writer/_files/allsections.yaml @@ -0,0 +1,35 @@ +all: +# this is a comment + hostname: all + name: thisname + db: + host: 127.0.0.1 + user: username + pass: password + name: live + one: + two: + three: multi + +staging: + hostname: staging + db: + name: dbstaging + debug: + _extends: all +debug: + hostname: debug + debug: 1 + values: + changed: 1 + db: + name: dbdebug + special: + no: + null: + false: + _extends: all +other_staging: + only_in: otherStaging + db: + pass: anotherpwd diff --git a/test/_files/indentedcomments.yaml b/test/_files/indentedcomments.yaml new file mode 100644 index 0000000..4b7b767 --- /dev/null +++ b/test/_files/indentedcomments.yaml @@ -0,0 +1,4 @@ +resources: + #frontcontroller! + frontController: + controllerDirectory: APPLICATION_PATH/controllers \ No newline at end of file diff --git a/test/_files/inlinecomments.yaml b/test/_files/inlinecomments.yaml new file mode 100644 index 0000000..c3b75e6 --- /dev/null +++ b/test/_files/inlinecomments.yaml @@ -0,0 +1,3 @@ +resources: + frontController: + controllerDirectory: APPLICATION_PATH/controllers #heynow! \ No newline at end of file diff --git a/test/_files/listbooleans.yaml b/test/_files/listbooleans.yaml new file mode 100644 index 0000000..21fc789 --- /dev/null +++ b/test/_files/listbooleans.yaml @@ -0,0 +1,51 @@ +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/_files/listconstants.yaml b/test/_files/listconstants.yaml new file mode 100644 index 0000000..86610ca --- /dev/null +++ b/test/_files/listconstants.yaml @@ -0,0 +1,4 @@ +production: + paths: + - ZEND_CONFIG_YAML_TEST_PATH + - ZEND_CONFIG_YAML_TEST_PATH/library/test diff --git a/test/_files/translations-de_DE.php b/test/_files/translations-de_DE.php new file mode 100644 index 0000000..5f42e0b --- /dev/null +++ b/test/_files/translations-de_DE.php @@ -0,0 +1,5 @@ + 'ein Hund', + 'two dogs' => 'zwei Hunde' +); diff --git a/test/bootstrap.php b/test/bootstrap.php new file mode 100644 index 0000000..057f291 --- /dev/null +++ b/test/bootstrap.php @@ -0,0 +1,34 @@ + Date: Mon, 8 Oct 2012 20:27:45 +0200 Subject: [PATCH 09/12] Add unit tests and fix minor errors --- src/Factory.php | 32 ++++++--- test/FactoryTest.php | 92 +++++++++++++++++++++++++- test/Writer/TestAssets/DummyWriter.php | 23 +++++++ 3 files changed, 137 insertions(+), 10 deletions(-) create mode 100755 test/Writer/TestAssets/DummyWriter.php diff --git a/src/Factory.php b/src/Factory.php index 6c900dd..0407e8f 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -52,7 +52,7 @@ class Factory * @var array */ protected static $writerExtensions = array( - 'php' => 'PhpArray', + 'php' => 'php', 'ini' => 'ini', 'json' => 'json', 'xml' => 'xml', @@ -132,8 +132,9 @@ public static function fromFiles(array $files, $returnConfigObject = false) * * @param string $filename * @param array|Config $config - * * @return boolean TRUE on success | FALSE on failure + * @throws Exception\RuntimeException + * @throws Exception\InvalidArgumentException */ public static function toFile($filename, $config) { @@ -142,7 +143,7 @@ public static function toFile($filename, $config) (!is_object($config) && !is_array($config)) ) { throw new Exception\InvalidArgumentException( - __METHOD__." \$config should be an array or instance of Zend\Config\Config" + __METHOD__." \$config should be an array or instance of Zend\\Config\\Config" ); } @@ -161,29 +162,32 @@ public static function toFile($filename, $config) ); } - if(!isset(self::$extensionWriters[$extension])) { + if(!isset(self::$writerExtensions[$extension])) { throw new Exception\RuntimeException( - "Unsupported config file extension: .{$extension}" + "Unsupported config file extension: '.{$extension}' for writing." ); } - $writer = self::$extensionWriters[$extension]; + $writer = self::$writerExtensions[$extension]; if (($writer instanceOf Writer\AbstractWriter) === false) { $writer = self::getWriterPluginManager()->get($writer); - self::$extensionWriters[$extension] = $writer; + self::$writerExtensions[$extension] = $writer; } if (is_object($config)) { $config = $config->toArray(); } - return file_put_contents($filename, $writer->processConfig($config)); + $content = $writer->processConfig($config); + + return (bool) (file_put_contents($filename, $content) !== false); } /** * Set reader plugin manager * * @param ReaderPluginManager $readers + * @return void */ public static function setReaderPluginManager(ReaderPluginManager $readers) { @@ -207,6 +211,7 @@ public static function getReaderPluginManager() * Set writer plugin manager * * @param WriterPluginManager $writers + * @return void */ public static function setWriterPluginManager(WriterPluginManager $writers) { @@ -233,6 +238,7 @@ public static function getWriterPluginManager() * @param string $extension * @param string|Reader\ReaderInterface $reader * @throws Exception\InvalidArgumentException + * @return void */ public static function registerReader($extension, $reader) { @@ -250,6 +256,14 @@ public static function registerReader($extension, $reader) self::$extensions[$extension] = $reader; } + /** + * Set config writer for file extension + * + * @param string $extension + * @param string|Writer\AbstractWriter $writer + * @throw Exception\InvalidArgumentException + * @return void + */ public static function registerWriter($extension, $writer) { $extension = strtolower($extension); @@ -263,6 +277,6 @@ public static function registerWriter($extension, $writer) )); } - self::$extensions[$extension] = $writer; + self::$writerExtensions[$extension] = $writer; } } diff --git a/test/FactoryTest.php b/test/FactoryTest.php index 3f5d724..3f72b74 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -20,6 +20,28 @@ */ class FactoryTest extends \PHPUnit_Framework_TestCase { + protected $tmpFiles = array(); + + protected function getTestAssetFileName($ext) + { + if (empty($this->tmpfiles[$ext])) { + $this->tmpfiles[$ext] = tempnam(sys_get_temp_dir(), 'zend-config-writer').'.'.$ext; + } + return $this->tmpfiles[$ext]; + } + + public function tearDown() + { + foreach($this->tmpFiles as $file) { + if (file_exists($file)) { + if (!is_writable($file)) { + chmod($file, 0777); + } + @unlink($file); + } + } + } + public function testFromIni() { $config = Factory::fromFile(__DIR__ . '/TestAssets/Ini/include-base.ini'); @@ -125,7 +147,7 @@ public function testFactoryCanRegisterCustomReaderInstance() $this->assertEquals($configObject['one'], 1); } - public function testFactoryCanRegisterCustomReaderPlugn() + public function testFactoryCanRegisterCustomReaderPlugin() { $dummyReader = new Reader\TestAssets\DummyReader(); Factory::getReaderPluginManager()->setService('DummyReader', $dummyReader); @@ -138,5 +160,73 @@ public function testFactoryCanRegisterCustomReaderPlugn() $this->assertEquals($configObject['one'], 1); } + public function testFactoryToFileInvalidFileExtension() + { + $this->setExpectedException('RuntimeException'); + $result = Factory::toFile(__DIR__.'/TestAssets/bad.ext', array()); + } + + public function testFactoryToFileNoDirInHere() + { + $this->setExpectedException('RuntimeException'); + $result = Factory::toFile(__DIR__.'/TestAssets/NoDirInHere/nonExisiting/dummy.php', array()); + } + + public function testFactoryWriteToFile() + { + $config = array('test' => 'foo', 'bar' => array(0 => 'baz', 1 => 'foo')); + + $file = $this->getTestAssetFileName('php'); + $result = Factory::toFile($file, $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(true, $result); + $this->assertEquals($expected, file_get_contents($file)); + } + + public function testFactoryToFileWrongConfig() + { + $this->setExpectedException('InvalidArgumentException'); + $result = Factory::toFile('test.ini', 'Im wrong'); + } + + public function testFactoryRegisterInvalidWriter() + { + $this->setExpectedException('InvalidArgumentException'); + Factory::registerWriter('dum', new Reader\TestAssets\DummyReader()); + } + + public function testFactoryCanRegisterCustomWriterInstance() + { + Factory::registerWriter('dum', new Writer\TestAssets\DummyWriter()); + + $file = $this->getTestAssetFileName('dum'); + $res = Factory::toFile($file, array('one' => 1)); + + $this->assertEquals($res, true); + } + + public function testFactoryCanRegisterCustomWriterPlugin() + { + $dummyWriter = new Writer\TestAssets\DummyWriter(); + Factory::getWriterPluginManager()->setService('DummyWriter', $dummyWriter); + + Factory::registerWriter('dum', 'DummyWriter'); + + $file = $this->getTestAssetFileName('dum'); + + $res = Factory::toFile($file, array('one' => 1)); + $this->assertEquals($res, true); + } } diff --git a/test/Writer/TestAssets/DummyWriter.php b/test/Writer/TestAssets/DummyWriter.php new file mode 100755 index 0000000..8bf8ba9 --- /dev/null +++ b/test/Writer/TestAssets/DummyWriter.php @@ -0,0 +1,23 @@ + Date: Mon, 8 Oct 2012 20:30:47 +0200 Subject: [PATCH 10/12] fix comment --- src/Factory.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index 0407e8f..25986d2 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -128,14 +128,14 @@ public static function fromFiles(array $files, $returnConfigObject = false) } /** - * Writes a config to a file - * - * @param string $filename - * @param array|Config $config - * @return boolean TRUE on success | FALSE on failure - * @throws Exception\RuntimeException - * @throws Exception\InvalidArgumentException - */ + * Writes a config to a file + * + * @param string $filename + * @param array|Config $config + * @return boolean TRUE on success | FALSE on failure + * @throws Exception\RuntimeException + * @throws Exception\InvalidArgumentException + */ public static function toFile($filename, $config) { if ( From 2083d4285a585ecf5e1788eb9a56f6fa37b81c2b Mon Sep 17 00:00:00 2001 From: Jesper Dolieslager Date: Mon, 8 Oct 2012 22:04:39 +0200 Subject: [PATCH 11/12] fix eof --- src/WriterPluginManager.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/WriterPluginManager.php b/src/WriterPluginManager.php index 58598c5..35717f5 100755 --- a/src/WriterPluginManager.php +++ b/src/WriterPluginManager.php @@ -27,4 +27,3 @@ public function validatePlugin($plugin) ); } } - From bc87fcff205161c5eb20670307a8b3a579072e3c Mon Sep 17 00:00:00 2001 From: Jesper Dolieslager Date: Tue, 9 Oct 2012 07:55:12 +0200 Subject: [PATCH 12/12] eol in tests ;) --- test/Writer/TestAssets/DummyWriter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Writer/TestAssets/DummyWriter.php b/test/Writer/TestAssets/DummyWriter.php index 8bf8ba9..d5a989c 100755 --- a/test/Writer/TestAssets/DummyWriter.php +++ b/test/Writer/TestAssets/DummyWriter.php @@ -20,4 +20,3 @@ public function processConfig(array $config) return serialize($config); } } -