From 75721abf6fce65f02f73a20ab05143f8092f7921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=B8=D1=80=D1=8E=D1=85=D0=B8=D0=BD?= Date: Fri, 19 Jan 2018 01:01:01 +0300 Subject: [PATCH] Initial --- .gitignore | 3 + composer.json | 21 ++++ src/Compiler/CompilerInterface.php | 23 ++++ src/Dotenv.php | 163 +++++++++++++++++++++++++++++ src/Exception/RuntimeException.php | 13 +++ src/Loader/LoaderInterface.php | 16 +++ src/Parser/ParserInterface.php | 18 ++++ src/Types/KeyValue.php | 48 +++++++++ 8 files changed, 305 insertions(+) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 src/Compiler/CompilerInterface.php create mode 100644 src/Dotenv.php create mode 100644 src/Exception/RuntimeException.php create mode 100644 src/Loader/LoaderInterface.php create mode 100644 src/Parser/ParserInterface.php create mode 100644 src/Types/KeyValue.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8925195 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +vendor +composer.lock \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..565db47 --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "neonxp/dotenv", + "description": "Library to load .env files", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Alexander Kiryukhin", + "email": "alexander@kiryukhin.su" + } + ], + "require": {}, + "autoload": { + "psr-4": { + "NeonXP\\Dotenv\\": "src" + } + }, + "require-dev": { + "phpunit/phpunit": "^6.5" + } +} diff --git a/src/Compiler/CompilerInterface.php b/src/Compiler/CompilerInterface.php new file mode 100644 index 0000000..042a7d0 --- /dev/null +++ b/src/Compiler/CompilerInterface.php @@ -0,0 +1,23 @@ + + * @license: MIT + */ + +namespace NeonXP\Dotenv\Compiler; + +use NeonXP\Dotenv\Types\KeyValue; + +interface CompilerInterface +{ + /** + * @param KeyValue[] $collection + */ + function setRawCollection(array $collection): void; + + /** + * @param KeyValue $keyValue + * @return KeyValue + */ + function compileKeyValue(KeyValue $keyValue): KeyValue; +} \ No newline at end of file diff --git a/src/Dotenv.php b/src/Dotenv.php new file mode 100644 index 0000000..8e7ac10 --- /dev/null +++ b/src/Dotenv.php @@ -0,0 +1,163 @@ + + * @license: MIT + */ + +namespace NeonXP\Dotenv; + +use NeonXP\Dotenv\Compiler\CompilerInterface; +use NeonXP\Dotenv\Exception\RuntimeException; +use NeonXP\Dotenv\Loader\LoaderInterface; +use NeonXP\Dotenv\Parser\ParserInterface; +use NeonXP\Dotenv\Types\KeyValue; + +class Dotenv implements \ArrayAccess, \IteratorAggregate +{ + /** + * @var LoaderInterface + */ + private $loader; + /** + * @var ParserInterface + */ + private $parser; + /** + * @var CompilerInterface + */ + private $compiler; + + /** + * @var array + */ + private $loadedValues; + + /** + * Dotenv constructor. + * @param LoaderInterface $loader + * @param ParserInterface $parser + * @param CompilerInterface $compiler + */ + public function __construct(LoaderInterface $loader = null, ParserInterface $parser = null, CompilerInterface $compiler = null) + { + $this->loader = $loader; + $this->parser = $parser; + $this->compiler = $compiler; + } + + /** + * Load .env file using loader and parse it + * @param string $filePath + * @return Dotenv + */ + public function load(string $filePath = '.env'): Dotenv + { + $lines = $this->loader->load($filePath); + $rawData = array_map([$this->parser, 'parseLine'], $lines); + $this->compiler->setRawCollection($rawData); + $this->loadedValues = array_reduce( + array_map([$this->compiler, 'compileKeyValue'], $rawData), + function (array $acc, KeyValue $current) { + $acc[$current->getKey()] = $current->getValue(); + return $acc; + }, + [] + ); + + return $this; + } + + /** + * Is key exists + * @param string $key + * @return bool + * @throws RuntimeException + */ + public function has(string $key): bool + { + $this->checkIsLoaded(); + return isset($this->loadedValues[$key]); + } + + /** + * @param string $key + * @param mixed|null $default + * @return mixed + * @throws RuntimeException + */ + public function get(string $key, mixed $default = null): mixed + { + if (!$this->has($key)) { + return $default; + } + return $this->loadedValues[$key]; + } + + /** + * @internal + * @throws RuntimeException + * @return void + */ + protected function checkIsLoaded(): void + { + if (!$this->loadedValues) { + throw new RuntimeException('Dotenv file not loaded'); + } + } + + /** + * @inheritdoc + * @return \ArrayIterator|\Traversable + * @throws RuntimeException + */ + public function getIterator() + { + $this->checkIsLoaded(); + return new \ArrayIterator($this->loadedValues); + } + + /** + * @inheritdoc + * @param string $offset + * @return bool + * @throws RuntimeException + */ + public function offsetExists($offset) + { + return $this->has($offset); + } + + /** + * @inheritdoc + * @param string $offset + * @return mixed + * @throws RuntimeException + */ + public function offsetGet($offset) + { + return $this->get($offset); + } + + /** + * @inheritdoc + * @param string $offset + * @param mixed $value + * @throws RuntimeException + */ + public function offsetSet($offset, $value) + { + throw new RuntimeException('Collection is immutable'); + } + + /** + * @inheritdoc + * @param string $offset + * @throws RuntimeException + */ + public function offsetUnset($offset) + { + throw new RuntimeException('Collection is immutable'); + } + + +} \ No newline at end of file diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php new file mode 100644 index 0000000..1a9be9c --- /dev/null +++ b/src/Exception/RuntimeException.php @@ -0,0 +1,13 @@ + + * @license: MIT + */ + +namespace NeonXP\Dotenv\Exception; + + +class RuntimeException extends \Exception +{ + +} \ No newline at end of file diff --git a/src/Loader/LoaderInterface.php b/src/Loader/LoaderInterface.php new file mode 100644 index 0000000..1c4f166 --- /dev/null +++ b/src/Loader/LoaderInterface.php @@ -0,0 +1,16 @@ + + * @license: MIT + */ + +namespace NeonXP\Dotenv\Loader; + +interface LoaderInterface +{ + /** + * @param string $filePath + * @return string[] + */ + public function load(string $filePath = '.env'): array; +} \ No newline at end of file diff --git a/src/Parser/ParserInterface.php b/src/Parser/ParserInterface.php new file mode 100644 index 0000000..b53e29f --- /dev/null +++ b/src/Parser/ParserInterface.php @@ -0,0 +1,18 @@ + + * @license: MIT + */ + +namespace NeonXP\Dotenv\Parser; + +use NeonXP\Dotenv\Types\KeyValue; + +interface ParserInterface +{ + /** + * @param string $line + * @return KeyValue + */ + public function parseLine(string $line): KeyValue; +} \ No newline at end of file diff --git a/src/Types/KeyValue.php b/src/Types/KeyValue.php new file mode 100644 index 0000000..e17dc4d --- /dev/null +++ b/src/Types/KeyValue.php @@ -0,0 +1,48 @@ + + * @license: MIT + */ + +namespace NeonXP\Dotenv\Types; + + +class KeyValue +{ + /** + * @var string + */ + private $key; + + /** + * @var string + */ + private $value; + + /** + * KeyValue constructor. + * @param string $key + * @param mixed $value + */ + public function __construct(string $key, mixed $value) + { + $this->key = $key; + $this->value = $value; + } + + /** + * @return string + */ + public function getKey(): string + { + return $this->key; + } + + /** + * @return mixed + */ + public function getValue(): mixed + { + return $this->value; + } +} \ No newline at end of file