├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .php_cs ├── .scrutinizer.yml ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── chkipper.json ├── composer.json ├── hidev.yml ├── history.md ├── logo.png ├── phpunit.xml.dist ├── src ├── Builder.php ├── Package.php ├── Plugin.php ├── configs │ ├── Config.php │ ├── ConfigFactory.php │ ├── Defines.php │ ├── DotEnv.php │ ├── Params.php │ ├── Rebuild.php │ ├── System.php │ └── __rebuild.php ├── exceptions │ ├── BadConfigurationException.php │ ├── CircularDependencyException.php │ ├── Exception.php │ ├── FailedReadException.php │ ├── FailedWriteException.php │ └── UnsupportedFileTypeException.php ├── readers │ ├── AbstractReader.php │ ├── EnvReader.php │ ├── JsonReader.php │ ├── PhpReader.php │ ├── ReaderFactory.php │ └── YamlReader.php └── utils │ ├── ClosureEncoder.php │ ├── Helper.php │ ├── RemoveArrayKeys.php │ └── Resolver.php ├── tests ├── _bootstrap.php ├── composer.json └── unit │ ├── HelperTest.php │ ├── PluginTest.php │ ├── configs │ └── ConfigFactoryTest.php │ └── readers │ └── ReaderFactoryTest.php └── version /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### What steps will reproduce the problem? 4 | 5 | ### What is the expected result? 6 | 7 | ### What do you get instead? 8 | 9 | 10 | ### Additional info 11 | 12 | | Q | A 13 | | ---------------- | --- 14 | | Version | 0.3.? 15 | | Composer Version | 1.8.? 16 | | PHP version | 7.?.? 17 | | Operating system | 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | | Q | A 2 | | -------------------- | --- 3 | | Bugfix? | ✔️/❌ 4 | | Feature? | ✔️/❌ 5 | | Break compatibility? | ✔️/❌ 6 | | Tests pass? | ✔️/❌ 7 | | Fix issues | # 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # local config 2 | /.env 3 | /hidev-local.yml 4 | 5 | # IDE & OS files 6 | .*.swp 7 | .DS_Store 8 | .buildpath 9 | .idea 10 | .project 11 | .settings 12 | Thumbs.db 13 | nbproject 14 | 15 | # composer internals 16 | /composer.lock 17 | /vendor 18 | 19 | # php-cs-fixer cache 20 | .php_cs.cache 21 | 22 | # phpunit generated files 23 | coverage.clover 24 | 25 | # dynamic files 26 | .phpunit.result.cache 27 | 28 | # Binaries 29 | chkipper.phar 30 | composer.phar 31 | ocular.phar 32 | php-cs-fixer.phar 33 | phpstan.phar 34 | phpunit-skelgen.phar 35 | phpunit.phar 36 | 37 | # hidev internals 38 | /.hidev/composer.json 39 | /.hidev/composer.lock 40 | /.hidev/runtime 41 | /.hidev/vendor 42 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | setUsingCache(true) 14 | ->setRiskyAllowed(true) 15 | ->setRules(array( 16 | '@Symfony' => true, 17 | 'header_comment' => [ 18 | 'header' => $header, 19 | 'separate' => 'bottom', 20 | 'location' => 'after_declare_strict', 21 | 'commentType' => 'PHPDoc', 22 | ], 23 | 'binary_operator_spaces' => [ 24 | 'default' => null, 25 | ], 26 | 'concat_space' => ['spacing' => 'one'], 27 | 'array_syntax' => ['syntax' => 'short'], 28 | 'phpdoc_no_alias_tag' => ['replacements' => ['type' => 'var']], 29 | 'blank_line_before_return' => false, 30 | 'phpdoc_align' => false, 31 | 'phpdoc_scalar' => false, 32 | 'phpdoc_separation' => false, 33 | 'phpdoc_to_comment' => false, 34 | 'method_argument_space' => false, 35 | 'ereg_to_preg' => true, 36 | 'blank_line_after_opening_tag' => true, 37 | 'single_blank_line_before_namespace' => true, 38 | 'ordered_imports' => true, 39 | 'phpdoc_order' => true, 40 | 'pre_increment' => true, 41 | 'strict_comparison' => true, 42 | 'strict_param' => true, 43 | 'no_multiline_whitespace_before_semicolons' => true, 44 | 'semicolon_after_instruction' => false, 45 | 'yoda_style' => false, 46 | )) 47 | ->setFinder( 48 | PhpCsFixer\Finder::create() 49 | ->in(__DIR__) 50 | ->notPath('vendor') 51 | ->notPath('runtime') 52 | ->notPath('web/assets') 53 | ) 54 | ; 55 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | checks: 2 | php: 3 | code_rating: true 4 | duplication: true 5 | tools: 6 | php_code_coverage: 7 | enabled: true 8 | external_code_coverage: 9 | timeout: 600 10 | build: 11 | nodes: 12 | analysis: 13 | tests: 14 | override: [php-scrutinizer-run] 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.2 5 | - 7.3 6 | 7 | # faster builds on new travis setup not using sudo 8 | sudo: false 9 | 10 | # cache vendor dirs 11 | cache: 12 | directories: 13 | - $HOME/.composer/cache 14 | 15 | install: 16 | - travis_retry composer self-update && composer --version 17 | - export PATH="$HOME/.composer/vendor/bin:$PATH" 18 | - travis_retry composer install --prefer-dist --no-interaction 19 | 20 | script: 21 | - | 22 | vendor/bin/phpunit $PHPUNIT_FLAGS --coverage-clover=coverage.clover 23 | 24 | after_script: 25 | - wget -c https://scrutinizer-ci.com/ocular.phar 26 | - php php-ocular code-coverage:upload --format=php-clover coverage.clover 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # hiqdev/composer-config-plugin 2 | 3 | ## [0.4.0] - 2020-03-08 4 | 5 | - Fixed config assembling on Windows ([@samdark]) 6 | - Added configuring of output dir ([@hiqsol]) 7 | - Added building alternative configs ([@hiqsol]) 8 | - Added support for `vlucas/phpdotenv` v4 ([@jseliga]) 9 | - Better work with env vars ([@hiqsol]) 10 | - Used `riimu/kit-phpencoder` for variable exporting ([@hiqsol]) 11 | - Bug fixes ([@hiqsol], [@SilverFire], [@samdark], [@noname007], [@jomonkj], [@machour]) 12 | 13 | ## [0.3.0] - 2019-04-11 14 | 15 | - Fixed config reading and merging ([@hiqsol]) 16 | - Added dev-only configs ([@hiqsol], [@samdark]) 17 | - Changed to use `defines` files as is to keep values ([@hiqsol]) 18 | - Reworked configuration files building ([@hiqsol], [@marclaporte], [@loveorigami]) 19 | 20 | ## [0.2.5] - 2017-05-19 21 | 22 | - Added showing package dependencies hierarchy tree with `composer du -v` ([@hiqsol]) 23 | 24 | ## [0.2.4] - 2017-05-18 25 | 26 | - Added proper resolving of config dependencies with `Resolver` class ([@hiqsol]) 27 | - Fixed exportVar closures in Windows ([@SilverFire], [@edgardmessias]) 28 | 29 | ## [0.2.3] - 2017-04-18 30 | 31 | - Added vendor dir arg to `Builder::path` to get config path at given vendor dir ([@hiqsol]) 32 | 33 | ## [0.2.2] - 2017-04-12 34 | 35 | - Improved README ([@hiqsol]) 36 | - Added support for `.env`, JSON and YAML ([@hiqsol]) 37 | 38 | ## [0.2.1] - 2017-03-23 39 | 40 | - Fixed wrong call of `Composer\Config::get()` ([@SilverFire]) 41 | 42 | ## [0.2.0] - 2017-03-15 43 | 44 | - Added initializaion of composer autoloading for project classes become usable in configs ([@hiqsol]) 45 | - Added work with `$config_name` paths for use of already built config ([@hiqsol]) 46 | - Renamed pathes -> paths everywhere ([@hiqsol]) 47 | - Added collecting dev aliases for root package ([@hiqsol]) 48 | 49 | ## [0.1.0] - 2016-12-26 50 | 51 | - Added proper rebuild ([@hiqsol]) 52 | - Changed output dir to `composer-config-plugin-output` ([@hiqsol]) 53 | - Changed: splitted out `Builder` ([@hiqsol]) 54 | - Changed namespace to `hiqdev\composer\config` ([@hiqsol]) 55 | 56 | ## [0.0.9] - 2016-09-22 57 | 58 | - Fixed infinite loop in case of circular dependencies in composer ([@hiqsol]) 59 | 60 | ## [0.0.8] - 2016-08-27 61 | 62 | - Added showing ordered list of packages when verbose option ([@hiqsol]) 63 | 64 | ## [0.0.7] - 2016-08-26 65 | 66 | - Fixed packages processing order again, used original `composer.json` ([@hiqsol]) 67 | 68 | ## [0.0.6] - 2016-08-23 69 | 70 | - Fixed packages processing order ([@hiqsol]) 71 | 72 | ## [0.0.5] - 2016-06-22 73 | 74 | - Added multiple defines ([@hiqsol]) 75 | 76 | ## [0.0.4] - 2016-05-21 77 | 78 | - Added multiple configs and params ([@hiqsol]) 79 | 80 | ## [0.0.3] - 2016-05-20 81 | 82 | - Changed aliases assembling ([@hiqsol]) 83 | 84 | ## [0.0.2] - 2016-05-19 85 | 86 | - Removed replace composer-extension-plugin ([@hiqsol]) 87 | 88 | ## [0.0.1] - 2016-05-18 89 | 90 | - Added basics ([@hiqsol]) 91 | 92 | ## [Development started] - 2016-05-18 93 | 94 | [@SilverFire]: https://github.com/SilverFire 95 | [d.naumenko.a@gmail.com]: https://github.com/SilverFire 96 | [@tafid]: https://github.com/tafid 97 | [andreyklochok@gmail.com]: https://github.com/tafid 98 | [@BladeRoot]: https://github.com/BladeRoot 99 | [bladeroot@gmail.com]: https://github.com/BladeRoot 100 | [@hiqsol]: https://github.com/hiqsol 101 | [sol@hiqdev.com]: https://github.com/hiqsol 102 | [@edgardmessias]: https://github.com/edgardmessias 103 | [edgardmessias@gmail.com]: https://github.com/edgardmessias 104 | [@samdark]: https://github.com/samdark 105 | [sam@rmcreative.ru]: https://github.com/samdark 106 | [@loveorigami]: https://github.com/loveorigami 107 | [loveorigami@mail.ru]: https://github.com/loveorigami 108 | [@marclaporte]: https://github.com/marclaporte 109 | [marc@laporte.name]: https://github.com/marclaporte 110 | [@jseliga]: https://github.com/jseliga 111 | [seliga.honza@gmail.com]: https://github.com/jseliga 112 | [@machour]: https://github.com/machour 113 | [machour@gmail.com]: https://github.com/machour 114 | [@jomonkj]: https://github.com/jomonkj 115 | [jomon.entero@gmail.com]: https://github.com/jomonkj 116 | [@noname007]: https://github.com/noname007 117 | [soul11201@gmail.com]: https://github.com/noname007 118 | [Under development]: https://github.com/hiqdev/composer-config-plugin/compare/0.3.0...HEAD 119 | [0.0.9]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.8...0.0.9 120 | [0.0.8]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.7...0.0.8 121 | [0.0.7]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.6...0.0.7 122 | [0.0.6]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.5...0.0.6 123 | [0.0.5]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.4...0.0.5 124 | [0.0.4]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.3...0.0.4 125 | [0.0.3]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.2...0.0.3 126 | [0.0.2]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.1...0.0.2 127 | [0.0.1]: https://github.com/hiqdev/composer-config-plugin/releases/tag/0.0.1 128 | [0.1.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.9...0.1.0 129 | [0.2.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.1.0...0.2.0 130 | [0.2.1]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.0...0.2.1 131 | [0.2.2]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.1...0.2.2 132 | [0.2.3]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.2...0.2.3 133 | [0.2.4]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.3...0.2.4 134 | [0.2.5]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.4...0.2.5 135 | [0.3.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.5...0.3.0 136 | [0.4.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.3.0...0.4.0 137 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2016-2018, HiQDev (http://hiqdev.com/) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of HiQDev nor the names of its 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DEPRECATED 2 | 3 | **in favour of [yiisoft/composer-config-plugin]** 4 | 5 | Create an issue if you have any problems. 6 | 7 | [yiisoft/composer-config-plugin]: https://github.com/yiisoft/composer-config-plugin 8 | -------------------------------------------------------------------------------- /chkipper.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hiqdev/composer-config-plugin", 3 | "authors": { 4 | "hiqsol": { 5 | "name": "Andrii Vasyliev", 6 | "role": "Project lead", 7 | "email": "sol@hiqdev.com", 8 | "github": "https://github.com/hiqsol", 9 | "homepage": "http://hipanel.com/" 10 | }, 11 | "SilverFire": { 12 | "name": "Dmitry Naumenko", 13 | "role": "Lead backend developer", 14 | "email": "d.naumenko.a@gmail.com", 15 | "github": "https://github.com/SilverFire", 16 | "homepage": "http://silverfire.me/" 17 | }, 18 | "tafid": { 19 | "name": "Andrey Klochok", 20 | "role": "Lead frontend developer", 21 | "email": "andreyklochok@gmail.com", 22 | "github": "https://github.com/tafid", 23 | "homepage": "http://hiqdev.com/" 24 | }, 25 | "BladeRoot": { 26 | "name": "Yuriy Myronchuk", 27 | "role": "QA Lead", 28 | "email": "bladeroot@gmail.com", 29 | "github": "https://github.com/BladeRoot", 30 | "homepage": "http://hiqdev.com/" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hiqdev/composer-config-plugin", 3 | "type": "composer-plugin", 4 | "description": "Composer plugin for config assembling", 5 | "keywords": [ 6 | "composer", 7 | "config", 8 | "assembling", 9 | "plugin" 10 | ], 11 | "homepage": "https://github.com/hiqdev/composer-config-plugin", 12 | "license": "BSD-3-Clause", 13 | "support": { 14 | "email": "support@hiqdev.com", 15 | "source": "https://github.com/hiqdev/composer-config-plugin", 16 | "issues": "https://github.com/hiqdev/composer-config-plugin/issues", 17 | "wiki": "https://github.com/hiqdev/composer-config-plugin/wiki", 18 | "forum": "http://forum.hiqdev.com/" 19 | }, 20 | "authors": [ 21 | { 22 | "name": "Andrii Vasyliev", 23 | "role": "Project lead", 24 | "email": "sol@hiqdev.com", 25 | "homepage": "http://hipanel.com/" 26 | }, 27 | { 28 | "name": "Dmitry Naumenko", 29 | "role": "Lead backend developer", 30 | "email": "d.naumenko.a@gmail.com", 31 | "homepage": "http://silverfire.me/" 32 | }, 33 | { 34 | "name": "Andrey Klochok", 35 | "role": "Lead frontend developer", 36 | "email": "andreyklochok@gmail.com", 37 | "homepage": "http://hiqdev.com/" 38 | }, 39 | { 40 | "name": "Yuriy Myronchuk", 41 | "role": "QA Lead", 42 | "email": "bladeroot@gmail.com", 43 | "homepage": "http://hiqdev.com/" 44 | } 45 | ], 46 | "require": { 47 | "php": ">=7.1", 48 | "composer-plugin-api": "^1.0", 49 | "riimu/kit-phpencoder": "^2.4", 50 | "opis/closure": "^3.3" 51 | }, 52 | "require-dev": { 53 | "phpunit/phpunit": "^7.0", 54 | "composer/composer": "~1.0@dev" 55 | }, 56 | "suggest": { 57 | "vlucas/phpdotenv": "^2.0 for `.env` files support", 58 | "symfony/yaml": "^2.0 || ^3.0 || ^4.0 for YAML files support" 59 | }, 60 | "autoload": { 61 | "psr-4": { 62 | "hiqdev\\composer\\config\\": "src" 63 | } 64 | }, 65 | "extra": { 66 | "class": "hiqdev\\composer\\config\\Plugin", 67 | "branch-alias": { 68 | "dev-master": "1.0.x-dev" 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /hidev.yml: -------------------------------------------------------------------------------- 1 | package: 2 | type: composer-plugin 3 | name: composer-config-plugin 4 | title: Composer plugin for config assembling 5 | headline: Composer Config Plugin 6 | keywords: composer, config, assembling, plugin 7 | description: | 8 | This [Composer] plugin provides assembling 9 | of configurations distributed with composer packages. 10 | This allows to put configuration needed to use package right inside of 11 | the package thus implementing plugin system: package becomes a plugin 12 | holding both the code and it's configuration. 13 | 14 | How it works? 15 | 16 | - scans installed packages for `config-plugin` extra option in their 17 | `composer.json` 18 | - loads `dotenv` files to set `$_ENV` variables 19 | - requires `defines` files to set constants 20 | - requires `params` files 21 | - requires config files 22 | - options collected on earlier steps could and should be used in later 23 | steps, e.g. `$_ENV` should be used for constants and parameters, which 24 | in turn should be used for configs 25 | - files processing order is crucial to achieve expected behavior: options 26 | in root package have priority over options from included packages, more 27 | about it see below in **Files processing order** section 28 | - collected configs are written as PHP files in 29 | `vendor/hiqdev/composer-config-plugin-output` 30 | directory along with information needed to rebuild configs on demand 31 | - then assembled configs can be loaded into application with `require` 32 | 33 | **Read more** about the general idea behind this plugin in [english] or 34 | [russian]. 35 | 36 | [composer]: https://getcomposer.org/ 37 | [english]: https://hiqdev.com/pages/articles/app-organization 38 | [russian]: https://habrahabr.ru/post/329286/ 39 | 40 | readme: 41 | forceRewrite: false 42 | 43 | plugins: 44 | hiqdev/composer-config-plugin: "dev-master" 45 | hiqdev/hidev-php: "dev-master" 46 | hiqdev/hidev-hiqdev: "dev-master" 47 | hiqdev/hidev-readme: "dev-master" 48 | hiqdev/hidev-chkipper: "dev-master" 49 | hiqdev/hidev-composer: "dev-master" 50 | hiqdev/hidev-license: "dev-master" 51 | hiqdev/hidev-php-cs-fixer: "dev-master" 52 | hiqdev/hidev-phpstan: "dev-master" 53 | hiqdev/hidev-phpunit: "dev-master" 54 | hiqdev/hidev-scrutinizer: "dev-master" 55 | hiqdev/hidev-travis: "dev-master" 56 | -------------------------------------------------------------------------------- /history.md: -------------------------------------------------------------------------------- 1 | # hiqdev/composer-config-plugin 2 | 3 | ## [0.4.0] - 2020-03-08 4 | 5 | - Fixed config assembling on Windows 6 | - [217fcbe] 2020-02-21 Fix building config with custom dir under Windows [@samdark] 7 | - [341d3ad] 2020-02-06 Fix config assembly on Windows [@samdark] 8 | - Added configuring of output dir 9 | - [892eb6b] 2020-02-03 Fixed `findOutputDir` to work properly when output dir is not default [@hiqsol] 10 | - [2a84e31] 2020-01-21 Removed unused `OutputDir` class [@hiqsol] 11 | - [4d68359] 2020-02-20 Fixed problem with env vars leaking between alternatives [@hiqsol] 12 | - [0d92a2d] 2019-07-30 Added `config-plugin-output-dir` option description [@hiqsol] 13 | - [7e7b36e] 2019-07-30 Fixed writing to changed output dir [@hiqsol] 14 | - [8a6a588] 2019-07-25 Fixed taking proper dirname depth [@hiqsol] 15 | - [f1b4ff1] 2019-07-25 Added `OutputDir` NOT finished [@hiqsol] 16 | - Added building alternative configs 17 | - [e06125e] 2019-07-26 Fixed getting alternatives [@hiqsol] 18 | - [6a4eb47] 2019-07-25 Fixed bugs in getting alternatives, allowed alternatives file [@hiqsol] 19 | - [7317438] 2019-07-25 Added building `alternatives` [@hiqsol] 20 | - [b1c9639] 2019-07-25 Added more get extra values methods to `Package` class [@hiqsol] 21 | - [42f3c4e] 2019-07-25 Added `Config::clone()` [@hiqsol] 22 | - [910c127] 2019-07-25 Changed `EnvReader` to return all ENV values (was only new) [@hiqsol] 23 | - [1d6dd28] 2019-07-25 Fixed `ReaderFactory` to distinguish builders [@hiqsol] 24 | - Added support for `vlucas/phpdotenv` v4 25 | - [1db8b15] 2020-02-13 Added support for `vlucas/phpdotenv` v4 [@jseliga] 26 | - Better work with env vars 27 | - [d038a30] 2019-12-18 Allowed `-` in params for pushing env vars [@hiqsol] 28 | - [7fa31d1] 2019-10-24 Allowed to push env vars into config arrays [@hiqsol] 29 | - Used `riimu/kit-phpencoder` for variable exporting 30 | - [594aaab] 2019-07-02 Used `riimu/kit-phpencoder` for variable exporting [@hiqsol] 31 | - Bug fixes 32 | - [c18a233] 2020-03-05 Added test for `RemoveArrayKeys` [@hiqsol] 33 | - [c84e82e] 2020-03-05 Refactored out `utils` dir [@hiqsol] 34 | - [7d445fa] 2020-03-04 Added `RemoveArrayKeys` fix utility [@hiqsol] 35 | - [4a6b89c] 2020-02-29 Disabled readme generation by hidev [@hiqsol] 36 | - [fc0df4c] 2020-02-03 Disabled warning if `composer.json` not readable [@hiqsol] 37 | - [0ebcdea] 2020-01-17 Prevented infinite recursion in `getAllFiles()` #48 [@hiqsol] 38 | - [3fd5c38] 2020-01-11 Enabled wildcard config paths [@hiqsol] 39 | - [d238de7] 2019-08-13 Config::putFile() should throw an exception when dir can not be created [@SilverFire] 40 | - [e2e8c7b] 2019-08-25 Fixing files doubling #42 [@hiqsol] 41 | - [3babef6] 2019-08-25 Extended error message for better debugging [@hiqsol] 42 | - [266138a] 2019-08-20 Update README.md [@SilverFire] 43 | - [3e18cbe] 2019-08-01 Greatly simplified export of closures [@hiqsol] 44 | - [fb5a5d8] 2019-07-31 Fix #39: use opis/closure for dumping closure code [@samdark] 45 | - [b5fe4d5] 2019-07-31 Added `$params` initialization in configs [@hiqsol] 46 | - [ef8a42c] 2019-07-31 Redone travis config and require-dev phpunit [@hiqsol] 47 | - [a0401ea] 2019-07-31 Returned back memoization in ReaderFactory [@hiqsol] 48 | - [3d9bb59] 2019-07-31 Add issue and pull request templates [@samdark] 49 | - [77a8eac] 2019-07-04 Raised PHP version requirement to 7.1 #32 [@hiqsol] 50 | - [b36d5ad] 2019-07-04 add 7.0 [@noname007] 51 | - [820a9e6] 2019-05-12 Update Plugin.php [@jomonkj] 52 | - [4f8d841] 2019-04-23 Check both old & new Yii Array helpers classes [@machour] 53 | 54 | ## [0.3.0] - 2019-04-11 55 | 56 | - Fixed config reading and merging 57 | - [efcb091] 2019-04-11 Changed plugin versions to all dev-master [@hiqsol] 58 | - [597227a] 2019-03-22 Added support for both 2nd and 3rd versions of `phpdotenv` [@hiqsol] 59 | - [9f61a78] 2019-01-11 Added processing `UnsetArrayValue` and `ReplaceArrayValue`, allows to fix #20 [@hiqsol] 60 | - [83bc091] 2019-01-11 Added substitution and files reordering, fixes #19 [@hiqsol] 61 | - [0c8c821] 2018-12-20 Added `Plugin::addFile()` and used in loadDotEnv to prevent dublicating [@hiqsol] 62 | - Added dev-only configs 63 | - [959c971] 2018-12-08 Added `config-plugin-dev` [@hiqsol] 64 | - [faab5ed] 2018-12-05 Tuned output to fit composer 1.8+ [@hiqsol] 65 | - [49f65f7] 2018-11-15 Added skiping repeated values [@hiqsol] 66 | - [bf49430] 2018-10-08 Code style fixes (#16) [@samdark] 67 | - [e3e4f78] 2018-10-07 There's no need to duplicate docs since they're all in the readme [@samdark] 68 | - [f4ef5d2] 2018-10-07 More consistency [@samdark] 69 | - [1d807d0] 2018-10-07 Improved readme [@samdark] 70 | - [2543887] 2018-10-07 Explicitly declare PHP 7 requirement in composer.json [@samdark] 71 | - [5cbfdac] 2018-10-07 Fix wrong constructor call arguments [@samdark] 72 | - [99c5696] 2018-09-08 Added `COMPOSER_CONFIG_PLUGIN_BASEDIR` constant definition to generated configs [@hiqsol] 73 | - Changed to use `defines` files as is to keep values 74 | - [34cfa36] 2018-08-24 Fixed writing `defines` with added merging env vars [@hiqsol] 75 | - [3ec43a4] 2018-08-23 Changed `Defines` builder to `require_once` instead of require [@hiqsol] 76 | - [7e6e4fa] 2018-08-13 Redone `defines` building, require all instead of assembling [@hiqsol] 77 | - [6d2c277] 2018-08-03 Added `DotEnv` class, no defines and dotenv needed for dotenv [@hiqsol] 78 | - Reworked configuration files building 79 | - [ed34c6e] 2018-08-23 csfixed [@hiqsol] 80 | - [faf6cec] 2018-08-22 Added more type hinting [@hiqsol] 81 | - [8ba86d9] 2018-08-08 Collecting all `packages` instead of yii2-extensions only [@hiqsol] 82 | - [462c616] 2018-08-08 Removed check for `yii2-extension`, collecting aliases from all packages [@hiqsol] 83 | - [7534700] 2018-08-04 Added `1.0.x-dev` branch-alias [@hiqsol] 84 | - [22965f1] 2018-08-03 csfixed [@hiqsol] 85 | - [1d78abf] 2018-08-03 Added merging ENV vars in normal configs [@hiqsol] 86 | - [e88f547] 2018-08-01 Fixed `System::load()` to allow file not exist [@hiqsol] 87 | - [19b80be] 2018-07-31 Fixed `Builder::rebuild()` by fixing aliases loading [@hiqsol] 88 | - [3c7654c] 2018-07-31 Allowed return null in reference functions [@hiqsol] 89 | - [39fc269] 2018-07-31 Changed recommended config path to `config` (was src/config) [@hiqsol] 90 | - [03d7359] 2018-07-31 csfixed [@hiqsol] 91 | - [f73714d] 2018-07-31 Added lot of phpdocs [@hiqsol] 92 | - [3378133] 2018-07-31 Extracted package logic to `Package` class: prefer data from `composer.json` [@hiqsol] 93 | - [4e4f6b9] 2018-07-30 Added `suggest` section to composer.json [@hiqsol] 94 | - [8273a37] 2018-07-30 Moved aliases and extensions building to `Builder` [@hiqsol] 95 | - [5f84f43] 2018-07-30 Removed `__addition` config and `Builder::files` , passing files explicitly [@hiqsol] 96 | - [1d52609] 2018-07-30 Added `System` config `setValue()`, `mergeValues()` and `build()` [@hiqsol] 97 | - [5ccb875] 2018-07-30 Removed expired `Yii.php` loading stuff [@hiqsol] 98 | - [eba7d87] 2018-07-30 Removed `io` from `Builder` [@hiqsol] 99 | - [b8e8baf] 2018-07-28 Extracted `Config::renderVars()` method [@hiqsol] 100 | - [117b250] 2018-07-28 Removed `isSpecialConfig` (cleaning up) [@hiqsol] 101 | - [540be97] 2018-07-25 Fixed `substitutePath()` to substitute also exact path again [@hiqsol] 102 | - [1df0194] 2018-07-25 Merged rework [@hiqsol] 103 | - [349da2d] 2018-07-25 HUGE refactoring out config classes [@hiqsol] 104 | - [b08f320] 2018-07-25 Added tests for readers factory [@hiqsol] 105 | - [c2d1320] 2018-07-25 Refactored readers to have builder [@hiqsol] 106 | - [f4fd70b] 2018-07-25 Fixed `Helper::mergeConfig()` for empty arguments list [@hiqsol] 107 | - [8a9d349] 2018-07-25 Moved `ReaderFactory` to readers dir [@hiqsol] 108 | - [c02b3cd] 2018-07-25 csfixed [@hiqsol] 109 | - [5596670] 2018-07-20 Fixed `Builder::substitutePath()` to substitute also exact path [@hiqsol] 110 | - [77aa87a] 2018-07-10 Fixed collecting files list: adding only unique [@hiqsol] 111 | - [c3e0699] 2018-07-10 renamed application to `app` [@hiqsol] 112 | - [05af3cc] 2018-07-08 trying yii 3.0 version [@hiqsol] 113 | - [8304c24] 2018-07-08 removed unused `$rawParams` [@hiqsol] 114 | - [14a42b0] 2018-01-29 Merge pull request #5 from marclaporte/patch-1 [@hiqsol] 115 | - [af29b9b] 2018-01-27 Fix a typo [@marclaporte] 116 | - [b1a84e7] 2018-01-27 csfixed [@hiqsol] 117 | - [6796608] 2017-11-30 still fixing to work in Windows [@hiqsol] 118 | - [6621a38] 2017-11-30 Merge pull request #4 from loveorigami/patch-1 [@hiqsol] 119 | - [2e358df] 2017-11-30 normalizeDir for windows path [@loveorigami] 120 | - [167ae38] 2017-11-30 quickfixed to `normalizePath` to force unix directory separator for substitutions to work in Windows [@hiqsol] 121 | - [4c7e79d] 2017-11-19 added `normalizePath` to convert Windows backslashes to normal slashes [@hiqsol] 122 | - [fdc740a] 2017-10-17 csfixed [@hiqsol] 123 | - [2b9795d] 2017-10-17 fixed expects array error [@hiqsol] 124 | - [05fff11] 2017-10-17 added pushing env vars into params with `pushEnvVars` [@hiqsol] 125 | - [35823f1] 2017-09-27 disabled require Yii.php because it sets `Yii_` constants wrong [@hiqsol] 126 | - [32105a5] 2017-09-27 added require Yii in `Plugin::initAutoload` [@hiqsol] 127 | - [67bf230] 2017-09-27 csfixed [@hiqsol] 128 | - [bea1b98] 2017-09-27 switched to phpunit 6 [@hiqsol] 129 | - [078c488] 2017-09-27 added links to app-organization article [@hiqsol] 130 | 131 | ## [0.2.5] - 2017-05-19 132 | 133 | - Added showing package dependencies hierarchy tree with `composer du -v` 134 | - [a08ff85] 2017-05-19 csfixed [@hiqsol] 135 | - [f6b00f4] 2017-05-19 docs [@hiqsol] 136 | - [37dcf77] 2017-05-19 improved tree colors [@hiqsol] 137 | - [3ddd313] 2017-05-19 added showing packages hierarchy tree with `showDepsTree()` [@hiqsol] 138 | - [aaa59c6] 2017-05-19 docs [@hiqsol] 139 | 140 | ## [0.2.4] - 2017-05-18 141 | 142 | - Added proper resolving of config dependencies with `Resolver` class 143 | - [4889e11] 2017-05-18 removed phpunit 6 compatibility hack [@hiqsol] 144 | - [b38c0f5] 2017-05-11 csfixed [@hiqsol] 145 | - [bea8462] 2017-05-11 renamed `hidev.yml` <- .hidev/config.yml [@hiqsol] 146 | - [a0f372d] 2017-05-11 added proper resolving of config dependencies with `Resolver` class [@hiqsol] 147 | - Fixed exportVar closures in Windows 148 | - [b411092] 2017-04-28 Merge pull request #1 from edgardmessias/patch-1 [@SilverFire] 149 | - [42cf9ad] 2017-04-28 Fixed exportVar closures in Windows Environment [@edgardmessias] 150 | 151 | ## [0.2.3] - 2017-04-18 152 | 153 | - Added vendor dir arg to `Builder::path` to get config path at given vendor dir 154 | - [ed7f586] 2017-04-18 csfixed [@hiqsol] 155 | - [06c9079] 2017-04-18 added vendor dir optional argument to `Builder::path` [@hiqsol] 156 | 157 | ## [0.2.2] - 2017-04-12 158 | 159 | - Improved README 160 | - [2920c4e] 2017-04-12 added Known issues to readme [@hiqsol] 161 | - [4a317e4] 2017-04-12 greatly improved docs [@hiqsol] 162 | - Added support for `.env`, JSON and YAML 163 | - [43c0d3c] 2017-04-12 refactored out readers and ReaderFactory [@hiqsol] 164 | - [8ec1461] 2017-04-12 refactored exceptions [@hiqsol] 165 | - [e89b1ab] 2017-04-12 added saving loaded constants to `defines` [@hiqsol] 166 | - [94d957b] 2017-04-12 added saving loaded env vars [@hiqsol] 167 | - [a379609] 2017-04-12 added Collection stub [@hiqsol] 168 | - [dc0397a] 2017-04-11 changed `Plugin::addFiles`: renamed from processFiles and reversed order of `defines` [@hiqsol] 169 | - [66521da] 2017-04-05 changed dotenv loading to common used behavior: shell environment will override those set in the `.env` [@hiqsol] 170 | - [a490575] 2017-04-04 added support for JSON and YAML [@hiqsol] 171 | - [d11c2bb] 2017-04-04 added support for `.env` [@hiqsol] 172 | 173 | ## [0.2.1] - 2017-03-23 174 | 175 | - Fixed wrong call of `Composer\Config::get()` 176 | - [57e403a] 2017-03-23 csfixed [@SilverFire] 177 | - [33192bb] 2017-03-23 Added PHPUnit 6 compatibility [@SilverFire] 178 | - [d32060d] 2017-03-23 Updated travis config [@SilverFire] 179 | - [e1bea13] 2017-03-23 Fixed wrong call of composer\config::get() [@SilverFire] 180 | 181 | ## [0.2.0] - 2017-03-15 182 | 183 | - Added initializaion of composer autoloading for project classes become usable in configs 184 | - [e1d9513] 2017-03-15 added initAutoload [@hiqsol] 185 | - Added work with `$config_name` paths for use of already built config 186 | - [4555b54] 2017-03-09 csfixed [@hiqsol] 187 | - [9bba22d] 2017-03-09 added `$config` paths to include built configs [@hiqsol] 188 | - [5f3d05c] 2017-03-08 minor: grammarnazi pathes -> paths [@hiqsol] 189 | - [6d3fb2b] 2017-02-02 csfixed [@hiqsol] 190 | - [a8f42dd] 2017-02-02 return defines back to default list of files [@hiqsol] 191 | - Renamed pathes -> paths everywhere 192 | - [82a0652] 2017-02-02 renamed paths <- pathes [@hiqsol] 193 | - [c13991e] 2017-02-02 added exporting defines [@hiqsol] 194 | - [864f8b1] 2017-01-12 renamed `Builder::substitutePaths` <- substitutePathes [@hiqsol] 195 | - [2d68985] 2016-12-31 doc [@hiqsol] 196 | - Added collecting dev aliases for root package 197 | - [49f229b] 2016-12-26 + collect dev aliases for root package [@hiqsol] 198 | 199 | ## [0.1.0] - 2016-12-26 200 | 201 | - Added proper rebuild 202 | - [623d741] 2016-12-26 add FailedWriteException [@hiqsol] 203 | - [c71fd6f] 2016-12-26 fixed fileGet when file does not exist [@hiqsol] 204 | - [02019cd] 2016-12-26 csfixed work with skippable [@hiqsol] 205 | - [9f4362e] 2016-12-26 + proper propagating skippable sign [@hiqsol] 206 | - [778096f] 2016-12-26 + putFile: checks if content changed before writing [@hiqsol] 207 | - [42ffadd] 2016-12-26 fixed namespace in tests [@hiqsol] 208 | - [4554fdd] 2016-12-26 csfixed [@hiqsol] 209 | - [333717a] 2016-12-26 + use dev self for .hidev/vendor [@hiqsol] 210 | - [e61e88b] 2016-12-26 + copying `__rebuild` script [@hiqsol] 211 | - Changed output dir to `composer-config-plugin-output` 212 | - [2a4a539] 2016-12-26 CHANGED output dir to `composer-config-plugin-output` [@hiqsol] 213 | - [ec65010] 2016-12-26 changed: `path()` and substituting pathes moved into Builder [@hiqsol] 214 | - [436f10d] 2016-12-25 added work with `addition` [@hiqsol] 215 | - Changed: splitted out `Builder` 216 | - [b85299b] 2016-12-25 basically finished splitting out Builder [@hiqsol] 217 | - [c53bb32] 2016-12-24 + `Helper::className()` [@hiqsol] 218 | - Changed namespace to `hiqdev\composer\config` 219 | - [ab86c3c] 2016-12-24 started BIG redoing: changed namespace, added Builder, output to other dir [@hiqsol] 220 | - [e447659] 2016-12-23 doc [@hiqsol] 221 | - [e1565a6] 2016-10-04 removed use of `::class` to be older php compatible [@hiqsol] 222 | 223 | ## [0.0.9] - 2016-09-22 224 | 225 | - Fixed infinite loop in case of circular dependencies in composer 226 | - [434673d] 2016-09-22 fixed: prevented infinite loop in case of circular dependencies [@hiqsol] 227 | - [5b6b30e] 2016-09-14 improved readme [@hiqsol] 228 | 229 | ## [0.0.8] - 2016-08-27 230 | 231 | - Added showing ordered list of packages when verbose option 232 | - [5de8257] 2016-08-27 added showing list of packages if verbose [@hiqsol] 233 | 234 | ## [0.0.7] - 2016-08-26 235 | 236 | - Fixed packages processing order again, used original `composer.json` 237 | - [a9c0ba1] 2016-08-26 fixed scrutinizer issues [@hiqsol] 238 | - [cc15516] 2016-08-25 redone iterateDependencies and used getPrettyName() instead of getName() [@hiqsol] 239 | 240 | ## [0.0.6] - 2016-08-23 241 | 242 | - Fixed packages processing order 243 | - [c4bf7f9] 2016-08-23 more ideas [@hiqsol] 244 | - [8340080] 2016-08-23 + require-dev phpunit 5.5 [@hiqsol] 245 | - [e08e6c7] 2016-08-23 fixed tests for composer 5.5 [@hiqsol] 246 | - [94284df] 2016-08-23 csfixed [@hiqsol] 247 | - [2faafaa] 2016-08-23 redone to chkipper for bumping [@hiqsol] 248 | - [0e4f55b] 2016-08-23 added fixed packages processing order [@hiqsol] 249 | 250 | ## [0.0.5] - 2016-06-22 251 | 252 | - Added multiple defines 253 | - [e58cc7a] 2016-06-22 allowed travis build failure for PHP 5.5 [@hiqsol] 254 | - [5b84dc8] 2016-06-22 added ability to have multiple defines [@hiqsol] 255 | - [827d606] 2016-05-22 csfixed [@hiqsol] 256 | 257 | ## [0.0.4] - 2016-05-21 258 | 259 | - Added multiple configs and params 260 | - [e9c4899] 2016-05-21 forced arrays [@hiqsol] 261 | - [d1fdc77] 2016-05-20 + added multiple configs and params [@hiqsol] 262 | 263 | ## [0.0.3] - 2016-05-20 264 | 265 | - Changed aliases assembling 266 | - [1076668] 2016-05-20 csfixed [@hiqsol] 267 | - [174c848] 2016-05-19 simplified aliases assembling [@hiqsol] 268 | - [5f232e4] 2016-05-19 improved Idea [@hiqsol] 269 | - [a976f3e] 2016-05-19 added Idea readme section [@hiqsol] 270 | 271 | ## [0.0.2] - 2016-05-19 272 | 273 | - Removed replace composer-extension-plugin 274 | - [0a3d1a6] 2016-05-19 removed replace composer-extension-plugin [@hiqsol] 275 | 276 | ## [0.0.1] - 2016-05-18 277 | 278 | - Added basics 279 | - [15e92b4] 2016-05-18 fixed getting baseDir [@hiqsol] 280 | - [ec3bda1] 2016-05-18 rehideved [@hiqsol] 281 | - [470dc87] 2016-05-18 looks working [@hiqsol] 282 | - [65d1a3e] 2016-05-18 redoing [@hiqsol] 283 | - [927a73f] 2016-05-18 + replace composer-extension-plugin [@hiqsol] 284 | - [6270475] 2016-05-18 redoing [@hiqsol] 285 | - [79b5c49] 2016-05-18 inited [@hiqsol] 286 | 287 | ## [Development started] - 2016-05-18 288 | 289 | [@SilverFire]: https://github.com/SilverFire 290 | [d.naumenko.a@gmail.com]: https://github.com/SilverFire 291 | [@tafid]: https://github.com/tafid 292 | [andreyklochok@gmail.com]: https://github.com/tafid 293 | [@BladeRoot]: https://github.com/BladeRoot 294 | [bladeroot@gmail.com]: https://github.com/BladeRoot 295 | [@hiqsol]: https://github.com/hiqsol 296 | [sol@hiqdev.com]: https://github.com/hiqsol 297 | [@edgardmessias]: https://github.com/edgardmessias 298 | [edgardmessias@gmail.com]: https://github.com/edgardmessias 299 | [@samdark]: https://github.com/samdark 300 | [sam@rmcreative.ru]: https://github.com/samdark 301 | [@loveorigami]: https://github.com/loveorigami 302 | [loveorigami@mail.ru]: https://github.com/loveorigami 303 | [@marclaporte]: https://github.com/marclaporte 304 | [marc@laporte.name]: https://github.com/marclaporte 305 | [@jseliga]: https://github.com/jseliga 306 | [seliga.honza@gmail.com]: https://github.com/jseliga 307 | [@machour]: https://github.com/machour 308 | [machour@gmail.com]: https://github.com/machour 309 | [@jomonkj]: https://github.com/jomonkj 310 | [jomon.entero@gmail.com]: https://github.com/jomonkj 311 | [@noname007]: https://github.com/noname007 312 | [soul11201@gmail.com]: https://github.com/noname007 313 | [e58cc7a]: https://github.com/hiqdev/composer-config-plugin/commit/e58cc7a 314 | [5b84dc8]: https://github.com/hiqdev/composer-config-plugin/commit/5b84dc8 315 | [827d606]: https://github.com/hiqdev/composer-config-plugin/commit/827d606 316 | [e9c4899]: https://github.com/hiqdev/composer-config-plugin/commit/e9c4899 317 | [d1fdc77]: https://github.com/hiqdev/composer-config-plugin/commit/d1fdc77 318 | [1076668]: https://github.com/hiqdev/composer-config-plugin/commit/1076668 319 | [174c848]: https://github.com/hiqdev/composer-config-plugin/commit/174c848 320 | [5f232e4]: https://github.com/hiqdev/composer-config-plugin/commit/5f232e4 321 | [a976f3e]: https://github.com/hiqdev/composer-config-plugin/commit/a976f3e 322 | [0a3d1a6]: https://github.com/hiqdev/composer-config-plugin/commit/0a3d1a6 323 | [15e92b4]: https://github.com/hiqdev/composer-config-plugin/commit/15e92b4 324 | [ec3bda1]: https://github.com/hiqdev/composer-config-plugin/commit/ec3bda1 325 | [470dc87]: https://github.com/hiqdev/composer-config-plugin/commit/470dc87 326 | [65d1a3e]: https://github.com/hiqdev/composer-config-plugin/commit/65d1a3e 327 | [927a73f]: https://github.com/hiqdev/composer-config-plugin/commit/927a73f 328 | [6270475]: https://github.com/hiqdev/composer-config-plugin/commit/6270475 329 | [79b5c49]: https://github.com/hiqdev/composer-config-plugin/commit/79b5c49 330 | [0e4f55b]: https://github.com/hiqdev/composer-config-plugin/commit/0e4f55b 331 | [c4bf7f9]: https://github.com/hiqdev/composer-config-plugin/commit/c4bf7f9 332 | [8340080]: https://github.com/hiqdev/composer-config-plugin/commit/8340080 333 | [e08e6c7]: https://github.com/hiqdev/composer-config-plugin/commit/e08e6c7 334 | [94284df]: https://github.com/hiqdev/composer-config-plugin/commit/94284df 335 | [2faafaa]: https://github.com/hiqdev/composer-config-plugin/commit/2faafaa 336 | [cc15516]: https://github.com/hiqdev/composer-config-plugin/commit/cc15516 337 | [a9c0ba1]: https://github.com/hiqdev/composer-config-plugin/commit/a9c0ba1 338 | [5de8257]: https://github.com/hiqdev/composer-config-plugin/commit/5de8257 339 | [434673d]: https://github.com/hiqdev/composer-config-plugin/commit/434673d 340 | [5b6b30e]: https://github.com/hiqdev/composer-config-plugin/commit/5b6b30e 341 | [c71fd6f]: https://github.com/hiqdev/composer-config-plugin/commit/c71fd6f 342 | [02019cd]: https://github.com/hiqdev/composer-config-plugin/commit/02019cd 343 | [9f4362e]: https://github.com/hiqdev/composer-config-plugin/commit/9f4362e 344 | [778096f]: https://github.com/hiqdev/composer-config-plugin/commit/778096f 345 | [42ffadd]: https://github.com/hiqdev/composer-config-plugin/commit/42ffadd 346 | [4554fdd]: https://github.com/hiqdev/composer-config-plugin/commit/4554fdd 347 | [333717a]: https://github.com/hiqdev/composer-config-plugin/commit/333717a 348 | [e61e88b]: https://github.com/hiqdev/composer-config-plugin/commit/e61e88b 349 | [2a4a539]: https://github.com/hiqdev/composer-config-plugin/commit/2a4a539 350 | [ec65010]: https://github.com/hiqdev/composer-config-plugin/commit/ec65010 351 | [436f10d]: https://github.com/hiqdev/composer-config-plugin/commit/436f10d 352 | [b85299b]: https://github.com/hiqdev/composer-config-plugin/commit/b85299b 353 | [c53bb32]: https://github.com/hiqdev/composer-config-plugin/commit/c53bb32 354 | [ab86c3c]: https://github.com/hiqdev/composer-config-plugin/commit/ab86c3c 355 | [e447659]: https://github.com/hiqdev/composer-config-plugin/commit/e447659 356 | [e1565a6]: https://github.com/hiqdev/composer-config-plugin/commit/e1565a6 357 | [Under development]: https://github.com/hiqdev/composer-config-plugin/compare/0.3.0...HEAD 358 | [0.0.9]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.8...0.0.9 359 | [0.0.8]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.7...0.0.8 360 | [0.0.7]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.6...0.0.7 361 | [0.0.6]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.5...0.0.6 362 | [0.0.5]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.4...0.0.5 363 | [0.0.4]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.3...0.0.4 364 | [0.0.3]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.2...0.0.3 365 | [0.0.2]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.1...0.0.2 366 | [0.0.1]: https://github.com/hiqdev/composer-config-plugin/releases/tag/0.0.1 367 | [623d741]: https://github.com/hiqdev/composer-config-plugin/commit/623d741 368 | [0.1.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.0.9...0.1.0 369 | [e1d9513]: https://github.com/hiqdev/composer-config-plugin/commit/e1d9513 370 | [4555b54]: https://github.com/hiqdev/composer-config-plugin/commit/4555b54 371 | [9bba22d]: https://github.com/hiqdev/composer-config-plugin/commit/9bba22d 372 | [5f3d05c]: https://github.com/hiqdev/composer-config-plugin/commit/5f3d05c 373 | [6d3fb2b]: https://github.com/hiqdev/composer-config-plugin/commit/6d3fb2b 374 | [a8f42dd]: https://github.com/hiqdev/composer-config-plugin/commit/a8f42dd 375 | [82a0652]: https://github.com/hiqdev/composer-config-plugin/commit/82a0652 376 | [c13991e]: https://github.com/hiqdev/composer-config-plugin/commit/c13991e 377 | [864f8b1]: https://github.com/hiqdev/composer-config-plugin/commit/864f8b1 378 | [2d68985]: https://github.com/hiqdev/composer-config-plugin/commit/2d68985 379 | [49f229b]: https://github.com/hiqdev/composer-config-plugin/commit/49f229b 380 | [0.2.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.1.0...0.2.0 381 | [e1bea13]: https://github.com/hiqdev/composer-config-plugin/commit/e1bea13 382 | [0.2.1]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.0...0.2.1 383 | [57e403a]: https://github.com/hiqdev/composer-config-plugin/commit/57e403a 384 | [33192bb]: https://github.com/hiqdev/composer-config-plugin/commit/33192bb 385 | [d32060d]: https://github.com/hiqdev/composer-config-plugin/commit/d32060d 386 | [2920c4e]: https://github.com/hiqdev/composer-config-plugin/commit/2920c4e 387 | [43c0d3c]: https://github.com/hiqdev/composer-config-plugin/commit/43c0d3c 388 | [8ec1461]: https://github.com/hiqdev/composer-config-plugin/commit/8ec1461 389 | [e89b1ab]: https://github.com/hiqdev/composer-config-plugin/commit/e89b1ab 390 | [94d957b]: https://github.com/hiqdev/composer-config-plugin/commit/94d957b 391 | [a379609]: https://github.com/hiqdev/composer-config-plugin/commit/a379609 392 | [4a317e4]: https://github.com/hiqdev/composer-config-plugin/commit/4a317e4 393 | [dc0397a]: https://github.com/hiqdev/composer-config-plugin/commit/dc0397a 394 | [66521da]: https://github.com/hiqdev/composer-config-plugin/commit/66521da 395 | [a490575]: https://github.com/hiqdev/composer-config-plugin/commit/a490575 396 | [d11c2bb]: https://github.com/hiqdev/composer-config-plugin/commit/d11c2bb 397 | [0.2.2]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.1...0.2.2 398 | [ed7f586]: https://github.com/hiqdev/composer-config-plugin/commit/ed7f586 399 | [06c9079]: https://github.com/hiqdev/composer-config-plugin/commit/06c9079 400 | [0.2.3]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.2...0.2.3 401 | [4889e11]: https://github.com/hiqdev/composer-config-plugin/commit/4889e11 402 | [b38c0f5]: https://github.com/hiqdev/composer-config-plugin/commit/b38c0f5 403 | [bea8462]: https://github.com/hiqdev/composer-config-plugin/commit/bea8462 404 | [a0f372d]: https://github.com/hiqdev/composer-config-plugin/commit/a0f372d 405 | [b411092]: https://github.com/hiqdev/composer-config-plugin/commit/b411092 406 | [42cf9ad]: https://github.com/hiqdev/composer-config-plugin/commit/42cf9ad 407 | [0.2.4]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.3...0.2.4 408 | [a08ff85]: https://github.com/hiqdev/composer-config-plugin/commit/a08ff85 409 | [f6b00f4]: https://github.com/hiqdev/composer-config-plugin/commit/f6b00f4 410 | [37dcf77]: https://github.com/hiqdev/composer-config-plugin/commit/37dcf77 411 | [3ddd313]: https://github.com/hiqdev/composer-config-plugin/commit/3ddd313 412 | [aaa59c6]: https://github.com/hiqdev/composer-config-plugin/commit/aaa59c6 413 | [0.2.5]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.4...0.2.5 414 | [67bf230]: https://github.com/hiqdev/composer-config-plugin/commit/67bf230 415 | [bea1b98]: https://github.com/hiqdev/composer-config-plugin/commit/bea1b98 416 | [078c488]: https://github.com/hiqdev/composer-config-plugin/commit/078c488 417 | [34cfa36]: https://github.com/hiqdev/composer-config-plugin/commit/34cfa36 418 | [3ec43a4]: https://github.com/hiqdev/composer-config-plugin/commit/3ec43a4 419 | [ed34c6e]: https://github.com/hiqdev/composer-config-plugin/commit/ed34c6e 420 | [faf6cec]: https://github.com/hiqdev/composer-config-plugin/commit/faf6cec 421 | [7e6e4fa]: https://github.com/hiqdev/composer-config-plugin/commit/7e6e4fa 422 | [8ba86d9]: https://github.com/hiqdev/composer-config-plugin/commit/8ba86d9 423 | [462c616]: https://github.com/hiqdev/composer-config-plugin/commit/462c616 424 | [7534700]: https://github.com/hiqdev/composer-config-plugin/commit/7534700 425 | [6d2c277]: https://github.com/hiqdev/composer-config-plugin/commit/6d2c277 426 | [22965f1]: https://github.com/hiqdev/composer-config-plugin/commit/22965f1 427 | [1d78abf]: https://github.com/hiqdev/composer-config-plugin/commit/1d78abf 428 | [e88f547]: https://github.com/hiqdev/composer-config-plugin/commit/e88f547 429 | [19b80be]: https://github.com/hiqdev/composer-config-plugin/commit/19b80be 430 | [3c7654c]: https://github.com/hiqdev/composer-config-plugin/commit/3c7654c 431 | [39fc269]: https://github.com/hiqdev/composer-config-plugin/commit/39fc269 432 | [03d7359]: https://github.com/hiqdev/composer-config-plugin/commit/03d7359 433 | [f73714d]: https://github.com/hiqdev/composer-config-plugin/commit/f73714d 434 | [3378133]: https://github.com/hiqdev/composer-config-plugin/commit/3378133 435 | [4e4f6b9]: https://github.com/hiqdev/composer-config-plugin/commit/4e4f6b9 436 | [8273a37]: https://github.com/hiqdev/composer-config-plugin/commit/8273a37 437 | [5f84f43]: https://github.com/hiqdev/composer-config-plugin/commit/5f84f43 438 | [1d52609]: https://github.com/hiqdev/composer-config-plugin/commit/1d52609 439 | [5ccb875]: https://github.com/hiqdev/composer-config-plugin/commit/5ccb875 440 | [eba7d87]: https://github.com/hiqdev/composer-config-plugin/commit/eba7d87 441 | [b8e8baf]: https://github.com/hiqdev/composer-config-plugin/commit/b8e8baf 442 | [117b250]: https://github.com/hiqdev/composer-config-plugin/commit/117b250 443 | [540be97]: https://github.com/hiqdev/composer-config-plugin/commit/540be97 444 | [1df0194]: https://github.com/hiqdev/composer-config-plugin/commit/1df0194 445 | [349da2d]: https://github.com/hiqdev/composer-config-plugin/commit/349da2d 446 | [b08f320]: https://github.com/hiqdev/composer-config-plugin/commit/b08f320 447 | [c2d1320]: https://github.com/hiqdev/composer-config-plugin/commit/c2d1320 448 | [f4fd70b]: https://github.com/hiqdev/composer-config-plugin/commit/f4fd70b 449 | [8a9d349]: https://github.com/hiqdev/composer-config-plugin/commit/8a9d349 450 | [c02b3cd]: https://github.com/hiqdev/composer-config-plugin/commit/c02b3cd 451 | [5596670]: https://github.com/hiqdev/composer-config-plugin/commit/5596670 452 | [77aa87a]: https://github.com/hiqdev/composer-config-plugin/commit/77aa87a 453 | [c3e0699]: https://github.com/hiqdev/composer-config-plugin/commit/c3e0699 454 | [05af3cc]: https://github.com/hiqdev/composer-config-plugin/commit/05af3cc 455 | [8304c24]: https://github.com/hiqdev/composer-config-plugin/commit/8304c24 456 | [14a42b0]: https://github.com/hiqdev/composer-config-plugin/commit/14a42b0 457 | [af29b9b]: https://github.com/hiqdev/composer-config-plugin/commit/af29b9b 458 | [b1a84e7]: https://github.com/hiqdev/composer-config-plugin/commit/b1a84e7 459 | [6796608]: https://github.com/hiqdev/composer-config-plugin/commit/6796608 460 | [6621a38]: https://github.com/hiqdev/composer-config-plugin/commit/6621a38 461 | [2e358df]: https://github.com/hiqdev/composer-config-plugin/commit/2e358df 462 | [167ae38]: https://github.com/hiqdev/composer-config-plugin/commit/167ae38 463 | [4c7e79d]: https://github.com/hiqdev/composer-config-plugin/commit/4c7e79d 464 | [fdc740a]: https://github.com/hiqdev/composer-config-plugin/commit/fdc740a 465 | [2b9795d]: https://github.com/hiqdev/composer-config-plugin/commit/2b9795d 466 | [05fff11]: https://github.com/hiqdev/composer-config-plugin/commit/05fff11 467 | [35823f1]: https://github.com/hiqdev/composer-config-plugin/commit/35823f1 468 | [32105a5]: https://github.com/hiqdev/composer-config-plugin/commit/32105a5 469 | [efcb091]: https://github.com/hiqdev/composer-config-plugin/commit/efcb091 470 | [597227a]: https://github.com/hiqdev/composer-config-plugin/commit/597227a 471 | [9f61a78]: https://github.com/hiqdev/composer-config-plugin/commit/9f61a78 472 | [83bc091]: https://github.com/hiqdev/composer-config-plugin/commit/83bc091 473 | [0c8c821]: https://github.com/hiqdev/composer-config-plugin/commit/0c8c821 474 | [959c971]: https://github.com/hiqdev/composer-config-plugin/commit/959c971 475 | [faab5ed]: https://github.com/hiqdev/composer-config-plugin/commit/faab5ed 476 | [49f65f7]: https://github.com/hiqdev/composer-config-plugin/commit/49f65f7 477 | [bf49430]: https://github.com/hiqdev/composer-config-plugin/commit/bf49430 478 | [e3e4f78]: https://github.com/hiqdev/composer-config-plugin/commit/e3e4f78 479 | [f4ef5d2]: https://github.com/hiqdev/composer-config-plugin/commit/f4ef5d2 480 | [1d807d0]: https://github.com/hiqdev/composer-config-plugin/commit/1d807d0 481 | [2543887]: https://github.com/hiqdev/composer-config-plugin/commit/2543887 482 | [5cbfdac]: https://github.com/hiqdev/composer-config-plugin/commit/5cbfdac 483 | [99c5696]: https://github.com/hiqdev/composer-config-plugin/commit/99c5696 484 | [0.3.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.2.5...0.3.0 485 | [c18a233]: https://github.com/hiqdev/composer-config-plugin/commit/c18a233 486 | [c84e82e]: https://github.com/hiqdev/composer-config-plugin/commit/c84e82e 487 | [7d445fa]: https://github.com/hiqdev/composer-config-plugin/commit/7d445fa 488 | [4a6b89c]: https://github.com/hiqdev/composer-config-plugin/commit/4a6b89c 489 | [217fcbe]: https://github.com/hiqdev/composer-config-plugin/commit/217fcbe 490 | [4d68359]: https://github.com/hiqdev/composer-config-plugin/commit/4d68359 491 | [1db8b15]: https://github.com/hiqdev/composer-config-plugin/commit/1db8b15 492 | [341d3ad]: https://github.com/hiqdev/composer-config-plugin/commit/341d3ad 493 | [fc0df4c]: https://github.com/hiqdev/composer-config-plugin/commit/fc0df4c 494 | [892eb6b]: https://github.com/hiqdev/composer-config-plugin/commit/892eb6b 495 | [2a84e31]: https://github.com/hiqdev/composer-config-plugin/commit/2a84e31 496 | [0ebcdea]: https://github.com/hiqdev/composer-config-plugin/commit/0ebcdea 497 | [3fd5c38]: https://github.com/hiqdev/composer-config-plugin/commit/3fd5c38 498 | [d038a30]: https://github.com/hiqdev/composer-config-plugin/commit/d038a30 499 | [7fa31d1]: https://github.com/hiqdev/composer-config-plugin/commit/7fa31d1 500 | [d238de7]: https://github.com/hiqdev/composer-config-plugin/commit/d238de7 501 | [e2e8c7b]: https://github.com/hiqdev/composer-config-plugin/commit/e2e8c7b 502 | [3babef6]: https://github.com/hiqdev/composer-config-plugin/commit/3babef6 503 | [266138a]: https://github.com/hiqdev/composer-config-plugin/commit/266138a 504 | [3e18cbe]: https://github.com/hiqdev/composer-config-plugin/commit/3e18cbe 505 | [fb5a5d8]: https://github.com/hiqdev/composer-config-plugin/commit/fb5a5d8 506 | [b5fe4d5]: https://github.com/hiqdev/composer-config-plugin/commit/b5fe4d5 507 | [ef8a42c]: https://github.com/hiqdev/composer-config-plugin/commit/ef8a42c 508 | [a0401ea]: https://github.com/hiqdev/composer-config-plugin/commit/a0401ea 509 | [3d9bb59]: https://github.com/hiqdev/composer-config-plugin/commit/3d9bb59 510 | [0d92a2d]: https://github.com/hiqdev/composer-config-plugin/commit/0d92a2d 511 | [7e7b36e]: https://github.com/hiqdev/composer-config-plugin/commit/7e7b36e 512 | [e06125e]: https://github.com/hiqdev/composer-config-plugin/commit/e06125e 513 | [6a4eb47]: https://github.com/hiqdev/composer-config-plugin/commit/6a4eb47 514 | [8a6a588]: https://github.com/hiqdev/composer-config-plugin/commit/8a6a588 515 | [f1b4ff1]: https://github.com/hiqdev/composer-config-plugin/commit/f1b4ff1 516 | [7317438]: https://github.com/hiqdev/composer-config-plugin/commit/7317438 517 | [b1c9639]: https://github.com/hiqdev/composer-config-plugin/commit/b1c9639 518 | [42f3c4e]: https://github.com/hiqdev/composer-config-plugin/commit/42f3c4e 519 | [910c127]: https://github.com/hiqdev/composer-config-plugin/commit/910c127 520 | [1d6dd28]: https://github.com/hiqdev/composer-config-plugin/commit/1d6dd28 521 | [77a8eac]: https://github.com/hiqdev/composer-config-plugin/commit/77a8eac 522 | [b36d5ad]: https://github.com/hiqdev/composer-config-plugin/commit/b36d5ad 523 | [594aaab]: https://github.com/hiqdev/composer-config-plugin/commit/594aaab 524 | [820a9e6]: https://github.com/hiqdev/composer-config-plugin/commit/820a9e6 525 | [4f8d841]: https://github.com/hiqdev/composer-config-plugin/commit/4f8d841 526 | [0.4.0]: https://github.com/hiqdev/composer-config-plugin/compare/0.3.0...0.4.0 527 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiqdev/composer-config-plugin/d092c526f864565fcab47411fb384b47aab39298/logo.png -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests/unit/ 6 | 7 | 8 | 9 | 10 | ./src/ 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Builder.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class Builder 22 | { 23 | /** 24 | * @var string path to output assembled configs 25 | */ 26 | protected $outputDir; 27 | 28 | /** 29 | * @var array collected variables 30 | */ 31 | protected $vars = []; 32 | 33 | /** 34 | * @var array configurations 35 | */ 36 | protected $configs = []; 37 | 38 | const OUTPUT_DIR_SUFFIX = '-output'; 39 | 40 | public function __construct($outputDir = null) 41 | { 42 | $this->setOutputDir($outputDir); 43 | } 44 | 45 | public function createAlternative($name): Builder 46 | { 47 | $dir = $this->outputDir . DIRECTORY_SEPARATOR . $name; 48 | $alt = new static($dir); 49 | foreach (['aliases', 'packages'] as $key) { 50 | $alt->configs[$key] = $this->getConfig($key)->clone($alt); 51 | } 52 | 53 | return $alt; 54 | } 55 | 56 | public function setOutputDir($outputDir) 57 | { 58 | $this->outputDir = $outputDir 59 | ? static::buildAbsPath($this->getBaseDir(), $outputDir) 60 | : static::findOutputDir(); 61 | } 62 | 63 | public function getBaseDir(): string 64 | { 65 | return dirname(__DIR__, 4); 66 | } 67 | 68 | public function getOutputDir(): string 69 | { 70 | return $this->outputDir; 71 | } 72 | 73 | public static function rebuild($outputDir = null) 74 | { 75 | $builder = new self($outputDir); 76 | $files = $builder->getConfig('__files')->load(); 77 | $builder->buildUserConfigs($files->getValues()); 78 | } 79 | 80 | public function rebuildUserConfigs() 81 | { 82 | $this->getConfig('__files')->load(); 83 | } 84 | 85 | /** 86 | * Returns default output dir. 87 | * @param string $baseDir path to project base dir 88 | * @return string 89 | */ 90 | public static function findOutputDir(string $baseDir = null): string 91 | { 92 | $baseDir = $baseDir ?: static::findBaseDir(); 93 | $path = $baseDir . DIRECTORY_SEPARATOR . 'composer.json'; 94 | $data = @json_decode(file_get_contents($path), true); 95 | $dir = $data['extra'][Package::EXTRA_OUTPUT_DIR_OPTION_NAME] ?? null; 96 | 97 | return $dir ? static::buildAbsPath($baseDir, $dir) : static::defaultOutputDir($baseDir); 98 | } 99 | 100 | public static function findBaseDir(): string 101 | { 102 | return dirname(__DIR__, 4); 103 | } 104 | 105 | /** 106 | * Returns default output dir. 107 | * @param string $vendor path to vendor dir 108 | * @return string 109 | */ 110 | public static function defaultOutputDir($baseDir = null): string 111 | { 112 | if ($baseDir) { 113 | $dir = $baseDir . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'hiqdev' . DIRECTORY_SEPARATOR . basename(dirname(__DIR__)); 114 | } else { 115 | $dir = \dirname(__DIR__); 116 | } 117 | 118 | return $dir . static::OUTPUT_DIR_SUFFIX; 119 | } 120 | 121 | /** 122 | * Returns full path to assembled config file. 123 | * @param string $filename name of config 124 | * @param string $baseDir path to base dir 125 | * @return string absolute path 126 | */ 127 | public static function path($filename, $baseDir = null) 128 | { 129 | return static::buildAbsPath(static::findOutputDir($baseDir), $filename . '.php'); 130 | } 131 | 132 | public static function buildAbsPath(string $dir, string $file): string 133 | { 134 | return strncmp($file, DIRECTORY_SEPARATOR, 1) === 0 ? $file : $dir . DIRECTORY_SEPARATOR . $file; 135 | } 136 | 137 | /** 138 | * Builds all (user and system) configs by given files list. 139 | * @param null|array $files files to process: config name => list of files 140 | */ 141 | public function buildAllConfigs(array $files) 142 | { 143 | $this->buildUserConfigs($files); 144 | $this->buildSystemConfigs($files); 145 | } 146 | 147 | /** 148 | * Builds configs by given files list. 149 | * @param null|array $files files to process: config name => list of files 150 | */ 151 | public function buildUserConfigs(array $files): array 152 | { 153 | $resolver = new Resolver($files); 154 | $files = $resolver->get(); 155 | foreach ($files as $name => $paths) { 156 | $this->getConfig($name)->load($paths)->build()->write(); 157 | } 158 | 159 | return $files; 160 | } 161 | 162 | public function buildSystemConfigs(array $files) 163 | { 164 | $this->getConfig('__files')->setValues($files); 165 | foreach (['__rebuild', '__files', 'aliases', 'packages'] as $name) { 166 | $this->getConfig($name)->build()->write(); 167 | } 168 | } 169 | 170 | public function getOutputPath($name) 171 | { 172 | return $this->outputDir . DIRECTORY_SEPARATOR . $name . '.php'; 173 | } 174 | 175 | protected function createConfig($name) 176 | { 177 | $config = ConfigFactory::create($this, $name); 178 | $this->configs[$name] = $config; 179 | 180 | return $config; 181 | } 182 | 183 | public function getConfig(string $name) 184 | { 185 | if (!isset($this->configs[$name])) { 186 | $this->configs[$name] = $this->createConfig($name); 187 | } 188 | 189 | return $this->configs[$name]; 190 | } 191 | 192 | public function getVar($name, $key) 193 | { 194 | $config = $this->configs[$name] ?? null; 195 | if (empty($config)) { 196 | return null; 197 | } 198 | 199 | return $config->getValues()[$key] ?? null; 200 | } 201 | 202 | public function getVars() 203 | { 204 | $vars = []; 205 | foreach ($this->configs as $name => $config) { 206 | $vars[$name] = $config->getValues(); 207 | } 208 | 209 | return $vars; 210 | } 211 | 212 | public function mergeAliases(array $aliases) 213 | { 214 | $this->getConfig('aliases')->mergeValues($aliases); 215 | } 216 | 217 | public function setPackage(string $name, array $data) 218 | { 219 | $this->getConfig('packages')->setValue($name, $data); 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/Package.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | class Package 24 | { 25 | const EXTRA_FILES_OPTION_NAME = 'config-plugin'; 26 | const EXTRA_DEV_FILES_OPTION_NAME = 'config-plugin-dev'; 27 | const EXTRA_OUTPUT_DIR_OPTION_NAME = 'config-plugin-output-dir'; 28 | const EXTRA_ALTERNATIVES_OPTION_NAME = 'config-plugin-alternatives'; 29 | 30 | private $options = ['output-dir', 'alternatives']; 31 | 32 | protected $package; 33 | 34 | /** 35 | * @var array composer.json raw data array 36 | */ 37 | protected $data; 38 | 39 | /** 40 | * @var string absolute path to the root base directory 41 | */ 42 | protected $baseDir; 43 | 44 | /** 45 | * @var string absolute path to vendor directory 46 | */ 47 | protected $vendorDir; 48 | 49 | /** 50 | * @var Filesystem utility 51 | */ 52 | protected $filesystem; 53 | 54 | private $composer; 55 | 56 | public function __construct(PackageInterface $package, Composer $composer) 57 | { 58 | $this->package = $package; 59 | $this->composer = $composer; 60 | } 61 | 62 | /** 63 | * Collects package aliases. 64 | * @return array collected aliases 65 | */ 66 | public function collectAliases(): array 67 | { 68 | $aliases = array_merge( 69 | $this->prepareAliases('psr-0'), 70 | $this->prepareAliases('psr-4') 71 | ); 72 | if ($this->isRoot()) { 73 | $aliases = array_merge($aliases, 74 | $this->prepareAliases('psr-0', true), 75 | $this->prepareAliases('psr-4', true) 76 | ); 77 | } 78 | 79 | return $aliases; 80 | } 81 | 82 | /** 83 | * Prepare aliases. 84 | * @param string 'psr-0' or 'psr-4' 85 | * @param bool $dev 86 | * @return array 87 | */ 88 | protected function prepareAliases($psr, $dev = false) 89 | { 90 | $autoload = $dev ? $this->getDevAutoload() : $this->getAutoload(); 91 | if (empty($autoload[$psr])) { 92 | return []; 93 | } 94 | 95 | $aliases = []; 96 | foreach ($autoload[$psr] as $name => $path) { 97 | if (is_array($path)) { 98 | // ignore psr-4 autoload specifications with multiple search paths 99 | // we can not convert them into aliases as they are ambiguous 100 | continue; 101 | } 102 | $name = str_replace('\\', '/', trim($name, '\\')); 103 | $path = $this->preparePath($path); 104 | if ('psr-0' === $psr) { 105 | $path .= '/' . $name; 106 | } 107 | $aliases["@$name"] = $path; 108 | } 109 | 110 | return $aliases; 111 | } 112 | 113 | /** 114 | * @return string package pretty name, like: vendor/name 115 | */ 116 | public function getPrettyName(): string 117 | { 118 | return $this->package->getPrettyName(); 119 | } 120 | 121 | /** 122 | * @return string package version, like: 3.0.16.0, 9999999-dev 123 | */ 124 | public function getVersion(): string 125 | { 126 | return $this->package->getVersion(); 127 | } 128 | 129 | /** 130 | * @return string package human friendly version, like: 5.x-dev d9aed42, 2.1.1, dev-master f6561bf 131 | */ 132 | public function getFullPrettyVersion(): string 133 | { 134 | return $this->package->getFullPrettyVersion(); 135 | } 136 | 137 | /** 138 | * @return string package CVS revision, like: 3a4654ac9655f32888efc82fb7edf0da517d8995 139 | */ 140 | public function getSourceReference(): ?string 141 | { 142 | return $this->package->getSourceReference(); 143 | } 144 | 145 | /** 146 | * @return string package dist revision, like: 3a4654ac9655f32888efc82fb7edf0da517d8995 147 | */ 148 | public function getDistReference(): ?string 149 | { 150 | return $this->package->getDistReference(); 151 | } 152 | 153 | /** 154 | * @return bool is package complete 155 | */ 156 | public function isComplete(): bool 157 | { 158 | return $this->package instanceof CompletePackageInterface; 159 | } 160 | 161 | /** 162 | * @return bool is this a root package 163 | */ 164 | public function isRoot(): bool 165 | { 166 | return $this->package instanceof RootPackageInterface; 167 | } 168 | 169 | /** 170 | * @return string package type, like: package, library 171 | */ 172 | public function getType(): string 173 | { 174 | return $this->getRawValue('type') ?? $this->package->getType(); 175 | } 176 | 177 | /** 178 | * @return array autoload configuration array 179 | */ 180 | public function getAutoload(): array 181 | { 182 | return $this->getRawValue('autoload') ?? $this->package->getAutoload(); 183 | } 184 | 185 | /** 186 | * @return array autoload-dev configuration array 187 | */ 188 | public function getDevAutoload(): array 189 | { 190 | return $this->getRawValue('autoload-dev') ?? $this->package->getDevAutoload(); 191 | } 192 | 193 | /** 194 | * @return array requre configuration array 195 | */ 196 | public function getRequires(): array 197 | { 198 | return $this->getRawValue('require') ?? $this->package->getRequires(); 199 | } 200 | 201 | /** 202 | * @return array requre-dev configuration array 203 | */ 204 | public function getDevRequires(): array 205 | { 206 | return $this->getRawValue('require-dev') ?? $this->package->getDevRequires(); 207 | } 208 | 209 | /** 210 | * @return array files array 211 | */ 212 | public function getFiles(): array 213 | { 214 | return $this->getExtraValue(self::EXTRA_FILES_OPTION_NAME, []); 215 | } 216 | 217 | /** 218 | * @return array dev-files array 219 | */ 220 | public function getDevFiles(): array 221 | { 222 | return $this->getExtraValue(self::EXTRA_DEV_FILES_OPTION_NAME, []); 223 | } 224 | 225 | /** 226 | * @return array output-dir option 227 | */ 228 | public function getOutputDir(): ?string 229 | { 230 | return $this->getExtraValue(self::EXTRA_OUTPUT_DIR_OPTION_NAME); 231 | } 232 | 233 | /** 234 | * @return mixed alternatives array or path to config 235 | */ 236 | public function getAlternatives() 237 | { 238 | return $this->getExtraValue(self::EXTRA_ALTERNATIVES_OPTION_NAME); 239 | } 240 | 241 | /** 242 | * @return array alternatives array 243 | */ 244 | public function getExtraValue($key, $default = null) 245 | { 246 | return $this->getExtra()[$key] ?? $default; 247 | } 248 | 249 | /** 250 | * @return array extra configuration array 251 | */ 252 | public function getExtra(): array 253 | { 254 | return $this->getRawValue('extra') ?? $this->package->getExtra(); 255 | } 256 | 257 | /** 258 | * @param string $name option name 259 | * @return mixed raw value from composer.json if available 260 | */ 261 | public function getRawValue(string $name) 262 | { 263 | if ($this->data === null) { 264 | $this->data = $this->readRawData(); 265 | } 266 | 267 | return $this->data[$name] ?? null; 268 | } 269 | 270 | /** 271 | * @return mixed all raw data from composer.json if available 272 | */ 273 | public function getRawData(): array 274 | { 275 | if ($this->data === null) { 276 | $this->data = $this->readRawData(); 277 | } 278 | 279 | return $this->data; 280 | } 281 | 282 | /** 283 | * @return array composer.json contents as array 284 | */ 285 | protected function readRawData(): array 286 | { 287 | $path = $this->preparePath('composer.json'); 288 | if (file_exists($path)) { 289 | return json_decode(file_get_contents($path), true); 290 | } 291 | 292 | return []; 293 | } 294 | 295 | /** 296 | * Builds path inside of a package. 297 | * @param string $file 298 | * @return string absolute paths will stay untouched 299 | */ 300 | public function preparePath(string $file): string 301 | { 302 | if (0 === strncmp($file, '$', 1)) { 303 | return $file; 304 | } 305 | 306 | $skippable = 0 === strncmp($file, '?', 1) ? '?' : ''; 307 | if ($skippable) { 308 | $file = substr($file, 1); 309 | } 310 | 311 | if (!$this->getFilesystem()->isAbsolutePath($file)) { 312 | $prefix = $this->isRoot() 313 | ? $this->getBaseDir() 314 | : $this->getVendorDir() . '/' . $this->getPrettyName(); 315 | $file = $prefix . '/' . $file; 316 | } 317 | 318 | return $skippable . $this->getFilesystem()->normalizePath($file); 319 | } 320 | 321 | /** 322 | * Get absolute path to package base dir. 323 | * @return string 324 | */ 325 | public function getBaseDir() 326 | { 327 | if (null === $this->baseDir) { 328 | $this->baseDir = dirname($this->getVendorDir()); 329 | } 330 | 331 | return $this->baseDir; 332 | } 333 | 334 | /** 335 | * Get absolute path to composer vendor dir. 336 | * @return string 337 | */ 338 | public function getVendorDir() 339 | { 340 | if (null === $this->vendorDir) { 341 | $dir = $this->composer->getConfig()->get('vendor-dir'); 342 | $this->vendorDir = $this->getFilesystem()->normalizePath($dir); 343 | } 344 | 345 | return $this->vendorDir; 346 | } 347 | 348 | /** 349 | * Getter for filesystem utility. 350 | * @return Filesystem 351 | */ 352 | public function getFilesystem() 353 | { 354 | if (null === $this->filesystem) { 355 | $this->filesystem = new Filesystem(); 356 | } 357 | 358 | return $this->filesystem; 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /src/Plugin.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | class Plugin implements PluginInterface, EventSubscriberInterface 29 | { 30 | /** 31 | * @var Package[] the array of active composer packages 32 | */ 33 | protected $packages; 34 | 35 | private $alternatives = []; 36 | 37 | private $outputDir; 38 | 39 | private $rootPackage; 40 | 41 | /** 42 | * @var array config name => list of files 43 | */ 44 | protected $files = [ 45 | 'dotenv' => [], 46 | 'defines' => [], 47 | 'params' => [], 48 | ]; 49 | 50 | protected $colors = ['red', 'green', 'yellow', 'cyan', 'magenta', 'blue']; 51 | 52 | /** 53 | * @var array package name => configs as listed in `composer.json` 54 | */ 55 | protected $originalFiles = []; 56 | 57 | /** 58 | * @var Builder 59 | */ 60 | protected $builder; 61 | 62 | /** 63 | * @var Composer instance 64 | */ 65 | protected $composer; 66 | 67 | /** 68 | * @var IOInterface 69 | */ 70 | public $io; 71 | 72 | /** 73 | * Initializes the plugin object with the passed $composer and $io. 74 | * @param Composer $composer 75 | * @param IOInterface $io 76 | */ 77 | public function activate(Composer $composer, IOInterface $io) 78 | { 79 | $this->composer = $composer; 80 | $this->io = $io; 81 | } 82 | 83 | /** 84 | * Returns list of events the plugin is subscribed to. 85 | * @return array list of events 86 | */ 87 | public static function getSubscribedEvents() 88 | { 89 | return [ 90 | ScriptEvents::POST_AUTOLOAD_DUMP => [ 91 | ['onPostAutoloadDump', 0], 92 | ], 93 | ]; 94 | } 95 | 96 | /** 97 | * This is the main function. 98 | * @param Event $event 99 | */ 100 | public function onPostAutoloadDump(Event $event) 101 | { 102 | $this->io->overwriteError('Assembling config files'); 103 | 104 | $this->builder = new Builder(); 105 | 106 | $this->initAutoload(); 107 | $this->scanPackages(); 108 | $this->reorderFiles(); 109 | $this->showDepsTree(); 110 | 111 | $this->builder->setOutputDir($this->outputDir); 112 | $this->builder->buildAllConfigs($this->files); 113 | 114 | $saveFiles = $this->files; 115 | $saveEnv = $_ENV; 116 | foreach ($this->alternatives as $name => $files) { 117 | $this->files = $saveFiles; 118 | $_ENV = $saveEnv; 119 | $builder = $this->builder->createAlternative($name); 120 | $this->addFiles($this->rootPackage, $files); 121 | $builder->buildAllConfigs($this->files); 122 | } 123 | } 124 | 125 | protected function initAutoload() 126 | { 127 | $dir = dirname(dirname(dirname(__DIR__))); 128 | require_once "$dir/autoload.php"; 129 | } 130 | 131 | protected function scanPackages() 132 | { 133 | foreach ($this->getPackages() as $package) { 134 | if ($package->isComplete()) { 135 | $this->processPackage($package); 136 | } 137 | } 138 | } 139 | 140 | protected function reorderFiles(): void 141 | { 142 | foreach (array_keys($this->files) as $name) { 143 | $this->files[$name] = $this->getAllFiles($name); 144 | } 145 | foreach ($this->files as $name => $files) { 146 | $this->files[$name] = $this->orderFiles($files); 147 | } 148 | } 149 | 150 | protected function getAllFiles(string $name, array $stack = []): array 151 | { 152 | if (empty($this->files[$name])) { 153 | return[]; 154 | } 155 | $res = []; 156 | foreach ($this->files[$name] as $file) { 157 | if (strncmp($file, '$', 1) === 0) { 158 | if (!in_array($name, $stack, true)) { 159 | $res = array_merge($res, $this->getAllFiles(substr($file, 1), array_merge($stack, [$name]))); 160 | } 161 | } else { 162 | $res[] = $file; 163 | } 164 | } 165 | 166 | return $res; 167 | } 168 | 169 | protected function orderFiles(array $files): array 170 | { 171 | if (empty($files)) { 172 | return []; 173 | } 174 | $keys = array_combine($files, $files); 175 | $res = []; 176 | foreach ($this->orderedFiles as $file) { 177 | if (isset($keys[$file])) { 178 | $res[$file] = $file; 179 | } 180 | } 181 | 182 | return array_values($res); 183 | } 184 | 185 | /** 186 | * Scans the given package and collects packages data. 187 | * @param Package $package 188 | */ 189 | protected function processPackage(Package $package) 190 | { 191 | $files = $package->getFiles(); 192 | $this->originalFiles[$package->getPrettyName()] = $files; 193 | 194 | if (!empty($files)) { 195 | $this->addFiles($package, $files); 196 | } 197 | if ($package->isRoot()) { 198 | $this->rootPackage = $package; 199 | $this->loadDotEnv($package); 200 | $devFiles = $package->getDevFiles(); 201 | if (!empty($devFiles)) { 202 | $this->addFiles($package, $devFiles); 203 | } 204 | $this->outputDir = $package->getOutputDir(); 205 | $alternatives = $package->getAlternatives(); 206 | if (is_string($alternatives)) { 207 | $this->alternatives = $this->readConfig($package, $alternatives); 208 | } elseif (is_array($alternatives)) { 209 | $this->alternatives = $alternatives; 210 | } elseif (!empty($alternatives)) { 211 | throw new BadConfigurationException('alternatives must be array or path to configuration file'); 212 | } 213 | } 214 | 215 | $aliases = $package->collectAliases(); 216 | 217 | $this->builder->mergeAliases($aliases); 218 | $this->builder->setPackage($package->getPrettyName(), array_filter([ 219 | 'name' => $package->getPrettyName(), 220 | 'version' => $package->getVersion(), 221 | 'reference' => $package->getSourceReference() ?: $package->getDistReference(), 222 | 'aliases' => $aliases, 223 | ])); 224 | } 225 | 226 | private function readConfig($package, $file): array 227 | { 228 | $path = $package->preparePath($file); 229 | if (!file_exists($path)) { 230 | throw new FailedReadException("failed read file: $file"); 231 | } 232 | $reader = ReaderFactory::get($this->builder, $path); 233 | 234 | return $reader->read($path); 235 | 236 | } 237 | 238 | protected function loadDotEnv(Package $package) 239 | { 240 | $path = $package->preparePath('.env'); 241 | if (file_exists($path) && class_exists('Dotenv\Dotenv')) { 242 | $this->addFile($package, 'dotenv', $path); 243 | } 244 | } 245 | 246 | /** 247 | * Adds given files to the list of files to be processed. 248 | * Prepares `defines` in reversed order (outer package first) because 249 | * constants cannot be redefined. 250 | * @param Package $package 251 | * @param array $files 252 | */ 253 | protected function addFiles(Package $package, array $files) 254 | { 255 | foreach ($files as $name => $paths) { 256 | $paths = (array) $paths; 257 | if ('defines' === $name) { 258 | $paths = array_reverse($paths); 259 | } 260 | foreach ($paths as $path) { 261 | $this->addFile($package, $name, $path); 262 | } 263 | } 264 | } 265 | 266 | protected $orderedFiles = []; 267 | 268 | protected function addFile(Package $package, string $name, string $path) 269 | { 270 | $path = $package->preparePath($path); 271 | if (!isset($this->files[$name])) { 272 | $this->files[$name] = []; 273 | } 274 | if (in_array($path, $this->files[$name], true)) { 275 | return; 276 | } 277 | if ('defines' === $name) { 278 | array_unshift($this->orderedFiles, $path); 279 | array_unshift($this->files[$name], $path); 280 | } else { 281 | array_push($this->orderedFiles, $path); 282 | array_push($this->files[$name], $path); 283 | } 284 | } 285 | 286 | /** 287 | * Sets [[packages]]. 288 | * @param Package[] $packages 289 | */ 290 | public function setPackages(array $packages) 291 | { 292 | $this->packages = $packages; 293 | } 294 | 295 | /** 296 | * Gets [[packages]]. 297 | * @return Package[] 298 | */ 299 | public function getPackages() 300 | { 301 | if (null === $this->packages) { 302 | $this->packages = $this->findPackages(); 303 | } 304 | 305 | return $this->packages; 306 | } 307 | 308 | /** 309 | * Plain list of all project dependencies (including nested) as provided by composer. 310 | * The list is unordered (chaotic, can be different after every update). 311 | */ 312 | protected $plainList = []; 313 | 314 | /** 315 | * Ordered list of package in form: package => depth 316 | * For order description @see findPackages. 317 | */ 318 | protected $orderedList = []; 319 | 320 | /** 321 | * Returns ordered list of packages: 322 | * - listed earlier in the composer.json will get earlier in the list 323 | * - childs before parents. 324 | * @return Package[] 325 | */ 326 | public function findPackages() 327 | { 328 | $root = new Package($this->composer->getPackage(), $this->composer); 329 | $this->plainList[$root->getPrettyName()] = $root; 330 | foreach ($this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages() as $package) { 331 | $this->plainList[$package->getPrettyName()] = new Package($package, $this->composer); 332 | } 333 | $this->orderedList = []; 334 | $this->iteratePackage($root, true); 335 | 336 | $res = []; 337 | foreach (array_keys($this->orderedList) as $name) { 338 | $res[] = $this->plainList[$name]; 339 | } 340 | 341 | return $res; 342 | } 343 | 344 | /** 345 | * Iterates through package dependencies. 346 | * @param Package $package to iterate 347 | * @param bool $includingDev process development dependencies, defaults to not process 348 | */ 349 | protected function iteratePackage(Package $package, $includingDev = false) 350 | { 351 | $name = $package->getPrettyName(); 352 | 353 | /// prevent infinite loop in case of circular dependencies 354 | static $processed = []; 355 | if (isset($processed[$name])) { 356 | return; 357 | } else { 358 | $processed[$name] = 1; 359 | } 360 | 361 | /// package depth in dependency hierarchy 362 | static $depth = 0; 363 | ++$depth; 364 | 365 | $this->iterateDependencies($package); 366 | if ($includingDev) { 367 | $this->iterateDependencies($package, true); 368 | } 369 | if (!isset($this->orderedList[$name])) { 370 | $this->orderedList[$name] = $depth; 371 | } 372 | 373 | --$depth; 374 | } 375 | 376 | /** 377 | * Iterates dependencies of the given package. 378 | * @param Package $package 379 | * @param bool $dev which dependencies to iterate: true - dev, default - general 380 | */ 381 | protected function iterateDependencies(Package $package, $dev = false) 382 | { 383 | $deps = $dev ? $package->getDevRequires() : $package->getRequires(); 384 | foreach (array_keys($deps) as $target) { 385 | if (isset($this->plainList[$target]) && empty($this->orderedList[$target])) { 386 | $this->iteratePackage($this->plainList[$target]); 387 | } 388 | } 389 | } 390 | 391 | protected function showDepsTree() 392 | { 393 | if (!$this->io->isVerbose()) { 394 | return; 395 | } 396 | 397 | foreach (array_reverse($this->orderedList) as $name => $depth) { 398 | $deps = $this->originalFiles[$name]; 399 | $color = $this->colors[$depth % count($this->colors)]; 400 | $indent = str_repeat(' ', $depth - 1); 401 | $package = $this->plainList[$name]; 402 | $showdeps = $deps ? '[' . implode(',', array_keys($deps)) . ']' : ''; 403 | $this->io->write(sprintf('%s - %s %s %s', $indent, $color, $name, $package->getFullPrettyVersion(), $showdeps)); 404 | } 405 | } 406 | } 407 | -------------------------------------------------------------------------------- /src/configs/Config.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class Config 25 | { 26 | const UNIX_DS = '/'; 27 | const BASE_DIR_MARKER = '<<>>'; 28 | 29 | /** 30 | * @var string config name 31 | */ 32 | protected $name; 33 | 34 | /** 35 | * @var array sources - paths to config source files 36 | */ 37 | protected $sources = []; 38 | 39 | /** 40 | * @var array config value 41 | */ 42 | protected $values = []; 43 | 44 | /** 45 | * @var Builder 46 | */ 47 | protected $builder; 48 | 49 | public function __construct(Builder $builder, string $name) 50 | { 51 | $this->builder = $builder; 52 | $this->name = $name; 53 | } 54 | 55 | public function clone(Builder $builder) 56 | { 57 | $config = new Config($builder, $this->name); 58 | $config->sources = $this->sources; 59 | $config->values = $this->values; 60 | 61 | return $config; 62 | } 63 | 64 | public function getBuilder(): Builder 65 | { 66 | return $this->builder; 67 | } 68 | 69 | public function getName(): string 70 | { 71 | return $this->name; 72 | } 73 | 74 | public function getValues(): array 75 | { 76 | return $this->values; 77 | } 78 | 79 | public function load(array $paths = []): self 80 | { 81 | $this->sources = $this->loadFiles($paths); 82 | 83 | return $this; 84 | } 85 | 86 | protected function loadFiles(array $paths): array 87 | { 88 | switch (count($paths)) { 89 | case 0: 90 | return []; 91 | case 1: 92 | return [$this->loadFile(reset($paths))]; 93 | } 94 | 95 | $configs = []; 96 | foreach ($paths as $path) { 97 | $cs = $this->loadFiles($this->glob($path)); 98 | foreach ($cs as $config) { 99 | if (!empty($config)) { 100 | $configs[] = $config; 101 | } 102 | } 103 | } 104 | 105 | return $configs; 106 | } 107 | 108 | protected function glob(string $path): array 109 | { 110 | if (strpos($path, '*') === FALSE) { 111 | return [$path]; 112 | } 113 | 114 | return glob($path); 115 | } 116 | 117 | /** 118 | * Reads config file. 119 | * @param string $path 120 | * @return array configuration read from file 121 | */ 122 | protected function loadFile($path): array 123 | { 124 | $reader = ReaderFactory::get($this->builder, $path); 125 | 126 | return $reader->read($path); 127 | } 128 | 129 | /** 130 | * Merges given configs and writes at given name. 131 | * @return Config 132 | */ 133 | public function build(): self 134 | { 135 | $this->values = $this->calcValues($this->sources); 136 | 137 | return $this; 138 | } 139 | 140 | public function write(): self 141 | { 142 | $this->writeFile($this->getOutputPath(), $this->values); 143 | 144 | return $this; 145 | } 146 | 147 | protected function calcValues(array $sources): array 148 | { 149 | $values = call_user_func_array([Helper::class, 'mergeConfig'], $sources); 150 | $values = Helper::fixConfig($values); 151 | 152 | return $this->substituteOutputDirs($values); 153 | } 154 | 155 | protected function writeFile(string $path, array $data): void 156 | { 157 | $this->writePhpFile($path, $data); 158 | } 159 | 160 | /** 161 | * Writes complete PHP config file by full path. 162 | * @param string $path 163 | * @param string|array $data 164 | * @param bool $withEnv 165 | * @param bool $withDefines 166 | * @throws FailedWriteException 167 | * @throws ReflectionException 168 | */ 169 | protected function writePhpFile(string $path, $data): void 170 | { 171 | $depth = $this->findDepth(); 172 | $baseDir = $depth>0 ? "dirname(__DIR__, $depth)" : '__DIR__'; 173 | static::putFile($path, $this->replaceMarkers(implode("\n\n", array_filter([ 174 | 'header' => ' "\$baseDir = $baseDir;", 176 | 'BASEDIR' => "defined('COMPOSER_CONFIG_PLUGIN_BASEDIR') or define('COMPOSER_CONFIG_PLUGIN_BASEDIR', \$baseDir);", 177 | 'dotenv' => $this->withEnv() ? "\$_ENV = array_merge((array) require __DIR__ . '/dotenv.php', (array) \$_ENV);" : '', 178 | 'defines' => $this->withDefines() ? $this->builder->getConfig('defines')->buildRequires() : '', 179 | 'params' => $this->withParams() ? "\$params = require __DIR__ . '/params.php';" : '', 180 | 'content' => is_array($data) ? $this->renderVars($data) : $data, 181 | ]))) . "\n"); 182 | } 183 | 184 | private function withEnv(): bool 185 | { 186 | return !in_array(static::class, [System::class, DotEnv::class], true); 187 | } 188 | 189 | private function withDefines(): bool 190 | { 191 | return !in_array(static::class, [System::class, DotEnv::class, Defines::class], true); 192 | } 193 | 194 | private function withParams(): bool 195 | { 196 | return !in_array(static::class, [System::class, DotEnv::class, Defines::class, Params::class], true); 197 | } 198 | 199 | private function findDepth() 200 | { 201 | $outDir = dirname(self::normalizePath($this->getOutputPath())); 202 | $diff = substr($outDir, strlen($this->getBaseDir())); 203 | 204 | return substr_count($diff, self::UNIX_DS); 205 | } 206 | 207 | /** 208 | * @param array $vars array to be exported 209 | * @return string 210 | * @throws ReflectionException 211 | */ 212 | protected function renderVars(array $vars): string 213 | { 214 | return 'return ' . Helper::exportVar($vars) . ';'; 215 | } 216 | 217 | protected function replaceMarkers(string $content): string 218 | { 219 | $content = str_replace("'" . static::BASE_DIR_MARKER, "\$baseDir . '", $content); 220 | 221 | return str_replace("'?" . static::BASE_DIR_MARKER, "'?' . \$baseDir . '", $content); 222 | } 223 | 224 | /** 225 | * Writes file if content changed. 226 | * @param string $path 227 | * @param string $content 228 | * @throws FailedWriteException 229 | */ 230 | protected static function putFile($path, $content): void 231 | { 232 | if (file_exists($path) && $content === file_get_contents($path)) { 233 | return; 234 | } 235 | $dirname = dirname($path); 236 | if (!file_exists($dirname) && !mkdir($dirname, 0777, true) && !is_dir($dirname)) { 237 | throw new FailedWriteException(sprintf('Directory "%s" was not created', $dirname)); 238 | } 239 | if (false === file_put_contents($path, $content)) { 240 | throw new FailedWriteException("Failed write file $path"); 241 | } 242 | } 243 | 244 | /** 245 | * Substitute output paths in given data array recursively with marker. 246 | * @param array $data 247 | * @return array 248 | */ 249 | public function substituteOutputDirs(array $data): array 250 | { 251 | $dir = static::normalizePath($this->getBaseDir()); 252 | 253 | return static::substitutePaths($data, $dir, static::BASE_DIR_MARKER); 254 | } 255 | 256 | /** 257 | * Normalizes given path with given directory separator. 258 | * Default forced to Unix directory separator for substitutePaths to work properly in Windows. 259 | * @param string $path path to be normalized 260 | * @param string $ds directory separator 261 | * @return string 262 | */ 263 | public static function normalizePath($path, $ds = self::UNIX_DS): string 264 | { 265 | return rtrim(strtr($path, '/\\', $ds . $ds), $ds); 266 | } 267 | 268 | /** 269 | * Substitute all paths in given array recursively with alias if applicable. 270 | * @param array $data 271 | * @param string $dir 272 | * @param string $alias 273 | * @return array 274 | */ 275 | public static function substitutePaths($data, $dir, $alias): array 276 | { 277 | foreach ($data as &$value) { 278 | if (is_string($value)) { 279 | $value = static::substitutePath($value, $dir, $alias); 280 | } elseif (is_array($value)) { 281 | $value = static::substitutePaths($value, $dir, $alias); 282 | } 283 | } 284 | 285 | return $data; 286 | } 287 | 288 | /** 289 | * Substitute path with alias if applicable. 290 | * @param string $path 291 | * @param string $dir 292 | * @param string $alias 293 | * @return string 294 | */ 295 | protected static function substitutePath($path, $dir, $alias): string 296 | { 297 | $end = $dir . self::UNIX_DS; 298 | $skippable = 0 === strncmp($path, '?', 1) ? '?' : ''; 299 | if ($skippable) { 300 | $path = substr($path, 1); 301 | } 302 | if ($path === $dir) { 303 | $result = $alias; 304 | } elseif (strpos($path, $end) === 0) { 305 | $result = $alias . substr($path, strlen($end) - 1); 306 | } else { 307 | $result = $path; 308 | } 309 | 310 | return $skippable . $result; 311 | } 312 | 313 | public function getBaseDir(): string 314 | { 315 | return dirname(__DIR__, 5); 316 | } 317 | 318 | public function getOutputDir(): string 319 | { 320 | return $this->builder->getOutputDir(); 321 | } 322 | 323 | public function getOutputPath(string $name = null): string 324 | { 325 | return $this->builder->getOutputPath($name ?: $this->name); 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /src/configs/ConfigFactory.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class ConfigFactory 22 | { 23 | private static $knownTypes = [ 24 | '__rebuild' => Rebuild::class, 25 | '__files' => System::class, 26 | 'aliases' => System::class, 27 | 'packages' => System::class, 28 | 'dotenv' => DotEnv::class, 29 | 'params' => Params::class, 30 | 'defines' => Defines::class, 31 | ]; 32 | 33 | /** 34 | * @param Builder $builder 35 | * @param string $name 36 | * @return Config 37 | */ 38 | public static function create(Builder $builder, string $name): Config 39 | { 40 | $class = static::$knownTypes[$name] ?? Config::class; 41 | 42 | return new $class($builder, $name); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/configs/Defines.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class Defines extends Config 19 | { 20 | protected function loadFile($path): array 21 | { 22 | parent::loadFile($path); 23 | if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') { 24 | return []; 25 | } 26 | 27 | return [$path]; 28 | } 29 | 30 | public function buildRequires(): string 31 | { 32 | $res = []; 33 | foreach ($this->values as $path) { 34 | $res[] = "require_once '$path';"; 35 | } 36 | 37 | return implode("\n", $res); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/configs/DotEnv.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class DotEnv extends Config 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/configs/Params.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class Params extends Config 19 | { 20 | protected function calcValues(array $sources): array 21 | { 22 | return $this->pushEnvVars(parent::calcValues($sources)); 23 | } 24 | 25 | protected function pushEnvVars($vars): array 26 | { 27 | $env = $this->builder->getConfig('dotenv')->getValues(); 28 | if (!empty($vars)) { 29 | foreach ($vars as $key => &$value) { 30 | if (is_array($value)) { 31 | foreach (array_keys($value) as $subkey) { 32 | $envKey = $this->getEnvKey($key . '_' . $subkey); 33 | if (isset($env[$envKey])) { 34 | $value[$subkey] = $env[$envKey]; 35 | } 36 | } 37 | } else { 38 | $envKey = $this->getEnvKey($key); 39 | if (isset($env[$envKey])) { 40 | $vars[$key] = $env[$envKey]; 41 | } 42 | } 43 | } 44 | } 45 | 46 | return $vars; 47 | } 48 | 49 | private function getEnvKey(string $key): string 50 | { 51 | return strtoupper(strtr($key, '.-', '__')); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/configs/Rebuild.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class Rebuild extends Config 19 | { 20 | protected function writeFile(string $path, array $data): void 21 | { 22 | static::putFile($path, file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . '__rebuild.php')); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/configs/System.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class System extends Config 20 | { 21 | public function setValue(string $name, $value): Config 22 | { 23 | $this->values[$name] = $value; 24 | 25 | return $this; 26 | } 27 | 28 | public function setValues(array $values): Config 29 | { 30 | $this->values = $values; 31 | 32 | return $this; 33 | } 34 | 35 | public function mergeValues(array $values): Config 36 | { 37 | $this->values = array_merge($this->values, $values); 38 | 39 | return $this; 40 | } 41 | 42 | public function load(array $paths = []): Config 43 | { 44 | $path = $this->getOutputPath(); 45 | if (!file_exists($path)) { 46 | return $this; 47 | } 48 | 49 | $this->values = array_merge($this->loadFile($path), $this->values); 50 | 51 | return $this; 52 | } 53 | 54 | public function build(): Config 55 | { 56 | $this->values = $this->substituteOutputDirs($this->values); 57 | 58 | return $this; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/configs/__rebuild.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 17 | */ 18 | class BadConfigurationException extends Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/exceptions/CircularDependencyException.php: -------------------------------------------------------------------------------- 1 | 16 | */ 17 | class CircularDependencyException extends Exception 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /src/exceptions/Exception.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class Exception extends \Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/exceptions/FailedReadException.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class FailedReadException extends Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/exceptions/FailedWriteException.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class FailedWriteException extends Exception 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/exceptions/UnsupportedFileTypeException.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class UnsupportedFileTypeException extends FailedReadException 19 | { 20 | } 21 | -------------------------------------------------------------------------------- /src/readers/AbstractReader.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | abstract class AbstractReader 22 | { 23 | /** 24 | * @var Builder 25 | */ 26 | protected $builder; 27 | 28 | public function __construct(Builder $builder) 29 | { 30 | $this->builder = $builder; 31 | } 32 | 33 | public function getBuilder(): Builder 34 | { 35 | return $this->builder; 36 | } 37 | 38 | public function read($path) 39 | { 40 | $skippable = 0 === strncmp($path, '?', 1) ? '?' : ''; 41 | if ($skippable) { 42 | $path = substr($path, 1); 43 | } 44 | 45 | if (is_readable($path)) { 46 | $res = $this->readRaw($path); 47 | 48 | return is_array($res) ? $res : []; 49 | } 50 | 51 | if (empty($skippable)) { 52 | throw new FailedReadException("failed read file: $path"); 53 | } 54 | 55 | return []; 56 | } 57 | 58 | public function getFileContents($path) 59 | { 60 | $res = file_get_contents($path); 61 | if (false === $res) { 62 | throw new FailedReadException("failed read file: $path"); 63 | } 64 | 65 | return $res; 66 | } 67 | 68 | abstract public function readRaw($path); 69 | } 70 | -------------------------------------------------------------------------------- /src/readers/EnvReader.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class EnvReader extends AbstractReader 22 | { 23 | public function readRaw($path) 24 | { 25 | if (!class_exists(Dotenv::class)) { 26 | throw new UnsupportedFileTypeException('for .env support require `vlucas/phpdotenv` in your composer.json'); 27 | } 28 | $info = pathinfo($path); 29 | $this->loadDotenv($info['dirname'], $info['basename']); 30 | 31 | return $_ENV; 32 | } 33 | 34 | /** 35 | * Creates and loads Dotenv object. 36 | * Supports all 2, 3 and 4 version of `phpdotenv` 37 | * @param mixed $dir 38 | * @param mixed $file 39 | * @return Dotenv\Dotenv 40 | */ 41 | private function loadDotenv($dir, $file) 42 | { 43 | if (method_exists(Dotenv::class, 'createMutable')) { 44 | Dotenv::createMutable($dir, $file)->load(); 45 | } elseif (method_exists(Dotenv::class, 'create')) { 46 | Dotenv::create($dir, $file)->overload(); 47 | } else { 48 | (new Dotenv($dir, $file))->overload(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/readers/JsonReader.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class JsonReader extends AbstractReader 19 | { 20 | public function readRaw($path) 21 | { 22 | return json_decode($this->getFileContents($path), true); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/readers/PhpReader.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class PhpReader extends AbstractReader 19 | { 20 | public function readRaw($__path) 21 | { 22 | /// Expose variables to be used in configs 23 | extract($this->builder->getVars()); 24 | 25 | return require $__path; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/readers/ReaderFactory.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class ReaderFactory 22 | { 23 | private static $loaders; 24 | 25 | protected static $knownReaders = [ 26 | 'env' => EnvReader::class, 27 | 'php' => PhpReader::class, 28 | 'json' => JsonReader::class, 29 | 'yaml' => YamlReader::class, 30 | 'yml' => YamlReader::class, 31 | ]; 32 | 33 | public static function get(Builder $builder, $path) 34 | { 35 | $type = static::detectType($path); 36 | $class = static::findClass($type); 37 | 38 | #return static::create($builder, $type); 39 | 40 | $uniqid = $class . ':' . spl_object_hash($builder); 41 | if (empty(static::$loaders[$uniqid])) { 42 | static::$loaders[$uniqid] = static::create($builder, $type); 43 | } 44 | 45 | return static::$loaders[$uniqid]; 46 | } 47 | 48 | public static function detectType($path) 49 | { 50 | if (strncmp(basename($path), '.env.', 5) === 0) { 51 | return 'env'; 52 | } 53 | 54 | return pathinfo($path, PATHINFO_EXTENSION); 55 | } 56 | 57 | public static function findClass($type) 58 | { 59 | if (empty(static::$knownReaders[$type])) { 60 | throw new UnsupportedFileTypeException("unsupported file type: $type"); 61 | } 62 | 63 | return static::$knownReaders[$type]; 64 | } 65 | 66 | public static function create(Builder $builder, $type) 67 | { 68 | $class = static::findClass($type); 69 | 70 | return new $class($builder); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/readers/YamlReader.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class YamlReader extends AbstractReader 22 | { 23 | public function readRaw($path) 24 | { 25 | if (!class_exists(Yaml::class)) { 26 | throw new UnsupportedFileTypeException("for YAML support require `symfony/yaml` in your composer.json (reading $path)"); 27 | } 28 | 29 | return Yaml::parse($this->getFileContents($path)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/utils/ClosureEncoder.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class ClosureEncoder implements Encoder 22 | { 23 | /** 24 | * {@inheritdoc} 25 | */ 26 | public function getDefaultOptions() 27 | { 28 | return []; 29 | } 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | public function supports($value) 35 | { 36 | return $value instanceof Closure; 37 | } 38 | 39 | /** 40 | * {@inheritdoc} 41 | */ 42 | public function encode($value, $depth, array $options, callable $encode) 43 | { 44 | return (new ReflectionClosure($value))->getCode(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/utils/Helper.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class Helper 21 | { 22 | /** 23 | * Merges two or more arrays into one recursively. 24 | * Based on Yii2 yii\helpers\BaseArrayHelper::merge. 25 | * @return array the merged array 26 | */ 27 | public static function mergeConfig(): array 28 | { 29 | $args = \func_get_args(); 30 | $res = array_shift($args) ?: []; 31 | foreach ($args as $items) { 32 | if (!\is_array($items)) { 33 | continue; 34 | } 35 | foreach ($items as $k => $v) { 36 | if ($v instanceof \yii\helpers\UnsetArrayValue || $v instanceof \Yiisoft\Arrays\UnsetArrayValue) { 37 | unset($res[$k]); 38 | } elseif ($v instanceof \yii\helpers\ReplaceArrayValue || $v instanceof \Yiisoft\Arrays\ReplaceArrayValue) { 39 | $res[$k] = $v->value; 40 | } elseif (\is_int($k)) { 41 | /// XXX skip repeated values 42 | if (\in_array($v, $res, true)) { 43 | continue; 44 | } 45 | if (isset($res[$k])) { 46 | $res[] = $v; 47 | } else { 48 | $res[$k] = $v; 49 | } 50 | } elseif (\is_array($v) && isset($res[$k]) && \is_array($res[$k])) { 51 | $res[$k] = self::mergeConfig($res[$k], $v); 52 | } else { 53 | $res[$k] = $v; 54 | } 55 | } 56 | } 57 | 58 | return $res; 59 | } 60 | 61 | public static function fixConfig(array $config): array 62 | { 63 | $remove = false; 64 | foreach ($config as $key => &$value) { 65 | if (is_array($value)) { 66 | $value = static::fixConfig($value); 67 | } elseif ($value instanceof RemoveArrayKeys) { 68 | $remove = true; 69 | unset($config[$key]); 70 | } 71 | } 72 | if ($remove) { 73 | return array_values($config); 74 | } 75 | 76 | return $config; 77 | } 78 | 79 | public static function exportDefines(array $defines): string 80 | { 81 | $res = ''; 82 | foreach ($defines as $key => $value) { 83 | $var = static::exportVar($value); 84 | $res .= "defined('$key') or define('$key', $var);\n"; 85 | } 86 | 87 | return $res; 88 | } 89 | 90 | /** 91 | * Returns PHP-executable string representation of given value. 92 | * Uses Riimu/Kit-PHPEncoder based `var_export` alternative. 93 | * And Opis/Closure to dump closures as PHP code. 94 | * @param mixed $value 95 | * @return string 96 | * @throws \ReflectionException 97 | */ 98 | public static function exportVar($value): string 99 | { 100 | return static::getEncoder()->encode($value); 101 | } 102 | 103 | private static $encoder; 104 | 105 | private static function getEncoder() 106 | { 107 | if (static::$encoder === null) { 108 | static::$encoder = static::createEncoder(); 109 | } 110 | 111 | return static::$encoder; 112 | } 113 | 114 | private static function createEncoder() 115 | { 116 | $encoder = new PHPEncoder([ 117 | 'object.format' => 'serialize', 118 | ]); 119 | $encoder->addEncoder(new ClosureEncoder(), true); 120 | 121 | return $encoder; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/utils/RemoveArrayKeys.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class RemoveArrayKeys 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /src/utils/Resolver.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class Resolver 22 | { 23 | protected $order = []; 24 | 25 | protected $deps = []; 26 | 27 | protected $following = []; 28 | 29 | public function __construct(array $files) 30 | { 31 | $this->files = $files; 32 | 33 | $this->collectDeps(); 34 | foreach (array_keys($this->files) as $name) { 35 | $this->followDeps($name); 36 | } 37 | } 38 | 39 | public function get() 40 | { 41 | $result = []; 42 | foreach ($this->order as $name) { 43 | $result[$name] = $this->resolveDeps($this->files[$name]); 44 | } 45 | 46 | return $result; 47 | } 48 | 49 | protected function resolveDeps(array $paths) 50 | { 51 | foreach ($paths as &$path) { 52 | $dep = $this->isDep($path); 53 | if ($dep) { 54 | $path = Builder::path($dep); 55 | } 56 | } 57 | 58 | return $paths; 59 | } 60 | 61 | protected function followDeps($name) 62 | { 63 | if (isset($this->order[$name])) { 64 | return; 65 | } 66 | if (isset($this->following[$name])) { 67 | throw new CircularDependencyException($name . ' ' . implode(',', $this->following)); 68 | } 69 | $this->following[$name] = $name; 70 | if (isset($this->deps[$name])) { 71 | foreach ($this->deps[$name] as $dep) { 72 | $this->followDeps($dep); 73 | } 74 | } 75 | $this->order[$name] = $name; 76 | unset($this->following[$name]); 77 | } 78 | 79 | protected function collectDeps() 80 | { 81 | foreach ($this->files as $name => $paths) { 82 | foreach ($paths as $path) { 83 | $dep = $this->isDep($path); 84 | if ($dep) { 85 | if (!isset($this->deps[$name])) { 86 | $this->deps[$name] = []; 87 | } 88 | $this->deps[$name][$dep] = $dep; 89 | } 90 | } 91 | } 92 | } 93 | 94 | protected function isDep($path) 95 | { 96 | return 0 === strncmp($path, '$', 1) ? substr($path, 1) : false; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /tests/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 42]; 14 | $closure = static function () use ($params) { 15 | return $params['test']; 16 | }; 17 | 18 | $exportedClosure = Helper::exportVar($closure); 19 | 20 | $this->assertSameWithoutLE("static function () use (\$params) {\n return \$params['test'];\n }", $exportedClosure); 21 | } 22 | 23 | private function assertSameWithoutLE($expected, $actual, string $message = ''): void 24 | { 25 | $expected = preg_replace('/\R/', "\n", $expected); 26 | $actual = preg_replace('/\R/', "\n", $actual); 27 | $this->assertSame($expected, $actual, $message); 28 | } 29 | 30 | public function testFixRemoveArrayKeys() 31 | { 32 | $config = [ 33 | 'a' => '1', 34 | 'b' => '2', 35 | 'c' => [ 36 | 'd' => 4, 37 | 'remove' => new RemoveArrayKeys(), 38 | 'e' => 5, 39 | ], 40 | ]; 41 | 42 | $fixed = $config; 43 | unset($fixed['c']['remove']); 44 | $fixed['c'] = array_values($fixed['c']); 45 | 46 | $this->assertEquals($fixed, Helper::fixConfig($config)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/unit/PluginTest.php: -------------------------------------------------------------------------------- 1 | composer = new Composer(); 32 | $this->composer->setConfig(new Config(true, getcwd())); 33 | $this->io = $this->createMock('Composer\IO\IOInterface'); 34 | $this->event = $this->getMockBuilder('Composer\Script\Event') 35 | ->setConstructorArgs(['test', $this->composer, $this->io]) 36 | ->getMock(); 37 | 38 | $this->object = new Plugin(); 39 | $this->object->setPackages($this->packages); 40 | $this->object->activate($this->composer, $this->io); 41 | } 42 | 43 | public function testGetPackages() 44 | { 45 | $this->assertSame($this->packages, $this->object->getPackages()); 46 | } 47 | 48 | public function testGetSubscribedEvents() 49 | { 50 | $this->assertInternalType('array', $this->object->getSubscribedEvents()); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/unit/configs/ConfigFactoryTest.php: -------------------------------------------------------------------------------- 1 | builder = new Builder(); 30 | 31 | $this->checkCreate('common', Config::class); 32 | $this->checkCreate('defines', Defines::class); 33 | $this->checkCreate('params', Params::class); 34 | $this->checkCreate('__files', System::class); 35 | } 36 | 37 | public function checkCreate(string $name, string $class) 38 | { 39 | $config = ConfigFactory::create($this->builder, $name); 40 | $this->assertInstanceOf($class, $config); 41 | $this->assertSame($this->builder, $config->getBuilder()); 42 | $this->assertSame($name, $config->getName()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/unit/readers/ReaderFactoryTest.php: -------------------------------------------------------------------------------- 1 | builder = new Builder(); 30 | 31 | $env = $this->checkGet('.env', EnvReader::class); 32 | $json = $this->checkGet('.json', JsonReader::class); 33 | $yml = $this->checkGet('.yml', YamlReader::class); 34 | $yaml = $this->checkGet('.yaml', YamlReader::class); 35 | $php = $this->checkGet('.php', PhpReader::class); 36 | $php2 = $this->checkGet('.php', PhpReader::class); 37 | 38 | $this->assertSame($php, $php2); 39 | $this->assertSame($yml, $yaml); 40 | } 41 | 42 | public function checkGet(string $name, string $class) 43 | { 44 | $reader = ReaderFactory::get($this->builder, $name); 45 | $this->assertInstanceOf($class, $reader); 46 | $this->assertSame($this->builder, $reader->getBuilder()); 47 | 48 | return $reader; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | composer-config-plugin dev-0.4.0-e3392b6 2020-03-08 20:51:09 +0200 e3392b6fae3dc3200d85edb359fcef5739558536 2 | --------------------------------------------------------------------------------