From 42503ca5e14097d30f2028ae9c3e66fd415bb0aa Mon Sep 17 00:00:00 2001 From: Marcel Frankruijter Date: Tue, 10 Nov 2020 21:26:10 +0100 Subject: [PATCH] Initial implementation of the package --- .gitattributes | 8 ++ .gitignore | 2 + .travis.yml | 16 +++ CHANGELOG.md | 12 ++ CODE_OF_CONDUCT.md | 76 +++++++++++ CONTRIBUTING.md | 28 +++++ LICENSE | 21 ++++ PULL_REQUEST_TEMPLATE.md | 18 +++ README.md | 49 ++++++++ composer.json | 61 +++++++++ .../command/environment.command.json | 4 + .../command/environment.get.command.json | 15 +++ .../command/environment.list.command.json | 6 + .../command/environment.set.command.json | 22 ++++ .../environment.configuration.json | 5 + .../invocations/environment.invocations.json | 13 ++ .../persistent/environment.persistent.json | 3 + .../environment.extension.json | 15 +++ .../environment.extension.json | 5 + .../services/environment.commands.json | 20 +++ docs/index.md | 8 ++ docs/usage/create-an-environment-variable.md | 45 +++++++ docs/usage/index.md | 9 ++ docs/usage/installation.md | 20 +++ locator.php | 14 +++ phpcs.xml | 12 ++ phpunit.xml | 16 +++ src/Command/EnvironmentGetCommand.php | 54 ++++++++ src/Command/EnvironmentListCommand.php | 57 +++++++++ src/Command/EnvironmentSetCommand.php | 58 +++++++++ .../UlrackEnvironmentExtensionPackage.php | 16 +++ src/Factory/Extension/EnvironmentFactory.php | 118 ++++++++++++++++++ tests/Command/EnvironmentGetCommandTest.php | 53 ++++++++ tests/Command/EnvironmentListCommandTest.php | 67 ++++++++++ tests/Command/EnvironmentSetCommandTest.php | 74 +++++++++++ .../Extension/EnvironmentFactoryTest.php | 54 ++++++++ 36 files changed, 1074 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 PULL_REQUEST_TEMPLATE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 configuration/command/environment.command.json create mode 100644 configuration/command/environment.get.command.json create mode 100644 configuration/command/environment.list.command.json create mode 100644 configuration/command/environment.set.command.json create mode 100644 configuration/configuration/environment.configuration.json create mode 100644 configuration/invocations/environment.invocations.json create mode 100644 configuration/persistent/environment.persistent.json create mode 100644 configuration/service-compiler-extensions/environment.extension.json create mode 100644 configuration/service-factory-extensions/environment.extension.json create mode 100644 configuration/services/environment.commands.json create mode 100644 docs/index.md create mode 100644 docs/usage/create-an-environment-variable.md create mode 100644 docs/usage/index.md create mode 100644 docs/usage/installation.md create mode 100644 locator.php create mode 100644 phpcs.xml create mode 100644 phpunit.xml create mode 100644 src/Command/EnvironmentGetCommand.php create mode 100644 src/Command/EnvironmentListCommand.php create mode 100644 src/Command/EnvironmentSetCommand.php create mode 100644 src/Common/UlrackEnvironmentExtensionPackage.php create mode 100644 src/Factory/Extension/EnvironmentFactory.php create mode 100644 tests/Command/EnvironmentGetCommandTest.php create mode 100644 tests/Command/EnvironmentListCommandTest.php create mode 100644 tests/Command/EnvironmentSetCommandTest.php create mode 100644 tests/Factory/Extension/EnvironmentFactoryTest.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..754617f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +/tests export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/phpunit.xml export-ignore +/phpcs.xml export-ignore +/PULL_REQUEST_TEMPLATE.md export-ignore +/CODE_OF_CONDUCT.md export-ignore +/CONTRIBUTING.md export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4f4acd3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vendor/ +composer.lock \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e1e0d74 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: php +php: + - '7.3' + - '7.4' + +before_script: + - composer install + +script: + - composer validate --strict + - vendor/bin/phpunit --coverage-text + - vendor/bin/phpcs src/ tests/ + +cache: + directories: + - $HOME/.composer/cache diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..06f15bd --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 1.0.0 - 2020-11-10 +### Added +- The initial implementation of the package. + +# Versions +- [1.0.0 > Unreleased](https://github.com/ulrack/environment-extension/compare/1.0.0...HEAD) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..6dcd974 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at info@grizzit.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..7921a76 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contributing + +To contribute to this package, please keep to these guidelines. + +- Fork the package. +- Create a branch per feature. +- Commit your changes to these branches. +- Create a pull request per feature to the master branch of the original repository. + +## Pull requests + +Pull request should follow these rules, before they can get accepted. + +- Follow the [pull request template](PULL_REQUEST_TEMPLATE.md). +- Contains a short but complete description. +- Has passed all test command listed bellow. + +## Running Tests + +``` bash +$ vendor/bin/phpunit --coverage-text +$ vendor/bin/phpcs src/ tests/ +``` + +## Notes + +Multiple commits per feature are allowed, but please provide a good description in your pull request. +This description will be used to squash your feature into the master branch. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c2833e1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) GrizzIT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..ce6ccf9 --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ +# (bugfix / feature / refactor / etc.): Short descriptive title + +## Description + +Fixes # + +Changes proposed in this pull request: +- +- +- + +Make sure you can check the following boxes before submitting the pull request: +- [] The proposed changes work with the dependencies from composer. +- [] The proposed changes have been thoroughly tested. +- [] The proposed changes don't alter the code in such a manner that it conflicts with the initial purpose of the package. + +Optional checkbox +- [] Backwards incompatible diff --git a/README.md b/README.md new file mode 100644 index 0000000..7bf58aa --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +[![Join us on Discord](https://img.shields.io/discord/753858953452191916.svg?label=Join+us&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/k9KVYqm) +[![Build Status](https://travis-ci.com/ulrack/environment-extension.svg?branch=master)](https://travis-ci.com/ulrack/environment-extension) + +# Ulrack Environment Extension + +This extension adds the ability to configure environment specific configuration +for projects using Ulrack. + +## Installation + +To install the package run the following command: + +``` +composer require ulrack/environment-extension +``` + +## Usage + +Please see the [documentation](docs/index.md) for information on the usage of this package. + +## Change log + +Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) and [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md) for details. + +## MIT License + +Copyright (c) GrizzIT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..95e22f3 --- /dev/null +++ b/composer.json @@ -0,0 +1,61 @@ +{ + "name": "ulrack/environment-extension", + "description": "The environment extension for Ulrack.", + "keywords": [ + "services", + "environment", + "variables" + ], + "type": "library", + "license": "MIT", + "prefer-stable": true, + "minimum-stability": "stable", + "require": { + "php": "^7.3", + "grizz-it/configuration": "^1.2", + "grizz-it/storage": "^1.0", + "ulrack/command": "^2.0", + "ulrack/invocation-extension": "^1.1", + "ulrack/persistent-extension": "^1.1", + "ulrack/services": "^3.3" + }, + "authors": [ + { + "name": "Ulrack", + "homepage": "https://www.ulrack.com/", + "role": "Developer" + } + ], + "config": { + "sort-packages": true + }, + "autoload": { + "psr-4": { + "Ulrack\\EnvironmentExtension\\": "src/" + }, + "files": [ + "locator.php" + ] + }, + "autoload-dev": { + "psr-4": { + "Ulrack\\EnvironmentExtension\\Tests\\": "tests/" + } + }, + "archive": { + "exclude": [ + "/tests", + "/.gitignore", + "/.travis.yml", + "/phpunit.xml", + "/phpcs.xml", + "/PULL_REQUEST_TEMPLATE.md", + "/CODE_OF_CONDUCT.md", + "/CONTRIBUTING.md" + ] + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.5" + } +} diff --git a/configuration/command/environment.command.json b/configuration/command/environment.command.json new file mode 100644 index 0000000..92d944b --- /dev/null +++ b/configuration/command/environment.command.json @@ -0,0 +1,4 @@ +{ + "command": "environment", + "description": "Environment related commands." +} \ No newline at end of file diff --git a/configuration/command/environment.get.command.json b/configuration/command/environment.get.command.json new file mode 100644 index 0000000..6c046d0 --- /dev/null +++ b/configuration/command/environment.get.command.json @@ -0,0 +1,15 @@ +{ + "parent": "environment", + "command": "get", + "description": "Retrieve the value of an environment variable.", + "service": "services.command.environment.get", + "parameters": [ + { + "long": "key", + "short": "k", + "description": "The key of the environment variable.", + "type": "string", + "required": true + } + ] +} \ No newline at end of file diff --git a/configuration/command/environment.list.command.json b/configuration/command/environment.list.command.json new file mode 100644 index 0000000..40d2e89 --- /dev/null +++ b/configuration/command/environment.list.command.json @@ -0,0 +1,6 @@ +{ + "parent": "environment", + "command": "list", + "description": "List all environment variable keys.", + "service": "services.command.environment.list" +} \ No newline at end of file diff --git a/configuration/command/environment.set.command.json b/configuration/command/environment.set.command.json new file mode 100644 index 0000000..7bb7208 --- /dev/null +++ b/configuration/command/environment.set.command.json @@ -0,0 +1,22 @@ +{ + "parent": "environment", + "command": "set", + "description": "Set the value of an environment variable.", + "service": "services.command.environment.set", + "parameters": [ + { + "long": "key", + "short": "k", + "description": "The key of the environment variable.", + "type": "string", + "required": true + }, + { + "long": "value", + "short": "v", + "description": "The value of the environment variable.", + "type": "string", + "required": true + } + ] +} \ No newline at end of file diff --git a/configuration/configuration/environment.configuration.json b/configuration/configuration/environment.configuration.json new file mode 100644 index 0000000..861c16e --- /dev/null +++ b/configuration/configuration/environment.configuration.json @@ -0,0 +1,5 @@ +{ + "$schema": "configuration.schema.json", + "key": "environment", + "location": "configuration/environment" +} diff --git a/configuration/invocations/environment.invocations.json b/configuration/invocations/environment.invocations.json new file mode 100644 index 0000000..76f3cbe --- /dev/null +++ b/configuration/invocations/environment.invocations.json @@ -0,0 +1,13 @@ +{ + "environment.service.factory.extension": { + "service": "invocations.environment.service.factory", + "method": "getExtension", + "parameters": { + "key": "environment" + } + }, + "environment.service.factory": { + "service": "services.core.service.manager", + "method": "getServiceFactory" + } +} \ No newline at end of file diff --git a/configuration/persistent/environment.persistent.json b/configuration/persistent/environment.persistent.json new file mode 100644 index 0000000..a9851fe --- /dev/null +++ b/configuration/persistent/environment.persistent.json @@ -0,0 +1,3 @@ +{ + "environment": {} +} \ No newline at end of file diff --git a/configuration/service-compiler-extensions/environment.extension.json b/configuration/service-compiler-extensions/environment.extension.json new file mode 100644 index 0000000..57b7e26 --- /dev/null +++ b/configuration/service-compiler-extensions/environment.extension.json @@ -0,0 +1,15 @@ +{ + "$schema": "service.compiler.extension.schema.json", + "class": "\\Ulrack\\Services\\Component\\Compiler\\Extension\\PassThroughCompiler", + "sortOrder": 100, + "key": "environment", + "schema": { + "type": "object", + "properties": { + "default": { + "default": null + } + }, + "required": ["default"] + } +} \ No newline at end of file diff --git a/configuration/service-factory-extensions/environment.extension.json b/configuration/service-factory-extensions/environment.extension.json new file mode 100644 index 0000000..5482401 --- /dev/null +++ b/configuration/service-factory-extensions/environment.extension.json @@ -0,0 +1,5 @@ +{ + "$schema": "service.factory.extension.schema.json", + "class": "\\Ulrack\\EnvironmentExtension\\Factory\\Extension\\EnvironmentFactory", + "key": "environment" +} \ No newline at end of file diff --git a/configuration/services/environment.commands.json b/configuration/services/environment.commands.json new file mode 100644 index 0000000..64e30f4 --- /dev/null +++ b/configuration/services/environment.commands.json @@ -0,0 +1,20 @@ +{ + "command.environment.get": { + "class": "\\Ulrack\\EnvironmentExtension\\Command\\EnvironmentGetCommand", + "parameters": { + "serviceFactory": "@{invocations.environment.service.factory}" + } + }, + "command.environment.set": { + "class": "\\Ulrack\\EnvironmentExtension\\Command\\EnvironmentSetCommand", + "parameters": { + "environmentStorage": "@{persistent.environment}" + } + }, + "command.environment.list": { + "class": "\\Ulrack\\EnvironmentExtension\\Command\\EnvironmentListCommand", + "parameters": { + "environmentFactory": "@{invocations.environment.service.factory.extension}" + } + } +} \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..2a8c398 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,8 @@ +# Ulrack Environment Extension Documentation + +This documentation will provide you with information about working with, and extending this package. + +- [Main README](../README.md) +- [Usage](usage/index.md) + - [Installation](usage/installation.md) + - [Create an environment variable](usage/create-an-environment-variable.md) diff --git a/docs/usage/create-an-environment-variable.md b/docs/usage/create-an-environment-variable.md new file mode 100644 index 0000000..a6d7aa8 --- /dev/null +++ b/docs/usage/create-an-environment-variable.md @@ -0,0 +1,45 @@ +# Ulrack Environment Extension - Create an environment variable + +This package add the ability to create and manage environment variables for +projects. This is being managed through the services layer, so multiple +declarations can be made per file. To create an environment variable create a +file in the `configuration/environment` directory with the following content. + +```json +{ + "foo": { + "default": null + } +} +``` + +A default value can be declared for an environment variable through the +`default` field. The environment can now be accessed anywhere in the project +through the services layer by calling it with `@{environment.foo}`. The +variable can be managed with commands. + +## List command + +The list command can be used to retrieve a list of all availible environment +variables. This command is `bin/application environment list`. + +## Get command + +The get command can be used to retrieve the JSON representation of a value of +an environment variable. This command accepts one parameter which is `key` (or +shorthand `k`). It can be invoked like this +`bin/application environment get --key="foo"`. + +## Set command + +The set command can be used to alter the value of the environment variable in +the storage. It accepts two parameters, the `key` variable (same as for the +`get` command). And the `value` (or shorthand `v`) parameter which accepts a +JSON string representation of the value. If the value parameter is omitted +it can be added interactively. + +## Further reading + +[Back to usage index](index.md) + +[Installation](installation.md) diff --git a/docs/usage/index.md b/docs/usage/index.md new file mode 100644 index 0000000..d773b77 --- /dev/null +++ b/docs/usage/index.md @@ -0,0 +1,9 @@ +# Ulrack Environment Extension - Usage Documentation + +This part of the documentation will focus on the usage of this package. + +## Index + +- [Main index](../index.md) +- [Installation](installation.md) +- [Create an environment variable](create-an-environment-variable.md) \ No newline at end of file diff --git a/docs/usage/installation.md b/docs/usage/installation.md new file mode 100644 index 0000000..adc08c9 --- /dev/null +++ b/docs/usage/installation.md @@ -0,0 +1,20 @@ +# Ulrack Environment Extension - Installation + +This package is meant as a plug-and-play extension to any Ulrack project. +To start using this package, install it through composer by running: +``` +composer require ulrack/environment-extension +``` + +After the package is installed, run the following command: +``` +bin/application cache clear +``` + +After this is done, the extension should be up and running. + +## Further reading + +[Back to usage index](index.md) + +[Create an environment variable](create-an-environment-variable.md) diff --git a/locator.php b/locator.php new file mode 100644 index 0000000..29cef29 --- /dev/null +++ b/locator.php @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..2b83b56 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,16 @@ + + + + + src + + + + + tests + + + diff --git a/src/Command/EnvironmentGetCommand.php b/src/Command/EnvironmentGetCommand.php new file mode 100644 index 0000000..d2421db --- /dev/null +++ b/src/Command/EnvironmentGetCommand.php @@ -0,0 +1,54 @@ +serviceFactory = $serviceFactory; + } + + /** + * Executes the command. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return void + */ + public function __invoke( + InputInterface $input, + OutputInterface $output + ): void { + $output->writeLine( + json_encode( + $this->serviceFactory->create( + 'environment.' . $input->getParameter('key') + ) + ) + ); + } +} diff --git a/src/Command/EnvironmentListCommand.php b/src/Command/EnvironmentListCommand.php new file mode 100644 index 0000000..19f473b --- /dev/null +++ b/src/Command/EnvironmentListCommand.php @@ -0,0 +1,57 @@ +environmentFactory = $environmentFactory; + } + + /** + * Executes the command. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return void + */ + public function __invoke( + InputInterface $input, + OutputInterface $output + ): void { + $keys = $this->environmentFactory->getKeys(); + if (count($keys) > 0) { + $output->outputList($keys); + + return; + } + + throw new Exception('No available keys.'); + } +} diff --git a/src/Command/EnvironmentSetCommand.php b/src/Command/EnvironmentSetCommand.php new file mode 100644 index 0000000..5471359 --- /dev/null +++ b/src/Command/EnvironmentSetCommand.php @@ -0,0 +1,58 @@ +environmentStorage = $environmentStorage; + } + + /** + * Executes the command. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return void + */ + public function __invoke( + InputInterface $input, + OutputInterface $output + ): void { + $value = $input->getParameter('value'); + + $jsonValue = json_decode($value, true); + if (json_last_error() === JSON_ERROR_NONE) { + $value = $jsonValue; + } + + $this->environmentStorage->set( + $input->getParameter('key'), + $value + ); + } +} diff --git a/src/Common/UlrackEnvironmentExtensionPackage.php b/src/Common/UlrackEnvironmentExtensionPackage.php new file mode 100644 index 0000000..c6c2f6e --- /dev/null +++ b/src/Common/UlrackEnvironmentExtensionPackage.php @@ -0,0 +1,16 @@ +environmentVariables[$serviceKey] = $value; + } + + /** + * Retrieves the environment storage. + * + * @return StorageInterface + */ + private function getEnvironmentStorage(): StorageInterface + { + if (is_null($this->environmentStorage)) { + $this->environmentStorage = $this->superCreate( + 'persistent.environment' + ); + } + + return $this->environmentStorage; + } + + /** + * Retrieves a list of all environment keys. + * + * @return array + */ + public function getKeys(): array + { + return array_keys($this->getServices()[$this->getKey()] ?? []); + } + + /** + * Invoke the invocation and return the result. + * + * @param string $serviceKey + * + * @return mixed + * + * @throws DefinitionNotFoundException When the definition can not be found. + */ + public function create(string $serviceKey) + { + $serviceKey = $this->preCreate( + $serviceKey, + $this->getParameters() + )['serviceKey']; + + $internalKey = preg_replace( + sprintf('/^%s\\./', preg_quote($this->getKey())), + '', + $serviceKey, + 1 + ); + + if (!isset($this->environmentVariables[$internalKey])) { + $services = $this->getServices()[$this->getKey()]; + if (!isset($services[$internalKey])) { + throw new DefinitionNotFoundException($serviceKey); + } + + $storage = $this->getEnvironmentStorage(); + if (!$storage->has($internalKey)) { + $storage->set( + $internalKey, + $services[$internalKey]['default'] ?? null + ); + } + + $this->registerService( + $internalKey, + $storage->get($internalKey) + ); + } + + return $this->postCreate( + $serviceKey, + $this->environmentVariables[$internalKey], + $this->getParameters() + )['return']; + } +} diff --git a/tests/Command/EnvironmentGetCommandTest.php b/tests/Command/EnvironmentGetCommandTest.php new file mode 100644 index 0000000..c383082 --- /dev/null +++ b/tests/Command/EnvironmentGetCommandTest.php @@ -0,0 +1,53 @@ +createMock(ServiceFactoryInterface::class); + $input = $this->createMock(InputInterface::class); + $output = $this->createMock(OutputInterface::class); + $subject = new EnvironmentGetCommand($serviceFactory); + + $input->expects(static::once()) + ->method('getParameter') + ->with('key') + ->willReturn('foo'); + + $serviceFactory->expects(static::once()) + ->method('create') + ->with('environment.foo') + ->willReturn('bar'); + + $output->expects(static::once()) + ->method('writeLine') + ->with('"bar"'); + + $subject->__invoke( + $input, + $output + ); + } +} diff --git a/tests/Command/EnvironmentListCommandTest.php b/tests/Command/EnvironmentListCommandTest.php new file mode 100644 index 0000000..b87d7ea --- /dev/null +++ b/tests/Command/EnvironmentListCommandTest.php @@ -0,0 +1,67 @@ +createMock(EnvironmentFactory::class); + $output = $this->createMock(OutputInterface::class); + $subject = new EnvironmentListCommand($serviceFactory); + $serviceFactory->expects(static::once()) + ->method('getKeys') + ->willReturn(['foo', 'bar']); + + $output->expects(static::once()) + ->method('outputList') + ->with(['foo', 'bar']); + + $subject->__invoke( + $this->createMock(InputInterface::class), + $output + ); + } + + /** + * @covers ::__invoke + * @covers ::__construct + * + * @return void + */ + public function testInvokeNoKeys(): void + { + $serviceFactory = $this->createMock(EnvironmentFactory::class); + $subject = new EnvironmentListCommand($serviceFactory); + $serviceFactory->expects(static::once()) + ->method('getKeys') + ->willReturn([]); + + $this->expectException(Exception::class); + $subject->__invoke( + $this->createMock(InputInterface::class), + $this->createMock(OutputInterface::class) + ); + } +} diff --git a/tests/Command/EnvironmentSetCommandTest.php b/tests/Command/EnvironmentSetCommandTest.php new file mode 100644 index 0000000..56167ed --- /dev/null +++ b/tests/Command/EnvironmentSetCommandTest.php @@ -0,0 +1,74 @@ +createMock(StorageInterface::class); + $input = $this->createMock(InputInterface::class); + $subject = new EnvironmentSetCommand($storage); + + $input->expects(static::exactly(2)) + ->method('getParameter') + ->withConsecutive(['value'], ['key']) + ->willReturnOnConsecutiveCalls('bar', 'foo'); + + $storage->expects(static::once()) + ->method('set') + ->with('foo', 'bar'); + + $subject->__invoke( + $input, + $this->createMock(OutputInterface::class) + ); + } + + /** + * @covers ::__invoke + * @covers ::__construct + * + * @return void + */ + public function testInvokeJson(): void + { + $storage = $this->createMock(StorageInterface::class); + $input = $this->createMock(InputInterface::class); + $subject = new EnvironmentSetCommand($storage); + + $input->expects(static::exactly(2)) + ->method('getParameter') + ->withConsecutive(['value'], ['key']) + ->willReturnOnConsecutiveCalls('{"foo":"bar"}', 'foo'); + + $storage->expects(static::once()) + ->method('set') + ->with('foo', ['foo' => 'bar']); + + $subject->__invoke( + $input, + $this->createMock(OutputInterface::class) + ); + } +} diff --git a/tests/Factory/Extension/EnvironmentFactoryTest.php b/tests/Factory/Extension/EnvironmentFactoryTest.php new file mode 100644 index 0000000..64b97b0 --- /dev/null +++ b/tests/Factory/Extension/EnvironmentFactoryTest.php @@ -0,0 +1,54 @@ +createMock(ServiceFactoryInterface::class); + $serviceFactory->expects(static::once()) + ->method('create') + ->with('persistent.environment') + ->willReturn($this->createMock(StorageInterface::class)); + + $subject = new EnvironmentFactory( + $serviceFactory, + 'environment', + [], + ['environment' => ['foo' => ['default' => null]]], + (function () { + return []; + }), + [] + ); + + $this->assertEquals(['foo'], $subject->getKeys()); + $this->assertEquals(null, $subject->create('environment.foo')); + + $this->expectException(DefinitionNotFoundException::class); + $subject->create('environment.bar'); + } +}