From b1e66f00690ce59200b4be9f354aeff5227f869a Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 12:07:24 -0600 Subject: [PATCH 01/17] Require psr/container - and conflict with container-interop < 1.2.0. --- composer.json | 6 ++- composer.lock | 100 +++++++++++++++++++++++++------------------------- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/composer.json b/composer.json index 1a9fd49..4648cd4 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ }, "require": { "php": "^5.6 || ^7.0", - "zendframework/zend-stdlib": "^2.7 || ^3.0" + "zendframework/zend-stdlib": "^2.7 || ^3.0", + "psr/container": "^1.0" }, "require-dev": { "zendframework/zend-filter": "^2.6", @@ -24,6 +25,9 @@ "phpunit/phpunit": "^5.7 || ^6.0", "zendframework/zend-coding-standard": "~1.0.0" }, + "conflict": { + "container-interop/container-interop": "<1.2.0" + }, "suggest": { "zendframework/zend-filter": "Zend\\Filter component", "zendframework/zend-i18n": "Zend\\I18n component", diff --git a/composer.lock b/composer.lock index cc44bc5..cae36f2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,57 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "24892bd677512c9e4ac8d7501256a956", + "content-hash": "0e670d06fc67e3463d1e4f16139ce192", "packages": [ + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" + }, { "name": "zendframework/zend-stdlib", "version": "3.1.0", @@ -773,55 +822,6 @@ ], "time": "2017-02-02T10:36:38+00:00" }, - { - "name": "psr/container", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Container\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", - "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "time": "2017-02-14T16:28:37+00:00" - }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.0", From 59921f54ba62a27350ff657a68449236af5f5ba5 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 12:11:20 -0600 Subject: [PATCH 02/17] Update `Factory` to typehint on psr/container interface, not specific plugin managers Allows usage with any PSR-11 implementation, not just the zend-servicemanager-based ones present. --- src/Factory.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index c7015fe..fb9bd66 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -9,6 +9,7 @@ namespace Zend\Config; +use Psr\Container\ContainerInterface; use Zend\ServiceManager\ServiceManager; use Zend\Stdlib\ArrayUtils; @@ -17,14 +18,14 @@ class Factory /** * Plugin manager for loading readers * - * @var null|ReaderPluginManager + * @var null|ContainerInterface */ public static $readers = null; /** * Plugin manager for loading writers * - * @var null|WriterPluginManager + * @var null|ContainerInterface */ public static $writers = null; @@ -204,10 +205,10 @@ public static function toFile($filename, $config) /** * Set reader plugin manager * - * @param ReaderPluginManager $readers + * @param ContainerInterface $readers * @return void */ - public static function setReaderPluginManager(ReaderPluginManager $readers) + public static function setReaderPluginManager(ContainerInterface $readers) { static::$readers = $readers; } @@ -215,7 +216,7 @@ public static function setReaderPluginManager(ReaderPluginManager $readers) /** * Get the reader plugin manager * - * @return ReaderPluginManager + * @return ContainerInterface */ public static function getReaderPluginManager() { @@ -228,10 +229,10 @@ public static function getReaderPluginManager() /** * Set writer plugin manager * - * @param WriterPluginManager $writers + * @param ContainerInterface $writers * @return void */ - public static function setWriterPluginManager(WriterPluginManager $writers) + public static function setWriterPluginManager(ContainerInterface $writers) { static::$writers = $writers; } @@ -239,7 +240,7 @@ public static function setWriterPluginManager(WriterPluginManager $writers) /** * Get the writer plugin manager * - * @return WriterPluginManager + * @return ContainerInterface */ public static function getWriterPluginManager() { From a3daad2a07c1921fc4dc3a3baf474819ab1798c5 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 12:35:24 -0600 Subject: [PATCH 03/17] Implemented standalone reader plugin manager --- src/Exception/PluginNotFoundException.php | 17 +++++ src/StandaloneReaderPluginManager.php | 55 ++++++++++++++ test/StandaloneReaderPluginManagerTest.php | 83 ++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 src/Exception/PluginNotFoundException.php create mode 100644 src/StandaloneReaderPluginManager.php create mode 100644 test/StandaloneReaderPluginManagerTest.php diff --git a/src/Exception/PluginNotFoundException.php b/src/Exception/PluginNotFoundException.php new file mode 100644 index 0000000..8147e84 --- /dev/null +++ b/src/Exception/PluginNotFoundException.php @@ -0,0 +1,17 @@ + Reader\Ini::class, + 'json' => Reader\Json::class, + 'xml' => Reader\Xml::class, + 'yaml' => Reader\Yaml::class, + 'javaproperties' => Reader\JavaProperties::class, + ]; + + /** + * @param string $plugin + * @return bool + */ + public function has($plugin) + { + if (in_array($plugin, array_values($this->knownPlugins), true)) { + return true; + } + + return in_array(strtolower($plugin), array_keys($this->knownPlugins), true); + } + + /** + * @param string $plugin + * @return Reader\ReaderInterface + * @throws Exception\PluginNotFoundException + */ + public function get($plugin) + { + if (! $this->has($plugin)) { + throw new Exception\PluginNotFoundException(sprintf( + 'Config reader plugin by name %s not found', + $plugin + )); + } + + if (! class_exists($plugin)) { + $plugin = $this->knownPlugins[strtolower($plugin)]; + } + + return new $plugin(); + } +} diff --git a/test/StandaloneReaderPluginManagerTest.php b/test/StandaloneReaderPluginManagerTest.php new file mode 100644 index 0000000..56597c6 --- /dev/null +++ b/test/StandaloneReaderPluginManagerTest.php @@ -0,0 +1,83 @@ + ['ini', Reader\Ini::class], + 'INI' => ['INI', Reader\Ini::class], + 'json' => ['json', Reader\Json::class], + 'JSON' => ['JSON', Reader\Json::class], + 'xml' => ['xml', Reader\Xml::class], + 'XML' => ['XML', Reader\Xml::class], + 'yaml' => ['yaml', Reader\Yaml::class], + 'YAML' => ['YAML', Reader\Yaml::class], + 'javaproperties' => ['javaproperties', Reader\JavaProperties::class], + 'javaProperties' => ['javaProperties', Reader\JavaProperties::class], + 'JAVAPROPERTIES' => ['JAVAPROPERTIES', Reader\JavaProperties::class], + ]; + } + + /** + * @dataProvider supportedConfigExtensions + */ + public function testCanRetrieveReaderByExtension($extension, $expectedType) + { + $manager = new StandaloneReaderPluginManager(); + $this->assertTrue( + $manager->has($extension), + sprintf('Failed to assert plugin manager has plugin %s', $extension) + ); + + $plugin = $manager->get($extension); + $this->assertInstanceOf($expectedType, $plugin); + } + + public function supportedConfigClassNames() + { + return [ + Reader\Ini::class => [Reader\Ini::class], + Reader\Json::class => [Reader\Json::class], + Reader\Xml::class => [Reader\Xml::class], + Reader\Yaml::class => [Reader\Yaml::class], + Reader\JavaProperties::class => [Reader\JavaProperties::class], + ]; + } + + /** + * @dataProvider supportedConfigClassNames + */ + public function testCanRetrieveReaderByPluginClassName($class) + { + $manager = new StandaloneReaderPluginManager(); + $this->assertTrue( + $manager->has($class), + sprintf('Failed to assert plugin manager has plugin %s', $class) + ); + + $plugin = $manager->get($class); + $this->assertInstanceOf($class, $plugin); + } + + public function testGetThrowsExceptionIfPluginNotFound() + { + $manager = new StandaloneReaderPluginManager(); + $this->expectException(Exception\PluginNotFoundException::class); + $this->expectExceptionMessage('Config reader plugin by name bogus not found'); + $manager->get('bogus'); + } +} From 5d842be17df084ca84a32613cceec41618fb9274 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 12:42:52 -0600 Subject: [PATCH 04/17] Implemented standalone config writer plugin manager --- src/StandaloneWriterPluginManager.php | 56 ++++++++++++++ test/StandaloneWriterPluginManagerTest.php | 85 ++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 src/StandaloneWriterPluginManager.php create mode 100644 test/StandaloneWriterPluginManagerTest.php diff --git a/src/StandaloneWriterPluginManager.php b/src/StandaloneWriterPluginManager.php new file mode 100644 index 0000000..7fe3c15 --- /dev/null +++ b/src/StandaloneWriterPluginManager.php @@ -0,0 +1,56 @@ + Writer\Ini::class, + 'json' => Writer\Json::class, + 'php' => Writer\PhpArray::class, + 'phparray' => Writer\PhpArray::class, + 'xml' => Writer\Xml::class, + 'yaml' => Writer\Yaml::class, + ]; + + /** + * @param string $plugin + * @return bool + */ + public function has($plugin) + { + if (in_array($plugin, array_values($this->knownPlugins), true)) { + return true; + } + + return in_array(strtolower($plugin), array_keys($this->knownPlugins), true); + } + + /** + * @param string $plugin + * @return Reader\ReaderInterface + * @throws Exception\PluginNotFoundException + */ + public function get($plugin) + { + if (! $this->has($plugin)) { + throw new Exception\PluginNotFoundException(sprintf( + 'Config writer plugin by name %s not found', + $plugin + )); + } + + if (! class_exists($plugin)) { + $plugin = $this->knownPlugins[strtolower($plugin)]; + } + + return new $plugin(); + } +} diff --git a/test/StandaloneWriterPluginManagerTest.php b/test/StandaloneWriterPluginManagerTest.php new file mode 100644 index 0000000..96aeb4f --- /dev/null +++ b/test/StandaloneWriterPluginManagerTest.php @@ -0,0 +1,85 @@ + ['ini', Writer\Ini::class], + 'INI' => ['INI', Writer\Ini::class], + 'json' => ['json', Writer\Json::class], + 'JSON' => ['JSON', Writer\Json::class], + 'php' => ['php', Writer\PhpArray::class], + 'PHP' => ['PHP', Writer\PhpArray::class], + 'phparray' => ['phparray', Writer\PhpArray::class], + 'phpArray' => ['phpArray', Writer\PhpArray::class], + 'PhpArray' => ['PhpArray', Writer\PhpArray::class], + 'xml' => ['xml', Writer\Xml::class], + 'XML' => ['XML', Writer\Xml::class], + 'yaml' => ['yaml', Writer\Yaml::class], + 'YAML' => ['YAML', Writer\Yaml::class], + ]; + } + + /** + * @dataProvider supportedConfigTypes + */ + public function testCanRetrieveWriterByType($type, $expectedType) + { + $manager = new StandaloneWriterPluginManager(); + $this->assertTrue( + $manager->has($type), + sprintf('Failed to assert plugin manager has plugin %s', $type) + ); + + $plugin = $manager->get($type); + $this->assertInstanceOf($expectedType, $plugin); + } + + public function supportedConfigClassNames() + { + return [ + Writer\Ini::class => [Writer\Ini::class], + Writer\Json::class => [Writer\Json::class], + Writer\PhpArray::class => [Writer\PhpArray::class], + Writer\Xml::class => [Writer\Xml::class], + Writer\Yaml::class => [Writer\Yaml::class], + ]; + } + + /** + * @dataProvider supportedConfigClassNames + */ + public function testCanRetrieveWriterByPluginClassName($class) + { + $manager = new StandaloneWriterPluginManager(); + $this->assertTrue( + $manager->has($class), + sprintf('Failed to assert plugin manager has plugin %s', $class) + ); + + $plugin = $manager->get($class); + $this->assertInstanceOf($class, $plugin); + } + + public function testGetThrowsExceptionIfPluginNotFound() + { + $manager = new StandaloneWriterPluginManager(); + $this->expectException(Exception\PluginNotFoundException::class); + $this->expectExceptionMessage('Config writer plugin by name bogus not found'); + $manager->get('bogus'); + } +} From a68e5ef268d272ef43c8a457a34b0006dba32371 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 12:49:15 -0600 Subject: [PATCH 05/17] Register standalone plugin manager variants by default Instead of zend-servicemanager variants. Ensures no requirement for zend-servicemanager for standalone usage of the `Factory`. --- src/Factory.php | 4 ++-- test/FactoryTest.php | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index fb9bd66..d7941d5 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -221,7 +221,7 @@ public static function setReaderPluginManager(ContainerInterface $readers) public static function getReaderPluginManager() { if (static::$readers === null) { - static::$readers = new ReaderPluginManager(new ServiceManager()); + static::$readers = new StandaloneReaderPluginManager(); } return static::$readers; } @@ -245,7 +245,7 @@ public static function setWriterPluginManager(ContainerInterface $writers) public static function getWriterPluginManager() { if (static::$writers === null) { - static::$writers = new WriterPluginManager(new ServiceManager()); + static::$writers = new StandaloneWriterPluginManager(); } return static::$writers; diff --git a/test/FactoryTest.php b/test/FactoryTest.php index f6661c8..a823624 100644 --- a/test/FactoryTest.php +++ b/test/FactoryTest.php @@ -12,9 +12,12 @@ use Interop\Container\ContainerInterface; use InvalidArgumentException; use PHPUnit\Framework\TestCase; +use ReflectionProperty; use RuntimeException; use Zend\Config\Factory; use Zend\Config\ReaderPluginManager; +use Zend\Config\StandaloneReaderPluginManager; +use Zend\Config\StandaloneWriterPluginManager; use Zend\Config\WriterPluginManager; /** @@ -37,6 +40,7 @@ public function setUp() { $this->originalIncludePath = get_include_path(); set_include_path(__DIR__ . '/TestAssets'); + $this->resetPluginManagers(); } public function tearDown() @@ -51,6 +55,17 @@ public function tearDown() @unlink($file); } } + + $this->resetPluginManagers(); + } + + public function resetPluginManagers() + { + foreach (['readers', 'writers'] as $pluginManager) { + $r = new ReflectionProperty(Factory::class, $pluginManager); + $r->setAccessible(true); + $r->setValue(null); + } } public function testFromIni() @@ -257,4 +272,16 @@ public function testFactoryCanRegisterCustomWriterPlugin() $res = Factory::toFile($file, ['one' => 1]); $this->assertEquals($res, true); } + + public function testDefaultReaderPluginManagerIsStandaloneVariant() + { + $readers = Factory::getReaderPluginManager(); + $this->assertInstanceOf(StandaloneReaderPluginManager::class, $readers); + } + + public function testDefaultWriterPluginManagerIsStandaloneVariant() + { + $writers = Factory::getWriterPluginManager(); + $this->assertInstanceOf(StandaloneWriterPluginManager::class, $writers); + } } From 53ede3dfc5cae28d785d3169861aa6e3ff366ef4 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 12:57:58 -0600 Subject: [PATCH 06/17] Added migration chapter detailing standalone plugin managers --- doc/book/migration/to-v3.md | 35 +++++++++++++++++++++++++++++++++++ mkdocs.yml | 4 +++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 doc/book/migration/to-v3.md diff --git a/doc/book/migration/to-v3.md b/doc/book/migration/to-v3.md new file mode 100644 index 0000000..b45b7d4 --- /dev/null +++ b/doc/book/migration/to-v3.md @@ -0,0 +1,35 @@ +# Migration to version 3 + +Version 3 is essentially fully backwards compatible with previous versions, with +one key exception: `Zend\Config\Factory` no longer requires usage of +zend-servicemanager for resolving plugins. + +The reason this is considered a backwards compatibility break, however, is due +to signature changes: + +- `Factory::setReaderPluginManager()` now accepts a + `Psr\Container\ContainerInterface`, and not a `Zend\Config\ReaderPluginManager` + instance; `ReaderPluginManager`, however, still fulfills that typehint. + +- `Factory::getReaderPluginManager()` now returns a + `Psr\Container\ContainerInterface` — specifically, a + `Zend\Config\StandaloneReaderPluginManager` — and not a + `Zend\Config\ReaderPluginManager` instance, by default; `ReaderPluginManager`, + however, still fulfills that typehint. + +- `Factory::setWriterPluginManager()` now accepts a + `Psr\Container\ContainerInterface`, and not a `Zend\Config\WriterPluginManager` + instance; `WriterPluginManager`, however, still fulfills that typehint. + +- `Factory::getWriterPluginManager()` now returns a + `Psr\Container\ContainerInterface` — specifically, a + `Zend\Config\StandaloneWriterPluginManager` — and not a + `Zend\Config\WriterPluginManager` instance, by default; `WriterPluginManager`, + however, still fulfills that typehint. + +If you were extending the class, you will need to update your signatures +accordingly. + +This particular update means that you may use any PSR-11 container as a reader +or writer plugin manager, and no longer require installation of +zend-servicemanager to use the plugin manager facilities. diff --git a/mkdocs.yml b/mkdocs.yml index ca15abd..19a2687 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -9,7 +9,9 @@ pages: - "Zend\\Config\\Writer": writer.md - "Zend\\Config\\Processor": processor.md - "Config Factory": factory.md + - Migration: + - "To version 3": migration/to-v3.md site_name: zend-config site_description: Zend\Config repo_url: 'https://github.com/zendframework/zend-config' -copyright: 'Copyright (c) 2016 Zend Technologies USA Inc.' +copyright: 'Copyright (c) 2017 Zend Technologies USA Inc.' From 0b1e92b3c06388fdfdb2290aab426503adde93df Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 13:47:20 -0600 Subject: [PATCH 07/17] Updated to most recent releases of all dependencies Set minimum supported versions to most recent releases of dependencies. In cases where 2.X and 3.X versions exist, and they are compatible, the most recent versons of each are `||`'d. --- composer.json | 10 +++++----- composer.lock | 29 ++++++++++++----------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/composer.json b/composer.json index 4648cd4..6a3f3a1 100644 --- a/composer.json +++ b/composer.json @@ -14,14 +14,14 @@ }, "require": { "php": "^5.6 || ^7.0", - "zendframework/zend-stdlib": "^2.7 || ^3.0", + "zendframework/zend-stdlib": "^2.7.7 || ^3.1", "psr/container": "^1.0" }, "require-dev": { - "zendframework/zend-filter": "^2.6", - "zendframework/zend-i18n": "^2.6", - "zendframework/zend-json": "^2.6.1", - "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-filter": "^2.7.1", + "zendframework/zend-i18n": "^2.7.3", + "zendframework/zend-json": "^2.6.1 || ^3.0", + "zendframework/zend-servicemanager": "^2.7.8 || ^3.2.1", "phpunit/phpunit": "^5.7 || ^6.0", "zendframework/zend-coding-standard": "~1.0.0" }, diff --git a/composer.lock b/composer.lock index cae36f2..33137bf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "0e670d06fc67e3463d1e4f16139ce192", + "content-hash": "fa26bef60e1134caa7ec23ef7cea5bf1", "packages": [ { "name": "psr/container", @@ -1621,40 +1621,35 @@ }, { "name": "zendframework/zend-json", - "version": "2.6.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/zendframework/zend-json.git", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab", + "reference": "f42a1588e75c2a3e338cd94c37906231e616daab", "shasum": "" }, "require": { "php": "^5.5 || ^7.0" }, "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0", - "zendframework/zend-http": "^2.5.4", - "zendframework/zend-server": "^2.6.1", - "zendframework/zend-stdlib": "^2.5 || ^3.0", - "zendframework/zendxml": "^1.0.2" + "squizlabs/php_codesniffer": "^2.3", + "zendframework/zend-stdlib": "^2.7 || ^3.0" }, "suggest": { - "zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server", - "zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server", - "zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses", - "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" + "zendframework/zend-json-server": "For implementing JSON-RPC servers", + "zendframework/zend-xml2json": "For converting XML documents to JSON" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev", - "dev-develop": "2.7-dev" + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" } }, "autoload": { @@ -1672,7 +1667,7 @@ "json", "zf2" ], - "time": "2016-02-04T21:20:26+00:00" + "time": "2016-04-01T02:34:00+00:00" }, { "name": "zendframework/zend-servicemanager", From b67064fd1fbc0e5f8147e12a43f4177f018d98ce Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 14:14:56 -0600 Subject: [PATCH 08/17] Allow usage without zend-json Will now default to ext/json when present. --- composer.json | 8 +- src/Exception/MissingExtensionException.php | 14 ++++ src/Reader/Json.php | 87 ++++++++++++++++++--- src/Writer/Json.php | 16 +++- 4 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 src/Exception/MissingExtensionException.php diff --git a/composer.json b/composer.json index 6a3f3a1..ad0b19f 100644 --- a/composer.json +++ b/composer.json @@ -29,10 +29,10 @@ "container-interop/container-interop": "<1.2.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" + "zendframework/zend-filter": "^2.7.1; install if you want to use the Filter processor", + "zendframework/zend-i18n": "^2.7.3; install if you want to use the Translator processor", + "zendframework/zend-json": "^2.6.1 || ^3.0; install if ext/json is not present, and you want to use the JSON reader or writer", + "zendframework/zend-servicemanager": "^2.7.8 || ^3.2.1; if you need an extensible plugin manager for use with the Config Factory" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/src/Exception/MissingExtensionException.php b/src/Exception/MissingExtensionException.php new file mode 100644 index 0000000..4c17c70 --- /dev/null +++ b/src/Exception/MissingExtensionException.php @@ -0,0 +1,14 @@ +directory = dirname($filename); - try { - $config = JsonFormat::decode(file_get_contents($filename), JsonFormat::TYPE_ARRAY); - } catch (JsonException\RuntimeException $e) { - throw new Exception\RuntimeException($e->getMessage()); - } + $config = $this->decode(file_get_contents($filename)); return $this->process($config); } @@ -69,11 +65,7 @@ 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()); - } + $config = $this->decode($string); return $this->process($config); } @@ -102,4 +94,79 @@ protected function process(array $data) } return $data; } + + /** + * Decode JSON configuration. + * + * Determines if ext/json is present, and, if so, uses that to decode the + * configuration. Otherwise, it uses zend-json, and, if that is missing, + * raises an exception indicating inability to decode. + * + * @param string $data + * @return array + * @throws Exception\RuntimeException for any decoding errors. + * @throws Exception\MissingExtensionException if neither ext/json nor + * zend-json are available. + */ + private function decode($data) + { + if (function_exists('json_decode')) { + return $this->decodeViaExtension($data); + } + + if (class_exists(JsonFormat::class)) { + return $this->decodeViaJsonComponent($data); + } + + throw new Exception\MissingExtensionException( + 'Cannot decode JSON config: missing ext/json. Compile PHP with ' + . 'ext/json, or install zendframework/zend-json' + ); + } + + /** + * Decode the JSON data via ext/json + * + * @param string $data + * @return array + * @throws Exception\RuntimeException if a non-array/non-object was returned + * by the configuration data. + * @throws Exception\RuntimeException if an error occured during decoding. + */ + private function decodeViaExtension($data) + { + $config = json_decode($data, true); + + if (null !== $config && ! is_array($config)) { + throw new Exception\RuntimeException( + 'Invalid JSON configuration; did not return an array or object' + ); + } + + if (null !== $config) { + return $config; + } + + if (JSON_ERROR_NONE === json_last_error()) { + return $config; + } + + throw new Exception\RuntimeException(json_last_error_msg()); + } + + /** + * Use zend-json to decode the configuration data. + * + * @param string $data + * @return array + * @throws Exception\RuntimeException if unable to decode. + */ + private function decodeViaJsonComponent($data) + { + try { + return JsonFormat::decode($data, JsonFormat::TYPE_ARRAY); + } catch (JsonException\RuntimeException $e) { + throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e); + } + } } diff --git a/src/Writer/Json.php b/src/Writer/Json.php index 78a68b3..d6272f2 100644 --- a/src/Writer/Json.php +++ b/src/Writer/Json.php @@ -9,6 +9,7 @@ namespace Zend\Config\Writer; +use Zend\Config\Exception; use Zend\Json\Json as JsonFormat; class Json extends AbstractWriter @@ -18,9 +19,22 @@ class Json extends AbstractWriter * * @param array $config * @return string + * @throws Exception\MissingExtensionException if neither ext/json nor + * zendframework/zend-json are available. */ public function processConfig(array $config) { - return JsonFormat::encode($config); + if (function_exists('json_encode')) { + return json_encode($config); + } + + if (class_exists(JsonFormat::class)) { + return JsonFormat::encode($config); + } + + throw new Exception\MissingExtensionException( + 'Cannot write JSON config: missing ext/json. Compile PHP with ' + . 'ext/json, or install zendframework/zend-json' + ); } } From 190ffd8672c1af26df594639c038d0b14b198c6e Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 14:28:58 -0600 Subject: [PATCH 09/17] Added license-check to QA toolchain - Now require `malukehno/docheader` in development. - Added configuration via `.docheader`. - `license-check` will check all `src/` files. - `license-check-all` will check all `src/` and `test/` files; there are test assets that are _expected_ to fail. - Travis runs `license-check` for targets doing CS checks. --- .docheader | 5 + .travis.yml | 1 + composer.json | 8 +- composer.lock | 327 +++++++++++++++++- src/AbstractConfigFactory.php | 8 +- src/Config.php | 8 +- src/Exception/ExceptionInterface.php | 8 +- src/Exception/InvalidArgumentException.php | 8 +- src/Exception/RuntimeException.php | 8 +- src/Factory.php | 8 +- src/Processor/Constant.php | 8 +- src/Processor/Filter.php | 8 +- src/Processor/ProcessorInterface.php | 8 +- src/Processor/Queue.php | 8 +- src/Processor/Token.php | 8 +- src/Processor/Translator.php | 8 +- src/Reader/Ini.php | 8 +- src/Reader/JavaProperties.php | 8 +- src/Reader/Json.php | 8 +- src/Reader/ReaderInterface.php | 8 +- src/Reader/Xml.php | 8 +- src/Reader/Yaml.php | 8 +- src/ReaderPluginManager.php | 8 +- src/Writer/AbstractWriter.php | 8 +- src/Writer/Ini.php | 8 +- src/Writer/Json.php | 8 +- src/Writer/PhpArray.php | 8 +- src/Writer/WriterInterface.php | 8 +- src/Writer/Xml.php | 8 +- src/Writer/Yaml.php | 8 +- src/WriterPluginManager.php | 8 +- test/AbstractConfigFactoryTest.php | 9 +- test/ConfigTest.php | 8 +- test/FactoryTest.php | 8 +- test/ProcessorTest.php | 8 +- test/Reader/AbstractReaderTestCase.php | 8 +- test/Reader/IniTest.php | 8 +- test/Reader/JavaPropertiesTest.php | 8 +- test/Reader/JsonTest.php | 8 +- test/Reader/TestAssets/DummyReader.php | 8 +- test/Reader/XmlTest.php | 8 +- test/Reader/YamlTest.php | 8 +- test/ReaderPluginManagerCompatibilityTest.php | 8 +- test/Writer/AbstractWriterTestCase.php | 8 +- test/Writer/IniTest.php | 8 +- test/Writer/JsonTest.php | 8 +- test/Writer/PhpArrayTest.php | 8 +- test/Writer/TestAssets/DummyClassA.php | 8 +- test/Writer/TestAssets/DummyClassB.php | 8 +- test/Writer/TestAssets/DummyWriter.php | 8 +- test/Writer/TestAssets/PhpReader.php | 8 +- test/Writer/XmlTest.php | 8 +- test/Writer/YamlTest.php | 8 +- test/WriterPluginManagerCompatibilityTest.php | 8 +- 54 files changed, 488 insertions(+), 254 deletions(-) create mode 100644 .docheader diff --git a/.docheader b/.docheader new file mode 100644 index 0000000..5602c91 --- /dev/null +++ b/.docheader @@ -0,0 +1,5 @@ +/** + * @see https://github.com/zendframework/zend-config for the canonical source repository + * @copyright Copyright (c) %regexp:(20\d{2}-)?20\d{2}% Zend Technologies USA Inc. (http://www.zend.com) + * @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License + */ diff --git a/.travis.yml b/.travis.yml index 0723966..b6f7886 100644 --- a/.travis.yml +++ b/.travis.yml @@ -80,6 +80,7 @@ install: script: - if [[ $TEST_COVERAGE == 'true' ]]; then composer test-coverage ; else composer test ; fi - if [[ $CHECK_CS == 'true' ]]; then composer cs-check ; fi + - if [[ $CHECK_CS == 'true' ]]; then composer license-check ; fi - if [[ $DEPLOY_DOCS == "true" && "$TRAVIS_TEST_RESULT" == "0" ]]; then travis_retry curl -sSL https://raw.githubusercontent.com/zendframework/zf-mkdoc-theme/master/theme-installer.sh | bash ; fi after_script: diff --git a/composer.json b/composer.json index ad0b19f..c3f0933 100644 --- a/composer.json +++ b/composer.json @@ -18,12 +18,13 @@ "psr/container": "^1.0" }, "require-dev": { + "zendframework/zend-coding-standard": "~1.0.0", "zendframework/zend-filter": "^2.7.1", "zendframework/zend-i18n": "^2.7.3", "zendframework/zend-json": "^2.6.1 || ^3.0", "zendframework/zend-servicemanager": "^2.7.8 || ^3.2.1", - "phpunit/phpunit": "^5.7 || ^6.0", - "zendframework/zend-coding-standard": "~1.0.0" + "malukenho/docheader": "^0.1.5", + "phpunit/phpunit": "^5.7 || ^6.0" }, "conflict": { "container-interop/container-interop": "<1.2.0" @@ -49,11 +50,14 @@ }, "scripts": { "check": [ + "@license-check", "@cs-check", "@test" ], "cs-check": "phpcs", "cs-fix": "phpcbf", + "license-check": "docheader check src/", + "license-check-all": "docheader check src/ test/", "test": "phpunit --colors=always", "test-coverage": "phpunit --colors=always --coverage-clover clover.xml", "upload-coverage": "coveralls -v" diff --git a/composer.lock b/composer.lock index 33137bf..f7da4cf 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "fa26bef60e1134caa7ec23ef7cea5bf1", + "content-hash": "501cc22b3c7da729258998bb2e73b950", "packages": [ { "name": "psr/container", @@ -187,6 +187,56 @@ ], "time": "2015-06-14T21:17:01+00:00" }, + { + "name": "malukenho/docheader", + "version": "0.1.5", + "source": { + "type": "git", + "url": "https://github.com/malukenho/docheader.git", + "reference": "f35ada934d1de3f5ba09970a6541009a41347658" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/malukenho/docheader/zipball/f35ada934d1de3f5ba09970a6541009a41347658", + "reference": "f35ada934d1de3f5ba09970a6541009a41347658", + "shasum": "" + }, + "require": { + "php": "~5.5|^7.0", + "symfony/console": "~2.0|^3.0", + "symfony/finder": "~2.0|^3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.7" + }, + "bin": [ + "bin/docheader" + ], + "type": "library", + "autoload": { + "psr-4": { + "DocHeader\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jefersson Nathan", + "email": "malukenho@phpse.net" + } + ], + "description": "A small library to check header docs", + "homepage": "https://github.com/malukenho/docheader", + "keywords": [ + "Code style", + "code standard", + "license" + ], + "time": "2016-11-17T16:46:05+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.6.0", @@ -822,6 +872,53 @@ ], "time": "2017-02-02T10:36:38+00:00" }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+00:00" + }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.0", @@ -1413,6 +1510,234 @@ ], "time": "2017-02-02T03:30:00+00:00" }, + { + "name": "symfony/console", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "7a8405a9fc175f87fed8a3c40856b0d866d61936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/7a8405a9fc175f87fed8a3c40856b0d866d61936", + "reference": "7a8405a9fc175f87fed8a3c40856b0d866d61936", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/debug": "~2.8|~3.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.8|~3.0", + "symfony/filesystem": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/filesystem": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2017-02-06T12:04:21+00:00" + }, + { + "name": "symfony/debug", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "b4d9818f127c60ce21ed62c395da7df868dc8477" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/b4d9818f127c60ce21ed62c395da7df868dc8477", + "reference": "b4d9818f127c60ce21ed62c395da7df868dc8477", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2017-01-28T02:37:08+00:00" + }, + { + "name": "symfony/finder", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "8c71141cae8e2957946b403cc71a67213c0380d6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/8c71141cae8e2957946b403cc71a67213c0380d6", + "reference": "8c71141cae8e2957946b403cc71a67213c0380d6", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2017-01-02T20:32:22+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", + "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2016-11-14T01:06:16+00:00" + }, { "name": "webmozart/assert", "version": "1.2.0", diff --git a/src/AbstractConfigFactory.php b/src/AbstractConfigFactory.php index 4b57440..0b4cf4b 100644 --- a/src/AbstractConfigFactory.php +++ b/src/AbstractConfigFactory.php @@ -1,10 +1,8 @@ - * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @see https://github.com/zendframework/zend-config for the canonical source repository + * @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com) + * @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License */ namespace ZendTest\Config; diff --git a/test/ConfigTest.php b/test/ConfigTest.php index 3e79623..1357d57 100644 --- a/test/ConfigTest.php +++ b/test/ConfigTest.php @@ -1,10 +1,8 @@ Date: Thu, 16 Feb 2017 14:36:43 -0600 Subject: [PATCH 10/17] Have PluginNotFoundException extend the component RuntimeException --- src/Exception/PluginNotFoundException.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Exception/PluginNotFoundException.php b/src/Exception/PluginNotFoundException.php index 8147e84..9c4956a 100644 --- a/src/Exception/PluginNotFoundException.php +++ b/src/Exception/PluginNotFoundException.php @@ -8,10 +8,8 @@ namespace Zend\Config\Exception; use Psr\Container\NotFoundExceptionInterface; -use RuntimeException; class PluginNotFoundException extends RuntimeException implements - ExceptionInterface, NotFoundExceptionInterface { } From f40b06cfd901d823d265de4027cbe5abb0d75f09 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 15:37:05 -0600 Subject: [PATCH 11/17] Removed redundant whitespace. --- src/StandaloneWriterPluginManager.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/StandaloneWriterPluginManager.php b/src/StandaloneWriterPluginManager.php index 7fe3c15..def9c3b 100644 --- a/src/StandaloneWriterPluginManager.php +++ b/src/StandaloneWriterPluginManager.php @@ -12,12 +12,12 @@ class StandaloneWriterPluginManager implements ContainerInterface { private $knownPlugins = [ - 'ini' => Writer\Ini::class, - 'json' => Writer\Json::class, - 'php' => Writer\PhpArray::class, - 'phparray' => Writer\PhpArray::class, - 'xml' => Writer\Xml::class, - 'yaml' => Writer\Yaml::class, + 'ini' => Writer\Ini::class, + 'json' => Writer\Json::class, + 'php' => Writer\PhpArray::class, + 'phparray' => Writer\PhpArray::class, + 'xml' => Writer\Xml::class, + 'yaml' => Writer\Yaml::class, ]; /** From b20121cd0c3e0a588649cf8a1827f6281cd4365d Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 15:38:48 -0600 Subject: [PATCH 12/17] Added parameter annotations to tests with data providers --- test/StandaloneReaderPluginManagerTest.php | 5 +++++ test/StandaloneWriterPluginManagerTest.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/test/StandaloneReaderPluginManagerTest.php b/test/StandaloneReaderPluginManagerTest.php index 56597c6..022919a 100644 --- a/test/StandaloneReaderPluginManagerTest.php +++ b/test/StandaloneReaderPluginManagerTest.php @@ -34,6 +34,9 @@ public function supportedConfigExtensions() /** * @dataProvider supportedConfigExtensions + * + * @param string $extension Configuration file extension. + * @param string $expectedType Expected plugin class. */ public function testCanRetrieveReaderByExtension($extension, $expectedType) { @@ -60,6 +63,8 @@ public function supportedConfigClassNames() /** * @dataProvider supportedConfigClassNames + * + * @param string $class Plugin class to retrieve and expect. */ public function testCanRetrieveReaderByPluginClassName($class) { diff --git a/test/StandaloneWriterPluginManagerTest.php b/test/StandaloneWriterPluginManagerTest.php index 96aeb4f..0bad224 100644 --- a/test/StandaloneWriterPluginManagerTest.php +++ b/test/StandaloneWriterPluginManagerTest.php @@ -36,6 +36,9 @@ public function supportedConfigTypes() /** * @dataProvider supportedConfigTypes + * + * @param string $type Configuration type. + * @param string $expectedType Expected plugin class. */ public function testCanRetrieveWriterByType($type, $expectedType) { @@ -62,6 +65,8 @@ public function supportedConfigClassNames() /** * @dataProvider supportedConfigClassNames + * + * @param string $class Plugin class to retrieve and expect. */ public function testCanRetrieveWriterByPluginClassName($class) { From 8a23270b1e852390226ee437a46c2349e530222d Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 15:41:03 -0600 Subject: [PATCH 13/17] Document defaults returned by get(Reader|Writer)PluginManager methods --- src/Factory.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index 02f00c9..8607b77 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -212,7 +212,10 @@ public static function setReaderPluginManager(ContainerInterface $readers) } /** - * Get the reader plugin manager + * Get the reader plugin manager. + * + * If none is available, registers and returns a + * StandaloneReaderPluginManager instance by default. * * @return ContainerInterface */ @@ -236,7 +239,10 @@ public static function setWriterPluginManager(ContainerInterface $writers) } /** - * Get the writer plugin manager + * Get the writer plugin manager. + * + * If none is available, registers and returns a + * StandaloneWriterPluginManager instance by default. * * @return ContainerInterface */ From 1567bf09fdc92eb47d6066625057e33a33c8cbf1 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 15:59:39 -0600 Subject: [PATCH 14/17] Require ext/json Instead of optionally requiring ext/json and/or zend-json, just require ext/json. This simplifies internal logic tremendously, and allows removal of a custom exception. --- composer.json | 3 +- composer.lock | 55 ++------------------- src/Exception/MissingExtensionException.php | 14 ------ src/Reader/Json.php | 45 ----------------- src/Writer/Json.php | 16 ++---- 5 files changed, 9 insertions(+), 124 deletions(-) delete mode 100644 src/Exception/MissingExtensionException.php diff --git a/composer.json b/composer.json index c3f0933..04e9e38 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ }, "require": { "php": "^5.6 || ^7.0", + "ext-json": "*", "zendframework/zend-stdlib": "^2.7.7 || ^3.1", "psr/container": "^1.0" }, @@ -21,7 +22,6 @@ "zendframework/zend-coding-standard": "~1.0.0", "zendframework/zend-filter": "^2.7.1", "zendframework/zend-i18n": "^2.7.3", - "zendframework/zend-json": "^2.6.1 || ^3.0", "zendframework/zend-servicemanager": "^2.7.8 || ^3.2.1", "malukenho/docheader": "^0.1.5", "phpunit/phpunit": "^5.7 || ^6.0" @@ -32,7 +32,6 @@ "suggest": { "zendframework/zend-filter": "^2.7.1; install if you want to use the Filter processor", "zendframework/zend-i18n": "^2.7.3; install if you want to use the Translator processor", - "zendframework/zend-json": "^2.6.1 || ^3.0; install if ext/json is not present, and you want to use the JSON reader or writer", "zendframework/zend-servicemanager": "^2.7.8 || ^3.2.1; if you need an extensible plugin manager for use with the Config Factory" }, "minimum-stability": "dev", diff --git a/composer.lock b/composer.lock index f7da4cf..d6610de 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "501cc22b3c7da729258998bb2e73b950", + "content-hash": "1e8323097896236fc51d3b13f716c9e1", "packages": [ { "name": "psr/container", @@ -1944,56 +1944,6 @@ ], "time": "2016-06-07T21:08:30+00:00" }, - { - "name": "zendframework/zend-json", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-json.git", - "reference": "f42a1588e75c2a3e338cd94c37906231e616daab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab", - "reference": "f42a1588e75c2a3e338cd94c37906231e616daab", - "shasum": "" - }, - "require": { - "php": "^5.5 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "^2.3", - "zendframework/zend-stdlib": "^2.7 || ^3.0" - }, - "suggest": { - "zendframework/zend-json-server": "For implementing JSON-RPC servers", - "zendframework/zend-xml2json": "For converting XML documents to JSON" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev", - "dev-develop": "3.1-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Json\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", - "homepage": "https://github.com/zendframework/zend-json", - "keywords": [ - "json", - "zf2" - ], - "time": "2016-04-01T02:34:00+00:00" - }, { "name": "zendframework/zend-servicemanager", "version": "3.2.1", @@ -2062,7 +2012,8 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^5.6 || ^7.0" + "php": "^5.6 || ^7.0", + "ext-json": "*" }, "platform-dev": [] } diff --git a/src/Exception/MissingExtensionException.php b/src/Exception/MissingExtensionException.php deleted file mode 100644 index 4c17c70..0000000 --- a/src/Exception/MissingExtensionException.php +++ /dev/null @@ -1,14 +0,0 @@ -decodeViaExtension($data); - } - - if (class_exists(JsonFormat::class)) { - return $this->decodeViaJsonComponent($data); - } - - throw new Exception\MissingExtensionException( - 'Cannot decode JSON config: missing ext/json. Compile PHP with ' - . 'ext/json, or install zendframework/zend-json' - ); - } - - /** - * Decode the JSON data via ext/json - * - * @param string $data - * @return array - * @throws Exception\RuntimeException if a non-array/non-object was returned - * by the configuration data. - * @throws Exception\RuntimeException if an error occured during decoding. - */ - private function decodeViaExtension($data) { $config = json_decode($data, true); @@ -151,20 +122,4 @@ private function decodeViaExtension($data) throw new Exception\RuntimeException(json_last_error_msg()); } - - /** - * Use zend-json to decode the configuration data. - * - * @param string $data - * @return array - * @throws Exception\RuntimeException if unable to decode. - */ - private function decodeViaJsonComponent($data) - { - try { - return JsonFormat::decode($data, JsonFormat::TYPE_ARRAY); - } catch (JsonException\RuntimeException $e) { - throw new Exception\RuntimeException($e->getMessage(), $e->getCode(), $e); - } - } } diff --git a/src/Writer/Json.php b/src/Writer/Json.php index 1e32205..b6848f8 100644 --- a/src/Writer/Json.php +++ b/src/Writer/Json.php @@ -17,22 +17,16 @@ class Json extends AbstractWriter * * @param array $config * @return string - * @throws Exception\MissingExtensionException if neither ext/json nor - * zendframework/zend-json are available. + * @throws Exception\RuntimeException if encoding errors occur. */ public function processConfig(array $config) { - if (function_exists('json_encode')) { - return json_encode($config); - } + $serialized = json_encode($config, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT); - if (class_exists(JsonFormat::class)) { - return JsonFormat::encode($config); + if (false === $serialized) { + throw new Exception\RuntimeException(json_last_error_msg()); } - throw new Exception\MissingExtensionException( - 'Cannot write JSON config: missing ext/json. Compile PHP with ' - . 'ext/json, or install zendframework/zend-json' - ); + return $serialized; } } From 39d53c30bfa298dc491c501c7caf956bba4f40e3 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 16:05:21 -0600 Subject: [PATCH 15/17] Edited migration document slightly. --- doc/book/migration/to-v3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/book/migration/to-v3.md b/doc/book/migration/to-v3.md index b45b7d4..eb313c8 100644 --- a/doc/book/migration/to-v3.md +++ b/doc/book/migration/to-v3.md @@ -4,8 +4,8 @@ Version 3 is essentially fully backwards compatible with previous versions, with one key exception: `Zend\Config\Factory` no longer requires usage of zend-servicemanager for resolving plugins. -The reason this is considered a backwards compatibility break, however, is due -to signature changes: +The reason this is considered a backwards compatibility break is due to +signature changes: - `Factory::setReaderPluginManager()` now accepts a `Psr\Container\ContainerInterface`, and not a `Zend\Config\ReaderPluginManager` From f7dccff833c3209d052a22db3fa5972c811d52cb Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 16:10:27 -0600 Subject: [PATCH 16/17] Added CHANGELOG entries for #36 --- CHANGELOG.md | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b65aae..781d187 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,48 @@ All notable changes to this project will be documented in this file, in reverse chronological order by release. -## 2.7.0 - TBD +## 3.0.0 - TBD ### Added -- Nothing. +- [#36](https://github.com/zendframework/zend-config/pull/36) adds support for + [PSR-11](http://www.php-fig.org/psr/psr-11/). + +- [#36](https://github.com/zendframework/zend-config/pull/36) adds the class + `Zend\Config\StandaloneReaderPluginManager` for managing config reader plugins. + This implementation implements the PSR-11 `ContainerInterface`, and uses a + hard-coded list of reader plugins. + +- [#36](https://github.com/zendframework/zend-config/pull/36) adds the class + `Zend\Config\StandaloneWriterPluginManager` for managing config writer plugins. + This implementation implements the PSR-11 `ContainerInterface`, and uses a + hard-coded list of writer plugins. + +### Changes + +- [#36](https://github.com/zendframework/zend-config/pull/36) updates the + `Zend\Config\Factory::getReaderPluginManager()` method to lazy-load a + `StandaloneReaderPluginManager` by default, instead of a + `ReaderPluginManager`, allowing usage out-of-the-box without requiring + zend-servicemanager. + +- [#36](https://github.com/zendframework/zend-config/pull/36) updates the + `Zend\Config\Factory::setReaderPluginManager()` method to typehint against + `Psr\Container\ContainerInterface` instead of `ReaderPluginManager`. If you + were extending and overriding that method, you will need to update your + signature. + +- [#36](https://github.com/zendframework/zend-config/pull/36) updates the + `Zend\Config\Factory::getWriterPluginManager()` method to lazy-load a + `StandaloneWriterPluginManager` by default, instead of a + `WriterPluginManager`, allowing usage out-of-the-box without requiring + zend-servicemanager. + +- [#36](https://github.com/zendframework/zend-config/pull/36) updates the + `Zend\Config\Factory::setWriterPluginManager()` method to typehint against + `Psr\Container\ContainerInterface` instead of `WriterPluginManager`. If you + were extending and overriding that method, you will need to update your + signature. ### Deprecated @@ -14,7 +51,9 @@ All notable changes to this project will be documented in this file, in reverse ### Removed -- Nothing. +- [#36](https://github.com/zendframework/zend-config/pull/36) removes usage of + zend-json as a JSON de/serializer in the JSON writer and reader; the + component now requires ext/json is installed to use these features. ### Fixed From 9199d714d76b6dc32a124d8b23afdd873ccedea7 Mon Sep 17 00:00:00 2001 From: Matthew Weier O'Phinney Date: Thu, 16 Feb 2017 16:15:49 -0600 Subject: [PATCH 17/17] Simplfiy travis install script - Always install from lock file - If on 5.6, update the PHPUnit dependency to ensure we get a version that works with that PHP version. - If on the "latest" strategy, do a full update. - If on the "lowest" strategy, do a full update, with `--prefer-lowest`. - If test coverage is requested, install coverage utilities. - Use variables to detail both legacy and coverage dependencies. --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b6f7886..c41323d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,8 @@ cache: env: global: - COMPOSER_ARGS="--no-interaction" + - COVERAGE_DEPS="satooshi/php-coveralls:^1.0" + - LEGACY_DEPS="phpunit/phpunit" - SITE_URL="https://zendframework.github.io/zend-config" - GH_USER_NAME="Matthew Weier O'Phinney" - GH_USER_EMAIL="matthew@weierophinney.net" @@ -68,13 +70,11 @@ before_install: - travis_retry composer self-update install: - - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 && -d vendor/composer ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies phpunit/phpunit ; fi - - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 && ! -d vendor/composer ]]; then travis_retry composer update $COMPOSER_ARGS --ignore-platform-reqs --with-dependencies phpunit/phpunit ; fi - - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 && $DEPS == 'locked' ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies phpunit/phpunit ; fi + - travis_retry composer install $COMPOSER_ARGS --ignore-platform-reqs + - if [[ $TRAVIS_PHP_VERSION =~ ^5.6 ]]; then travis_retry composer update $COMPOSER_ARGS --with-dependencies $LEGACY_DEPS ; fi - if [[ $DEPS == 'latest' ]]; then travis_retry composer update $COMPOSER_ARGS ; fi - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-lowest --prefer-stable $COMPOSER_ARGS ; fi - - travis_retry composer install $COMPOSER_ARGS - - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS satooshi/php-coveralls:^1.0 ; fi + - if [[ $TEST_COVERAGE == 'true' ]]; then travis_retry composer require --dev $COMPOSER_ARGS $COVERAGE_DEPS ; fi - composer show script: