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..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,18 +70,17 @@ 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: - 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/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 diff --git a/composer.json b/composer.json index 1a9fd49..04e9e38 100644 --- a/composer.json +++ b/composer.json @@ -14,21 +14,25 @@ }, "require": { "php": "^5.6 || ^7.0", - "zendframework/zend-stdlib": "^2.7 || ^3.0" + "ext-json": "*", + "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", - "phpunit/phpunit": "^5.7 || ^6.0", - "zendframework/zend-coding-standard": "~1.0.0" + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-filter": "^2.7.1", + "zendframework/zend-i18n": "^2.7.3", + "zendframework/zend-servicemanager": "^2.7.8 || ^3.2.1", + "malukenho/docheader": "^0.1.5", + "phpunit/phpunit": "^5.7 || ^6.0" + }, + "conflict": { + "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-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, @@ -45,11 +49,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 cc44bc5..d6610de 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": "1e8323097896236fc51d3b13f716c9e1", "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", @@ -138,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", @@ -774,17 +873,17 @@ "time": "2017-02-02T10:36:38+00:00" }, { - "name": "psr/container", - "version": "1.0.0", + "name": "psr/log", + "version": "1.0.2", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", "shasum": "" }, "require": { @@ -798,7 +897,7 @@ }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", @@ -811,16 +910,14 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" + "log", + "psr", + "psr-3" ], - "time": "2017-02-14T16:28:37+00:00" + "time": "2016-10-10T12:19:37+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -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", @@ -1619,61 +1944,6 @@ ], "time": "2016-06-07T21:08:30+00:00" }, - { - "name": "zendframework/zend-json", - "version": "2.6.1", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-json.git", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", - "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", - "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" - }, - "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" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev", - "dev-develop": "2.7-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-02-04T21:20:26+00:00" - }, { "name": "zendframework/zend-servicemanager", "version": "3.2.1", @@ -1742,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/doc/book/migration/to-v3.md b/doc/book/migration/to-v3.md new file mode 100644 index 0000000..eb313c8 --- /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 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.' 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 @@ 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 +61,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 +90,36 @@ 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. + */ + private function decode($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()); + } } diff --git a/src/Reader/ReaderInterface.php b/src/Reader/ReaderInterface.php index 1394943..671e32f 100644 --- a/src/Reader/ReaderInterface.php +++ b/src/Reader/ReaderInterface.php @@ -1,10 +1,8 @@ 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/src/StandaloneWriterPluginManager.php b/src/StandaloneWriterPluginManager.php new file mode 100644 index 0000000..def9c3b --- /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/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php index c6707cf..d631db5 100644 --- a/src/Writer/AbstractWriter.php +++ b/src/Writer/AbstractWriter.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 @@ originalIncludePath = get_include_path(); set_include_path(__DIR__ . '/TestAssets'); + $this->resetPluginManagers(); } public function tearDown() @@ -51,6 +53,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 +270,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); + } } diff --git a/test/ProcessorTest.php b/test/ProcessorTest.php index cbd47c1..78dd121 100644 --- a/test/ProcessorTest.php +++ b/test/ProcessorTest.php @@ -1,10 +1,8 @@ ['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 + * + * @param string $extension Configuration file extension. + * @param string $expectedType Expected plugin class. + */ + 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 + * + * @param string $class Plugin class to retrieve and expect. + */ + 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'); + } +} diff --git a/test/StandaloneWriterPluginManagerTest.php b/test/StandaloneWriterPluginManagerTest.php new file mode 100644 index 0000000..0bad224 --- /dev/null +++ b/test/StandaloneWriterPluginManagerTest.php @@ -0,0 +1,90 @@ + ['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 + * + * @param string $type Configuration type. + * @param string $expectedType Expected plugin class. + */ + 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 + * + * @param string $class Plugin class to retrieve and expect. + */ + 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'); + } +} diff --git a/test/Writer/AbstractWriterTestCase.php b/test/Writer/AbstractWriterTestCase.php index 59e6dc5..c12f1c0 100644 --- a/test/Writer/AbstractWriterTestCase.php +++ b/test/Writer/AbstractWriterTestCase.php @@ -1,10 +1,8 @@