diff --git a/src/Symfony/Component/Dotenv/CHANGELOG.md b/src/Symfony/Component/Dotenv/CHANGELOG.md index f04cc1bdf7bba..77d857f6f7e72 100644 --- a/src/Symfony/Component/Dotenv/CHANGELOG.md +++ b/src/Symfony/Component/Dotenv/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.1.0 +----- + + * Support array notation + 3.3.0 ----- diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 29e3daab04a8e..e6d96e597d574 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -27,6 +27,7 @@ final class Dotenv const VARNAME_REGEX = '(?i:[A-Z][A-Z0-9_]*+)'; const STATE_VARNAME = 0; const STATE_VALUE = 1; + const STATE_KEY = 2; private $path; private $cursor; @@ -114,6 +115,7 @@ public function parse(string $data, string $path = '.env'): array $this->state = self::STATE_VARNAME; $this->values = array(); $name = ''; + $key = null; $this->skipEmptyLines(); @@ -121,18 +123,31 @@ public function parse(string $data, string $path = '.env'): array switch ($this->state) { case self::STATE_VARNAME: $name = $this->lexVarname(); + + if ('[' === $this->data[$this->cursor]) { + $this->state = self::STATE_KEY; + } else { + $this->state = self::STATE_VALUE; + ++$this->cursor; + } + + break; + + case self::STATE_KEY: + $key = $this->lexKey(); $this->state = self::STATE_VALUE; break; case self::STATE_VALUE: - $this->values[$name] = $this->lexValue(); + $value = $this->lexValue(); + $this->setValue($name, $key, $value); $this->state = self::STATE_VARNAME; break; } } if (self::STATE_VALUE === $this->state) { - $this->values[$name] = ''; + $this->setValue($name, $key, ''); } try { @@ -164,12 +179,27 @@ private function lexVarname() throw $this->createFormatException('Whitespace are not supported after the variable name'); } + if ('=' !== $this->data[$this->cursor] && '[' !== $this->data[$this->cursor]) { + throw $this->createFormatException('Missing = in the environment variable declaration'); + } + + return $matches[2]; + } + + private function lexKey() + { + if (!preg_match('/\[(.*?)\]/', $this->data, $matches, 0, $this->cursor)) { + throw $this->createFormatException('Invalid character in variable name'); + return; + } + $this->moveCursor($matches[0]); + if ('=' !== $this->data[$this->cursor]) { throw $this->createFormatException('Missing = in the environment variable declaration'); } ++$this->cursor; - return $matches[2]; + return $matches[1]; } private function lexValue() @@ -399,4 +429,21 @@ private function createFormatException($message) { return new FormatException($message, new FormatExceptionContext($this->data, $this->path, $this->lineno, $this->cursor)); } + + private function setValue($name, $key, $value) + { + if (null === $key) { + $this->values[$name] = $value; + } else { + if (!isset($this->values[$name])) { + $this->values[$name] = array(); + } + + if ('' === $key) { + $this->values[$name][] = $value; + } else { + $this->values[$name][$key] = $value; + } + } + } } diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index ce7d3a93396b2..d3cfa57806f69 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -137,6 +137,12 @@ public function getEnvData() array('BAR=$LOCAL', array('BAR' => 'local')), array('BAR=$REMOTE', array('BAR' => 'remote')), array('FOO=$NOTDEFINED', array('FOO' => '')), + + // array + array('FOO[]=', array('FOO' => array(''))), + array('FOO[]=BAR', array('FOO' => array('BAR'))), + array("FOO[]=BAR\nFOO[]=BAZ", array('FOO' => array('BAR', 'BAZ'))), + array("FOO[bar]=BAR\nFOO[baz]=BAZ", array('FOO' => array('bar' => 'BAR', 'baz' => 'BAZ'))), ); if ('\\' !== DIRECTORY_SEPARATOR) {
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: