관리-도구
편집 파일: phpdotenv.tar
LICENSE.txt 0000604 00000003015 15224651653 0006373 0 ustar 00 The BSD 3-Clause License http://opensource.org/licenses/BSD-3-Clause Copyright (c) 2013, Vance Lucas All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Vance Lucas nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. src/Validator.php 0000604 00000006150 15224651653 0010000 0 ustar 00 <?php namespace Dotenv; use Dotenv\Exception\InvalidCallbackException; use Dotenv\Exception\ValidationException; /** * This is the validator class. * * It's responsible for applying validations against a number of variables. */ class Validator { /** * The variables to validate. * * @var array */ protected $variables; /** * The loader instance. * * @var \Dotenv\Loader */ protected $loader; /** * Create a new validator instance. * * @param array $variables * @param \Dotenv\Loader $loader * * @return void */ public function __construct(array $variables, Loader $loader) { $this->variables = $variables; $this->loader = $loader; $this->assertCallback( function ($value) { return $value !== null; }, 'is missing' ); } /** * Assert that each variable is not empty. * * @return \Dotenv\Validator */ public function notEmpty() { return $this->assertCallback( function ($value) { return strlen(trim($value)) > 0; }, 'is empty' ); } /** * Assert that each specified variable is an integer. * * @return \Dotenv\Validator */ public function isInteger() { return $this->assertCallback( function ($value) { return ctype_digit($value); }, 'is not an integer' ); } /** * Assert that each variable is amongst the given choices. * * @param string[] $choices * * @return \Dotenv\Validator */ public function allowedValues(array $choices) { return $this->assertCallback( function ($value) use ($choices) { return in_array($value, $choices); }, 'is not an allowed value' ); } /** * Assert that the callback returns true for each variable. * * @param callable $callback * @param string $message * * @throws \Dotenv\Exception\InvalidCallbackException|\Dotenv\Exception\ValidationException * * @return \Dotenv\Validator */ protected function assertCallback($callback, $message = 'failed callback assertion') { if (!is_callable($callback)) { throw new InvalidCallbackException('The provided callback must be callable.'); } $variablesFailingAssertion = array(); foreach ($this->variables as $variableName) { $variableValue = $this->loader->getEnvironmentVariable($variableName); if (call_user_func($callback, $variableValue) === false) { $variablesFailingAssertion[] = $variableName." $message"; } } if (count($variablesFailingAssertion) > 0) { throw new ValidationException(sprintf( 'One or more environment variables failed assertions: %s.', implode(', ', $variablesFailingAssertion) )); } return $this; } } src/Exception/InvalidFileException.php 0000604 00000000335 15224651653 0014055 0 ustar 00 <?php namespace Dotenv\Exception; use InvalidArgumentException; /** * This is the invalid file exception class. */ class InvalidFileException extends InvalidArgumentException implements ExceptionInterface { // } src/Exception/ExceptionInterface.php 0000604 00000000170 15224651653 0013564 0 ustar 00 <?php namespace Dotenv\Exception; /** * This is the exception interface. */ interface ExceptionInterface { // } src/Exception/InvalidPathException.php 0000604 00000000335 15224651653 0014072 0 ustar 00 <?php namespace Dotenv\Exception; use InvalidArgumentException; /** * This is the invalid path exception class. */ class InvalidPathException extends InvalidArgumentException implements ExceptionInterface { // } src/Exception/ValidationException.php 0000604 00000000312 15224651653 0013754 0 ustar 00 <?php namespace Dotenv\Exception; use RuntimeException; /** * This is the validation exception class. */ class ValidationException extends RuntimeException implements ExceptionInterface { // } src/Exception/InvalidCallbackException.php 0000604 00000000345 15224651653 0014673 0 ustar 00 <?php namespace Dotenv\Exception; use InvalidArgumentException; /** * This is the invalid callback exception class. */ class InvalidCallbackException extends InvalidArgumentException implements ExceptionInterface { // } src/Loader.php 0000604 00000024601 15224651653 0007262 0 ustar 00 <?php namespace Dotenv; use Dotenv\Exception\InvalidFileException; use Dotenv\Exception\InvalidPathException; /** * This is the loaded class. * * It's responsible for loading variables by reading a file from disk and: * - stripping comments beginning with a `#`, * - parsing lines that look shell variable setters, e.g `export key = value`, `key="value"`. */ class Loader { /** * The file path. * * @var string */ protected $filePath; /** * Are we immutable? * * @var bool */ protected $immutable; /** * Create a new loader instance. * * @param string $filePath * @param bool $immutable * * @return void */ public function __construct($filePath, $immutable = false) { $this->filePath = $filePath; $this->immutable = $immutable; } /** * Load `.env` file in given directory. * * @return array */ public function load() { $this->ensureFileIsReadable(); $filePath = $this->filePath; $lines = $this->readLinesFromFile($filePath); foreach ($lines as $line) { if (!$this->isComment($line) && $this->looksLikeSetter($line)) { $this->setEnvironmentVariable($line); } } return $lines; } /** * Ensures the given filePath is readable. * * @throws \Dotenv\Exception\InvalidPathException * * @return void */ protected function ensureFileIsReadable() { if (!is_readable($this->filePath) || !is_file($this->filePath)) { throw new InvalidPathException(sprintf('Unable to read the environment file at %s.', $this->filePath)); } } /** * Normalise the given environment variable. * * Takes value as passed in by developer and: * - ensures we're dealing with a separate name and value, breaking apart the name string if needed, * - cleaning the value of quotes, * - cleaning the name of quotes, * - resolving nested variables. * * @param string $name * @param string $value * * @return array */ protected function normaliseEnvironmentVariable($name, $value) { list($name, $value) = $this->splitCompoundStringIntoParts($name, $value); list($name, $value) = $this->sanitiseVariableName($name, $value); list($name, $value) = $this->sanitiseVariableValue($name, $value); $value = $this->resolveNestedVariables($value); return array($name, $value); } /** * Process the runtime filters. * * Called from the `VariableFactory`, passed as a callback in `$this->loadFromFile()`. * * @param string $name * @param string $value * * @return array */ public function processFilters($name, $value) { list($name, $value) = $this->splitCompoundStringIntoParts($name, $value); list($name, $value) = $this->sanitiseVariableName($name, $value); list($name, $value) = $this->sanitiseVariableValue($name, $value); return array($name, $value); } /** * Read lines from the file, auto detecting line endings. * * @param string $filePath * * @return array */ protected function readLinesFromFile($filePath) { // Read file into an array of lines with auto-detected line endings $autodetect = ini_get('auto_detect_line_endings'); ini_set('auto_detect_line_endings', '1'); $lines = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); ini_set('auto_detect_line_endings', $autodetect); return $lines; } /** * Determine if the line in the file is a comment, e.g. begins with a #. * * @param string $line * * @return bool */ protected function isComment($line) { return strpos(ltrim($line), '#') === 0; } /** * Determine if the given line looks like it's setting a variable. * * @param string $line * * @return bool */ protected function looksLikeSetter($line) { return strpos($line, '=') !== false; } /** * Split the compound string into parts. * * If the `$name` contains an `=` sign, then we split it into 2 parts, a `name` & `value` * disregarding the `$value` passed in. * * @param string $name * @param string $value * * @return array */ protected function splitCompoundStringIntoParts($name, $value) { if (strpos($name, '=') !== false) { list($name, $value) = array_map('trim', explode('=', $name, 2)); } return array($name, $value); } /** * Strips quotes from the environment variable value. * * @param string $name * @param string $value * * @throws \Dotenv\Exception\InvalidFileException * * @return array */ protected function sanitiseVariableValue($name, $value) { $value = trim($value); if (!$value) { return array($name, $value); } if ($this->beginsWithAQuote($value)) { // value starts with a quote $quote = $value[0]; $regexPattern = sprintf( '/^ %1$s # match a quote at the start of the value ( # capturing sub-pattern used (?: # we do not need to capture this [^%1$s\\\\] # any character other than a quote or backslash |\\\\\\\\ # or two backslashes together |\\\\%1$s # or an escaped quote e.g \" )* # as many characters that match the previous rules ) # end of the capturing sub-pattern %1$s # and the closing quote .*$ # and discard any string after the closing quote /mx', $quote ); $value = preg_replace($regexPattern, '$1', $value); $value = str_replace("\\$quote", $quote, $value); $value = str_replace('\\\\', '\\', $value); } else { $parts = explode(' #', $value, 2); $value = trim($parts[0]); // Unquoted values cannot contain whitespace if (preg_match('/\s+/', $value) > 0) { throw new InvalidFileException('Dotenv values containing spaces must be surrounded by quotes.'); } } return array($name, trim($value)); } /** * Resolve the nested variables. * * Look for {$varname} patterns in the variable value and replace with an * existing environment variable. * * @param string $value * * @return mixed */ protected function resolveNestedVariables($value) { if (strpos($value, '$') !== false) { $loader = $this; $value = preg_replace_callback( '/\${([a-zA-Z0-9_]+)}/', function ($matchedPatterns) use ($loader) { $nestedVariable = $loader->getEnvironmentVariable($matchedPatterns[1]); if ($nestedVariable === null) { return $matchedPatterns[0]; } else { return $nestedVariable; } }, $value ); } return $value; } /** * Strips quotes and the optional leading "export " from the environment variable name. * * @param string $name * @param string $value * * @return array */ protected function sanitiseVariableName($name, $value) { $name = trim(str_replace(array('export ', '\'', '"'), '', $name)); return array($name, $value); } /** * Determine if the given string begins with a quote. * * @param string $value * * @return bool */ protected function beginsWithAQuote($value) { return strpbrk($value[0], '"\'') !== false; } /** * Search the different places for environment variables and return first value found. * * @param string $name * * @return string|null */ public function getEnvironmentVariable($name) { switch (true) { case array_key_exists($name, $_ENV): return $_ENV[$name]; case array_key_exists($name, $_SERVER): return $_SERVER[$name]; default: $value = getenv($name); return $value === false ? null : $value; // switch getenv default to null } } /** * Set an environment variable. * * This is done using: * - putenv, * - $_ENV, * - $_SERVER. * * The environment variable value is stripped of single and double quotes. * * @param string $name * @param string|null $value * * @return void */ public function setEnvironmentVariable($name, $value = null) { list($name, $value) = $this->normaliseEnvironmentVariable($name, $value); // Don't overwrite existing environment variables if we're immutable // Ruby's dotenv does this with `ENV[key] ||= value`. if ($this->immutable && $this->getEnvironmentVariable($name) !== null) { return; } // If PHP is running as an Apache module and an existing // Apache environment variable exists, overwrite it if (function_exists('apache_getenv') && function_exists('apache_setenv') && apache_getenv($name)) { apache_setenv($name, $value); } if (function_exists('putenv')) { putenv("$name=$value"); } $_ENV[$name] = $value; $_SERVER[$name] = $value; } /** * Clear an environment variable. * * This is not (currently) used by Dotenv but is provided as a utility * method for 3rd party code. * * This is done using: * - putenv, * - unset($_ENV, $_SERVER). * * @param string $name * * @see setEnvironmentVariable() * * @return void */ public function clearEnvironmentVariable($name) { // Don't clear anything if we're immutable. if ($this->immutable) { return; } if (function_exists('putenv')) { putenv($name); } unset($_ENV[$name], $_SERVER[$name]); } } src/Dotenv.php 0000604 00000003770 15224651653 0007317 0 ustar 00 <?php namespace Dotenv; /** * This is the dotenv class. * * It's responsible for loading a `.env` file in the given directory and * setting the environment vars. */ class Dotenv { /** * The file path. * * @var string */ protected $filePath; /** * The loader instance. * * @var \Dotenv\Loader|null */ protected $loader; /** * Create a new dotenv instance. * * @param string $path * @param string $file * * @return void */ public function __construct($path, $file = '.env') { $this->filePath = $this->getFilePath($path, $file); $this->loader = new Loader($this->filePath, true); } /** * Load environment file in given directory. * * @return array */ public function load() { return $this->loadData(); } /** * Load environment file in given directory. * * @return array */ public function overload() { return $this->loadData(true); } /** * Returns the full path to the file. * * @param string $path * @param string $file * * @return string */ protected function getFilePath($path, $file) { if (!is_string($file)) { $file = '.env'; } $filePath = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$file; return $filePath; } /** * Actually load the data. * * @param bool $overload * * @return array */ protected function loadData($overload = false) { $this->loader = new Loader($this->filePath, !$overload); return $this->loader->load(); } /** * Required ensures that the specified variables exist, and returns a new validator object. * * @param string|string[] $variable * * @return \Dotenv\Validator */ public function required($variable) { return new Validator((array) $variable, $this->loader); } } composer.json 0000604 00000001317 15224651653 0007275 0 ustar 00 { "name": "vlucas/phpdotenv", "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", "keywords": ["env", "dotenv", "environment"], "license" : "BSD-3-Clause-Attribution", "authors" : [ { "name": "Vance Lucas", "email": "vance@vancelucas.com", "homepage": "http://www.vancelucas.com" } ], "require": { "php": ">=5.3.9" }, "require-dev": { "phpunit/phpunit": "^4.8 || ^5.0" }, "autoload": { "psr-4": { "Dotenv\\": "src/" } }, "extra": { "branch-alias": { "dev-master": "2.4-dev" } } }