First commit
This commit is contained in:
commit
d5bb2f19fa
117 changed files with 68604 additions and 0 deletions
22
vendor/yosymfony/toml/src/Exception/DumpException.php
vendored
Normal file
22
vendor/yosymfony/toml/src/Exception/DumpException.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml\Exception;
|
||||
|
||||
/**
|
||||
* Exception class thrown when an error occurs during dumping.
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@gmail.com>
|
||||
*
|
||||
*/
|
||||
class DumpException extends \RuntimeException
|
||||
{
|
||||
}
|
142
vendor/yosymfony/toml/src/Exception/ParseException.php
vendored
Normal file
142
vendor/yosymfony/toml/src/Exception/ParseException.php
vendored
Normal file
|
@ -0,0 +1,142 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml\Exception;
|
||||
|
||||
/**
|
||||
* Exception class thrown when an error occurs during parsing.
|
||||
* Based on ParseException of YAML component from Symfony.
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@gmail.com>
|
||||
*/
|
||||
class ParseException extends \RuntimeException
|
||||
{
|
||||
private $parsedFile;
|
||||
private $parsedLine;
|
||||
private $snippet;
|
||||
private $rawMessage;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $message The error message
|
||||
* @param int $parsedLine The line where the error occurred
|
||||
* @param string|null $snippet The snippet of code near the problem
|
||||
* @param string|null $parsedFile The file name where the error occurred
|
||||
* @param Exception $previous The previous exception
|
||||
*/
|
||||
public function __construct(string $message, int $parsedLine = -1, string $snippet = null, string $parsedFile = null, \Exception $previous = null)
|
||||
{
|
||||
$this->parsedFile = $parsedFile;
|
||||
$this->parsedLine = $parsedLine;
|
||||
$this->snippet = $snippet;
|
||||
$this->rawMessage = $message;
|
||||
|
||||
$this->updateRepr();
|
||||
|
||||
parent::__construct($this->message, 0, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the snippet of code near the error.
|
||||
*
|
||||
* @return string The snippet of code
|
||||
*/
|
||||
public function getSnippet() : string
|
||||
{
|
||||
return $this->snippet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the snippet of code near the error.
|
||||
*
|
||||
* @param string $snippet The code snippet
|
||||
*/
|
||||
public function setSnippet(string $snippet) : void
|
||||
{
|
||||
$this->snippet = $snippet;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filename where the error occurred.
|
||||
*
|
||||
* This method returns null if a string is parsed.
|
||||
*
|
||||
* @return string The filename
|
||||
*/
|
||||
public function getParsedFile() : string
|
||||
{
|
||||
return $this->parsedFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filename where the error occurred.
|
||||
*
|
||||
* @param string $parsedFile The filename
|
||||
*/
|
||||
public function setParsedFile(string $parsedFile) : void
|
||||
{
|
||||
$this->parsedFile = $parsedFile;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the line where the error occurred.
|
||||
*
|
||||
* @return int The file line
|
||||
*/
|
||||
public function getParsedLine() : int
|
||||
{
|
||||
return $this->parsedLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the line where the error occurred.
|
||||
*
|
||||
* @param int $parsedLine The file line
|
||||
*/
|
||||
public function setParsedLine(int $parsedLine) : void
|
||||
{
|
||||
$this->parsedLine = $parsedLine;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
private function updateRepr() : void
|
||||
{
|
||||
$this->message = $this->rawMessage;
|
||||
|
||||
$dot = false;
|
||||
if ('.' === substr($this->message, -1)) {
|
||||
$this->message = substr($this->message, 0, -1);
|
||||
$dot = true;
|
||||
}
|
||||
|
||||
if (null !== $this->parsedFile) {
|
||||
$this->message .= sprintf(' in %s', json_encode($this->parsedFile));
|
||||
}
|
||||
|
||||
if ($this->parsedLine >= 0) {
|
||||
$this->message .= sprintf(' at line %d', $this->parsedLine);
|
||||
}
|
||||
|
||||
if ($this->snippet) {
|
||||
$this->message .= sprintf(' (near "%s")', $this->snippet);
|
||||
}
|
||||
|
||||
if ($dot) {
|
||||
$this->message .= '.';
|
||||
}
|
||||
}
|
||||
}
|
197
vendor/yosymfony/toml/src/KeyStore.php
vendored
Normal file
197
vendor/yosymfony/toml/src/KeyStore.php
vendored
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml;
|
||||
|
||||
/**
|
||||
* Internal class for managing keys (key-values, tables and array of tables)
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@vpgugr.com>
|
||||
*/
|
||||
class KeyStore
|
||||
{
|
||||
private $keys = [];
|
||||
private $tables = [];
|
||||
private $arrayOfTables = [];
|
||||
private $implicitArrayOfTables = [];
|
||||
private $currentTable = '';
|
||||
private $currentArrayOfTable = '';
|
||||
|
||||
public function addKey(string $name) : void
|
||||
{
|
||||
if (!$this->isValidKey($name)) {
|
||||
throw new \LogicException("The key \"{$name}\" is not valid.");
|
||||
}
|
||||
|
||||
$this->keys[] = $this->composeKeyWithCurrentPrefix($name);
|
||||
}
|
||||
|
||||
public function isValidKey(string $name) : bool
|
||||
{
|
||||
$composedKey = $this->composeKeyWithCurrentPrefix($name);
|
||||
|
||||
if (in_array($composedKey, $this->keys, true) === true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function addTableKey(string $name) : void
|
||||
{
|
||||
if (!$this->isValidTableKey($name)) {
|
||||
throw new \LogicException("The table key \"{$name}\" is not valid.");
|
||||
}
|
||||
|
||||
$this->currentTable = '';
|
||||
$this->currentArrayOfTable = $this->getArrayOfTableKeyFromTableKey($name);
|
||||
$this->addkey($name);
|
||||
$this->currentTable = $name;
|
||||
$this->tables[] = $name;
|
||||
}
|
||||
|
||||
public function isValidTableKey($name) : bool
|
||||
{
|
||||
$currentTable = $this->currentTable;
|
||||
$currentArrayOfTable = $this->currentArrayOfTable;
|
||||
|
||||
$this->currentTable = '';
|
||||
$this->currentArrayOfTable = $this->getArrayOfTableKeyFromTableKey($name);
|
||||
|
||||
if ($this->currentArrayOfTable == $name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$isValid = $this->isValidKey($name);
|
||||
$this->currentTable = $currentTable;
|
||||
$this->currentArrayOfTable = $currentArrayOfTable;
|
||||
|
||||
return $isValid;
|
||||
}
|
||||
|
||||
public function isValidInlineTable(string $name): bool
|
||||
{
|
||||
return $this->isValidTableKey($name);
|
||||
}
|
||||
|
||||
public function addInlineTableKey(string $name) : void
|
||||
{
|
||||
$this->addTableKey($name);
|
||||
}
|
||||
|
||||
public function addArrayTableKey(string $name) : void
|
||||
{
|
||||
if (!$this->isValidArrayTableKey($name)) {
|
||||
throw new \LogicException("The array table key \"{$name}\" is not valid.");
|
||||
}
|
||||
|
||||
$this->currentTable = '';
|
||||
$this->currentArrayOfTable = '';
|
||||
|
||||
if (isset($this->arrayOfTables[$name]) === false) {
|
||||
$this->addkey($name);
|
||||
$this->arrayOfTables[$name] = 0;
|
||||
} else {
|
||||
$this->arrayOfTables[$name]++;
|
||||
}
|
||||
|
||||
$this->currentArrayOfTable = $name;
|
||||
$this->processImplicitArrayTableNameIfNeeded($name);
|
||||
}
|
||||
|
||||
public function isValidArrayTableKey(string $name) : bool
|
||||
{
|
||||
$isInArrayOfTables = isset($this->arrayOfTables[$name]);
|
||||
$isInKeys = in_array($name, $this->keys, true);
|
||||
|
||||
if ((!$isInArrayOfTables && !$isInKeys) || ($isInArrayOfTables && $isInKeys)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isRegisteredAsTableKey(string $name) : bool
|
||||
{
|
||||
return in_array($name, $this->tables);
|
||||
}
|
||||
|
||||
public function isRegisteredAsArrayTableKey(string $name) : bool
|
||||
{
|
||||
return isset($this->arrayOfTables[$name]);
|
||||
}
|
||||
|
||||
public function isTableImplicitFromArryTable(string $name) : bool
|
||||
{
|
||||
$isInImplicitArrayOfTables = in_array($name, $this->implicitArrayOfTables);
|
||||
$isInArrayOfTables = isset($this->arrayOfTables[$name]);
|
||||
|
||||
if ($isInImplicitArrayOfTables && !$isInArrayOfTables) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function composeKeyWithCurrentPrefix(string $name) : string
|
||||
{
|
||||
$currentArrayOfTableIndex = '';
|
||||
|
||||
if ($this->currentArrayOfTable != '') {
|
||||
$currentArrayOfTableIndex = (string) $this->arrayOfTables[$this->currentArrayOfTable];
|
||||
}
|
||||
|
||||
return \trim("{$this->currentArrayOfTable}{$currentArrayOfTableIndex}.{$this->currentTable}.{$name}", '.');
|
||||
}
|
||||
|
||||
private function getArrayOfTableKeyFromTableKey(string $name) : string
|
||||
{
|
||||
if (isset($this->arrayOfTables[$name])) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
$keyParts = explode('.', $name);
|
||||
|
||||
if (count($keyParts) === 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
array_pop($keyParts);
|
||||
|
||||
while (count($keyParts) > 0) {
|
||||
$candidateKey = implode('.', $keyParts);
|
||||
|
||||
if (isset($this->arrayOfTables[$candidateKey])) {
|
||||
return $candidateKey;
|
||||
}
|
||||
|
||||
array_pop($keyParts);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function processImplicitArrayTableNameIfNeeded(string $name) : void
|
||||
{
|
||||
$nameParts = explode('.', $name);
|
||||
|
||||
if (count($nameParts) < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
array_pop($nameParts);
|
||||
|
||||
while (count($nameParts) != 0) {
|
||||
$this->implicitArrayOfTables[] = implode('.', $nameParts);
|
||||
array_pop($nameParts);
|
||||
}
|
||||
}
|
||||
}
|
69
vendor/yosymfony/toml/src/Lexer.php
vendored
Normal file
69
vendor/yosymfony/toml/src/Lexer.php
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml;
|
||||
|
||||
use Yosymfony\ParserUtils\BasicLexer;
|
||||
use Yosymfony\ParserUtils\LexerInterface;
|
||||
use Yosymfony\ParserUtils\TokenStream;
|
||||
|
||||
/**
|
||||
* Lexer for Toml strings.
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@vpgugr.com>
|
||||
*/
|
||||
class Lexer implements LexerInterface
|
||||
{
|
||||
private $basicLexer;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->basicLexer = new BasicLexer([
|
||||
'/^(=)/' => 'T_EQUAL',
|
||||
'/^(true|false)/' => 'T_BOOLEAN',
|
||||
'/^(\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{6})?(Z|-\d{2}:\d{2})?)?)/' => 'T_DATE_TIME',
|
||||
'/^([+-]?((((\d_?)+[\.]?(\d_?)*)[eE][+-]?(\d_?)+)|((\d_?)+[\.](\d_?)+)))/' => 'T_FLOAT',
|
||||
'/^([+-]?(\d_?)+)/' => 'T_INTEGER',
|
||||
'/^(""")/' => 'T_3_QUOTATION_MARK',
|
||||
'/^(")/' => 'T_QUOTATION_MARK',
|
||||
"/^(''')/" => 'T_3_APOSTROPHE',
|
||||
"/^(')/" => 'T_APOSTROPHE',
|
||||
'/^(#)/' => 'T_HASH',
|
||||
'/^(\s+)/' => 'T_SPACE',
|
||||
'/^(\[)/' => 'T_LEFT_SQUARE_BRAKET',
|
||||
'/^(\])/' => 'T_RIGHT_SQUARE_BRAKET',
|
||||
'/^(\{)/' => 'T_LEFT_CURLY_BRACE',
|
||||
'/^(\})/' => 'T_RIGHT_CURLY_BRACE',
|
||||
'/^(,)/' => 'T_COMMA',
|
||||
'/^(\.)/' => 'T_DOT',
|
||||
'/^([-A-Z_a-z0-9]+)/' => 'T_UNQUOTED_KEY',
|
||||
'/^(\\\(b|t|n|f|r|"|\\\\|u[0-9AaBbCcDdEeFf]{4,4}|U[0-9AaBbCcDdEeFf]{8,8}))/' => 'T_ESCAPED_CHARACTER',
|
||||
'/^(\\\)/' => 'T_ESCAPE',
|
||||
'/^([\x{20}-\x{21}\x{23}-\x{26}\x{28}-\x{5A}\x{5E}-\x{10FFFF}]+)/u' => 'T_BASIC_UNESCAPED',
|
||||
|
||||
]);
|
||||
|
||||
$this->basicLexer
|
||||
->generateNewlineTokens()
|
||||
->generateEosToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function tokenize(string $input) : TokenStream
|
||||
{
|
||||
return $this->basicLexer->tokenize($input);
|
||||
}
|
||||
}
|
593
vendor/yosymfony/toml/src/Parser.php
vendored
Normal file
593
vendor/yosymfony/toml/src/Parser.php
vendored
Normal file
|
@ -0,0 +1,593 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml;
|
||||
|
||||
use Yosymfony\ParserUtils\AbstractParser;
|
||||
use Yosymfony\ParserUtils\Token;
|
||||
use Yosymfony\ParserUtils\TokenStream;
|
||||
use Yosymfony\ParserUtils\SyntaxErrorException;
|
||||
|
||||
/**
|
||||
* Parser for TOML strings (specification version 0.4.0).
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@vpgugr.com>
|
||||
*/
|
||||
class Parser extends AbstractParser
|
||||
{
|
||||
/** @var KeyStore */
|
||||
private $keyStore;
|
||||
/** @var TomlArray */
|
||||
private $tomlArray;
|
||||
|
||||
private static $tokensNotAllowedInBasicStrings = [
|
||||
'T_ESCAPE',
|
||||
'T_NEWLINE',
|
||||
'T_EOS',
|
||||
];
|
||||
|
||||
private static $tokensNotAllowedInLiteralStrings = [
|
||||
'T_NEWLINE',
|
||||
'T_EOS',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse(string $input)
|
||||
{
|
||||
if (preg_match('//u', $input) === false) {
|
||||
throw new SyntaxErrorException('The TOML input does not appear to be valid UTF-8.');
|
||||
}
|
||||
|
||||
$input = str_replace(["\r\n", "\r"], "\n", $input);
|
||||
$input = str_replace("\t", ' ', $input);
|
||||
|
||||
return parent::parse($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function parseImplementation(TokenStream $ts) : array
|
||||
{
|
||||
$this->keyStore = new KeyStore();
|
||||
$this->tomlArray = new TomlArray();
|
||||
|
||||
while ($ts->hasPendingTokens()) {
|
||||
$this->processExpression($ts);
|
||||
}
|
||||
|
||||
return $this->tomlArray->getArray();
|
||||
}
|
||||
|
||||
private function processExpression(TokenStream $ts) : void
|
||||
{
|
||||
if ($ts->isNext('T_HASH')) {
|
||||
$this->parseComment($ts);
|
||||
} elseif ($ts->isNextAny(['T_QUOTATION_MARK', 'T_UNQUOTED_KEY', 'T_INTEGER'])) {
|
||||
$this->parseKeyValue($ts);
|
||||
} elseif ($ts->isNextSequence(['T_LEFT_SQUARE_BRAKET','T_LEFT_SQUARE_BRAKET'])) {
|
||||
$this->parseArrayOfTables($ts);
|
||||
} elseif ($ts->isNext('T_LEFT_SQUARE_BRAKET')) {
|
||||
$this->parseTable($ts);
|
||||
} elseif ($ts->isNextAny(['T_SPACE','T_NEWLINE', 'T_EOS'])) {
|
||||
$ts->moveNext();
|
||||
} else {
|
||||
$msg = 'Expected T_HASH or T_UNQUOTED_KEY.';
|
||||
$this->unexpectedTokenError($ts->moveNext(), $msg);
|
||||
}
|
||||
}
|
||||
|
||||
private function parseComment(TokenStream $ts) : void
|
||||
{
|
||||
$this->matchNext('T_HASH', $ts);
|
||||
|
||||
while (!$ts->isNextAny(['T_NEWLINE', 'T_EOS'])) {
|
||||
$ts->moveNext();
|
||||
}
|
||||
}
|
||||
|
||||
private function parseKeyValue(TokenStream $ts, bool $isFromInlineTable = false) : void
|
||||
{
|
||||
$keyName = $this->parseKeyName($ts);
|
||||
$this->parseSpaceIfExists($ts);
|
||||
$this->matchNext('T_EQUAL', $ts);
|
||||
$this->parseSpaceIfExists($ts);
|
||||
|
||||
$isInlineTable = $ts->isNext('T_LEFT_CURLY_BRACE');
|
||||
|
||||
if ($isInlineTable) {
|
||||
if (!$this->keyStore->isValidInlineTable($keyName)) {
|
||||
$this->syntaxError("The inline table key \"{$keyName}\" has already been defined previously.");
|
||||
}
|
||||
|
||||
$this->keyStore->addInlineTableKey($keyName);
|
||||
} else {
|
||||
if (!$this->keyStore->isValidKey($keyName)) {
|
||||
$this->syntaxError("The key \"{$keyName}\" has already been defined previously.");
|
||||
}
|
||||
|
||||
$this->keyStore->addKey($keyName);
|
||||
}
|
||||
|
||||
if ($ts->isNext('T_LEFT_SQUARE_BRAKET')) {
|
||||
$this->tomlArray->addKeyValue($keyName, $this->parseArray($ts));
|
||||
} elseif ($isInlineTable) {
|
||||
$this->parseInlineTable($ts, $keyName);
|
||||
} else {
|
||||
$this->tomlArray->addKeyValue($keyName, $this->parseSimpleValue($ts)->value);
|
||||
}
|
||||
|
||||
if (!$isFromInlineTable) {
|
||||
$this->parseSpaceIfExists($ts);
|
||||
$this->parseCommentIfExists($ts);
|
||||
$this->errorIfNextIsNotNewlineOrEOS($ts);
|
||||
}
|
||||
}
|
||||
|
||||
private function parseKeyName(TokenStream $ts) : string
|
||||
{
|
||||
if ($ts->isNext('T_UNQUOTED_KEY')) {
|
||||
return $this->matchNext('T_UNQUOTED_KEY', $ts);
|
||||
}
|
||||
|
||||
if ($ts->isNext('T_INTEGER')) {
|
||||
return $this->parseInteger($ts);
|
||||
}
|
||||
|
||||
return $this->parseBasicString($ts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return object An object with two public properties: value and type.
|
||||
*/
|
||||
private function parseSimpleValue(TokenStream $ts)
|
||||
{
|
||||
if ($ts->isNext('T_BOOLEAN')) {
|
||||
$type = 'boolean';
|
||||
$value = $this->parseBoolean($ts);
|
||||
} elseif ($ts->isNext('T_INTEGER')) {
|
||||
$type = 'integer';
|
||||
$value = $this->parseInteger($ts);
|
||||
} elseif ($ts->isNext('T_FLOAT')) {
|
||||
$type = 'float';
|
||||
$value = $this->parseFloat($ts);
|
||||
} elseif ($ts->isNext('T_QUOTATION_MARK')) {
|
||||
$type = 'string';
|
||||
$value = $this->parseBasicString($ts);
|
||||
} elseif ($ts->isNext('T_3_QUOTATION_MARK')) {
|
||||
$type = 'string';
|
||||
$value = $this->parseMultilineBasicString($ts);
|
||||
} elseif ($ts->isNext('T_APOSTROPHE')) {
|
||||
$type = 'string';
|
||||
$value = $this->parseLiteralString($ts);
|
||||
} elseif ($ts->isNext('T_3_APOSTROPHE')) {
|
||||
$type = 'string';
|
||||
$value = $this->parseMultilineLiteralString($ts);
|
||||
} elseif ($ts->isNext('T_DATE_TIME')) {
|
||||
$type = 'datetime';
|
||||
$value = $this->parseDatetime($ts);
|
||||
} else {
|
||||
$this->unexpectedTokenError(
|
||||
$ts->moveNext(),
|
||||
'Expected boolean, integer, long, string or datetime.'
|
||||
);
|
||||
}
|
||||
|
||||
$valueStruct = new class() {
|
||||
public $value;
|
||||
public $type;
|
||||
};
|
||||
|
||||
$valueStruct->value = $value;
|
||||
$valueStruct->type = $type;
|
||||
|
||||
return $valueStruct;
|
||||
}
|
||||
|
||||
private function parseBoolean(TokenStream $ts) : bool
|
||||
{
|
||||
return $this->matchNext('T_BOOLEAN', $ts) == 'true' ? true : false;
|
||||
}
|
||||
|
||||
private function parseInteger(TokenStream $ts) : int
|
||||
{
|
||||
$token = $ts->moveNext();
|
||||
$value = $token->getValue();
|
||||
|
||||
if (preg_match('/([^\d]_[^\d])|(_$)/', $value)) {
|
||||
$this->syntaxError(
|
||||
'Invalid integer number: underscore must be surrounded by at least one digit.',
|
||||
$token
|
||||
);
|
||||
}
|
||||
|
||||
$value = str_replace('_', '', $value);
|
||||
|
||||
if (preg_match('/^0\d+/', $value)) {
|
||||
$this->syntaxError(
|
||||
'Invalid integer number: leading zeros are not allowed.',
|
||||
$token
|
||||
);
|
||||
}
|
||||
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
private function parseFloat(TokenStream $ts): float
|
||||
{
|
||||
$token = $ts->moveNext();
|
||||
$value = $token->getValue();
|
||||
|
||||
if (preg_match('/([^\d]_[^\d])|_[eE]|[eE]_|(_$)/', $value)) {
|
||||
$this->syntaxError(
|
||||
'Invalid float number: underscore must be surrounded by at least one digit.',
|
||||
$token
|
||||
);
|
||||
}
|
||||
|
||||
$value = str_replace('_', '', $value);
|
||||
|
||||
if (preg_match('/^0\d+/', $value)) {
|
||||
$this->syntaxError(
|
||||
'Invalid float number: leading zeros are not allowed.',
|
||||
$token
|
||||
);
|
||||
}
|
||||
|
||||
return (float) $value;
|
||||
}
|
||||
|
||||
private function parseBasicString(TokenStream $ts): string
|
||||
{
|
||||
$this->matchNext('T_QUOTATION_MARK', $ts);
|
||||
|
||||
$result = '';
|
||||
|
||||
while (!$ts->isNext('T_QUOTATION_MARK')) {
|
||||
if ($ts->isNextAny(self::$tokensNotAllowedInBasicStrings)) {
|
||||
$this->unexpectedTokenError($ts->moveNext(), 'This character is not valid.');
|
||||
}
|
||||
|
||||
$value = $ts->isNext('T_ESCAPED_CHARACTER') ? $this->parseEscapedCharacter($ts) : $ts->moveNext()->getValue();
|
||||
$result .= $value;
|
||||
}
|
||||
|
||||
$this->matchNext('T_QUOTATION_MARK', $ts);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function parseMultilineBasicString(TokenStream $ts) : string
|
||||
{
|
||||
$this->matchNext('T_3_QUOTATION_MARK', $ts);
|
||||
|
||||
$result = '';
|
||||
|
||||
if ($ts->isNext('T_NEWLINE')) {
|
||||
$ts->moveNext();
|
||||
}
|
||||
|
||||
while (!$ts->isNext('T_3_QUOTATION_MARK')) {
|
||||
if ($ts->isNext('T_EOS')) {
|
||||
$this->unexpectedTokenError($ts->moveNext(), 'Expected token "T_3_QUOTATION_MARK".');
|
||||
}
|
||||
|
||||
if ($ts->isNext('T_ESCAPE')) {
|
||||
$ts->skipWhileAny(['T_ESCAPE','T_SPACE', 'T_NEWLINE']);
|
||||
}
|
||||
|
||||
if ($ts->isNext('T_EOS')) {
|
||||
$this->unexpectedTokenError($ts->moveNext(), 'Expected token "T_3_QUOTATION_MARK".');
|
||||
}
|
||||
|
||||
if (!$ts->isNext('T_3_QUOTATION_MARK')) {
|
||||
$value = $ts->isNext('T_ESCAPED_CHARACTER') ? $this->parseEscapedCharacter($ts) : $ts->moveNext()->getValue();
|
||||
$result .= $value;
|
||||
}
|
||||
}
|
||||
|
||||
$this->matchNext('T_3_QUOTATION_MARK', $ts);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function parseLiteralString(TokenStream $ts) : string
|
||||
{
|
||||
$this->matchNext('T_APOSTROPHE', $ts);
|
||||
|
||||
$result = '';
|
||||
|
||||
while (!$ts->isNext('T_APOSTROPHE')) {
|
||||
if ($ts->isNextAny(self::$tokensNotAllowedInLiteralStrings)) {
|
||||
$this->unexpectedTokenError($ts->moveNext(), 'This character is not valid.');
|
||||
}
|
||||
|
||||
$result .= $ts->moveNext()->getValue();
|
||||
}
|
||||
|
||||
$this->matchNext('T_APOSTROPHE', $ts);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function parseMultilineLiteralString(TokenStream $ts) : string
|
||||
{
|
||||
$this->matchNext('T_3_APOSTROPHE', $ts);
|
||||
|
||||
$result = '';
|
||||
|
||||
if ($ts->isNext('T_NEWLINE')) {
|
||||
$ts->moveNext();
|
||||
}
|
||||
|
||||
while (!$ts->isNext('T_3_APOSTROPHE')) {
|
||||
if ($ts->isNext('T_EOS')) {
|
||||
$this->unexpectedTokenError($ts->moveNext(), 'Expected token "T_3_APOSTROPHE".');
|
||||
}
|
||||
|
||||
$result .= $ts->moveNext()->getValue();
|
||||
}
|
||||
|
||||
$this->matchNext('T_3_APOSTROPHE', $ts);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function parseEscapedCharacter(TokenStream $ts) : string
|
||||
{
|
||||
$token = $ts->moveNext();
|
||||
$value = $token->getValue();
|
||||
|
||||
switch ($value) {
|
||||
case '\b':
|
||||
return "\b";
|
||||
case '\t':
|
||||
return "\t";
|
||||
case '\n':
|
||||
return "\n";
|
||||
case '\f':
|
||||
return "\f";
|
||||
case '\r':
|
||||
return "\r";
|
||||
case '\"':
|
||||
return '"';
|
||||
case '\\\\':
|
||||
return '\\';
|
||||
}
|
||||
|
||||
if (strlen($value) === 6) {
|
||||
return json_decode('"'.$value.'"');
|
||||
}
|
||||
|
||||
preg_match('/\\\U([0-9a-fA-F]{4})([0-9a-fA-F]{4})/', $value, $matches);
|
||||
|
||||
return json_decode('"\u'.$matches[1].'\u'.$matches[2].'"');
|
||||
}
|
||||
|
||||
private function parseDatetime(TokenStream $ts) : \Datetime
|
||||
{
|
||||
$date = $this->matchNext('T_DATE_TIME', $ts);
|
||||
|
||||
return new \Datetime($date);
|
||||
}
|
||||
|
||||
private function parseArray(TokenStream $ts) : array
|
||||
{
|
||||
$result = [];
|
||||
$leaderType = '';
|
||||
|
||||
$this->matchNext('T_LEFT_SQUARE_BRAKET', $ts);
|
||||
|
||||
while (!$ts->isNext('T_RIGHT_SQUARE_BRAKET')) {
|
||||
$ts->skipWhileAny(['T_NEWLINE', 'T_SPACE']);
|
||||
$this->parseCommentsInsideBlockIfExists($ts);
|
||||
|
||||
if ($ts->isNext('T_LEFT_SQUARE_BRAKET')) {
|
||||
if ($leaderType === '') {
|
||||
$leaderType = 'array';
|
||||
}
|
||||
|
||||
if ($leaderType !== 'array') {
|
||||
$this->syntaxError(sprintf(
|
||||
'Data types cannot be mixed in an array. Value: "%s".',
|
||||
$valueStruct->value
|
||||
));
|
||||
}
|
||||
|
||||
$result[] = $this->parseArray($ts);
|
||||
} else {
|
||||
$valueStruct = $this->parseSimpleValue($ts);
|
||||
|
||||
if ($leaderType === '') {
|
||||
$leaderType = $valueStruct->type;
|
||||
}
|
||||
|
||||
if ($valueStruct->type !== $leaderType) {
|
||||
$this->syntaxError(sprintf(
|
||||
'Data types cannot be mixed in an array. Value: "%s".',
|
||||
$valueStruct->value
|
||||
));
|
||||
}
|
||||
|
||||
$result[] = $valueStruct->value;
|
||||
}
|
||||
|
||||
$ts->skipWhileAny(['T_NEWLINE', 'T_SPACE']);
|
||||
$this->parseCommentsInsideBlockIfExists($ts);
|
||||
|
||||
if (!$ts->isNext('T_RIGHT_SQUARE_BRAKET')) {
|
||||
$this->matchNext('T_COMMA', $ts);
|
||||
}
|
||||
|
||||
$ts->skipWhileAny(['T_NEWLINE', 'T_SPACE']);
|
||||
$this->parseCommentsInsideBlockIfExists($ts);
|
||||
}
|
||||
|
||||
$this->matchNext('T_RIGHT_SQUARE_BRAKET', $ts);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function parseInlineTable(TokenStream $ts, string $keyName) : void
|
||||
{
|
||||
$this->matchNext('T_LEFT_CURLY_BRACE', $ts);
|
||||
|
||||
$this->tomlArray->beginInlineTableKey($keyName);
|
||||
|
||||
$this->parseSpaceIfExists($ts);
|
||||
|
||||
if (!$ts->isNext('T_RIGHT_CURLY_BRACE')) {
|
||||
$this->parseKeyValue($ts, true);
|
||||
$this->parseSpaceIfExists($ts);
|
||||
}
|
||||
|
||||
while ($ts->isNext('T_COMMA')) {
|
||||
$ts->moveNext();
|
||||
|
||||
$this->parseSpaceIfExists($ts);
|
||||
$this->parseKeyValue($ts, true);
|
||||
$this->parseSpaceIfExists($ts);
|
||||
}
|
||||
|
||||
$this->matchNext('T_RIGHT_CURLY_BRACE', $ts);
|
||||
|
||||
$this->tomlArray->endCurrentInlineTableKey();
|
||||
}
|
||||
|
||||
private function parseTable(TokenStream $ts) : void
|
||||
{
|
||||
$this->matchNext('T_LEFT_SQUARE_BRAKET', $ts);
|
||||
|
||||
$fullTableName = $this->tomlArray->escapeKey($key = $this->parseKeyName($ts));
|
||||
|
||||
while ($ts->isNext('T_DOT')) {
|
||||
$ts->moveNext();
|
||||
|
||||
$key = $this->tomlArray->escapeKey($this->parseKeyName($ts));
|
||||
$fullTableName .= ".$key";
|
||||
}
|
||||
|
||||
if (!$this->keyStore->isValidTableKey($fullTableName)) {
|
||||
$this->syntaxError("The key \"{$fullTableName}\" has already been defined previously.");
|
||||
}
|
||||
|
||||
$this->keyStore->addTableKey($fullTableName);
|
||||
$this->tomlArray->addTableKey($fullTableName);
|
||||
$this->matchNext('T_RIGHT_SQUARE_BRAKET', $ts);
|
||||
|
||||
$this->parseSpaceIfExists($ts);
|
||||
$this->parseCommentIfExists($ts);
|
||||
$this->errorIfNextIsNotNewlineOrEOS($ts);
|
||||
}
|
||||
|
||||
private function parseArrayOfTables(TokenStream $ts) : void
|
||||
{
|
||||
$this->matchNext('T_LEFT_SQUARE_BRAKET', $ts);
|
||||
$this->matchNext('T_LEFT_SQUARE_BRAKET', $ts);
|
||||
|
||||
$fullTableName = $key = $this->tomlArray->escapeKey($this->parseKeyName($ts));
|
||||
|
||||
while ($ts->isNext('T_DOT')) {
|
||||
$ts->moveNext();
|
||||
|
||||
$key = $this->tomlArray->escapeKey($this->parseKeyName($ts));
|
||||
$fullTableName .= ".$key";
|
||||
}
|
||||
|
||||
if (!$this->keyStore->isValidArrayTableKey($fullTableName)) {
|
||||
$this->syntaxError("The key \"{$fullTableName}\" has already been defined previously.");
|
||||
}
|
||||
|
||||
if ($this->keyStore->isTableImplicitFromArryTable($fullTableName)) {
|
||||
$this->syntaxError("The array of tables \"{$fullTableName}\" has already been defined as previous table");
|
||||
}
|
||||
|
||||
$this->keyStore->addArrayTableKey($fullTableName);
|
||||
$this->tomlArray->addArrayTableKey($fullTableName);
|
||||
|
||||
$this->matchNext('T_RIGHT_SQUARE_BRAKET', $ts);
|
||||
$this->matchNext('T_RIGHT_SQUARE_BRAKET', $ts);
|
||||
|
||||
$this->parseSpaceIfExists($ts);
|
||||
$this->parseCommentIfExists($ts);
|
||||
$this->errorIfNextIsNotNewlineOrEOS($ts);
|
||||
}
|
||||
|
||||
private function matchNext(string $tokenName, TokenStream $ts) : string
|
||||
{
|
||||
if (!$ts->isNext($tokenName)) {
|
||||
$this->unexpectedTokenError($ts->moveNext(), "Expected \"$tokenName\".");
|
||||
}
|
||||
|
||||
return $ts->moveNext()->getValue();
|
||||
}
|
||||
|
||||
private function parseSpaceIfExists(TokenStream $ts) : void
|
||||
{
|
||||
if ($ts->isNext('T_SPACE')) {
|
||||
$ts->moveNext();
|
||||
}
|
||||
}
|
||||
|
||||
private function parseCommentIfExists(TokenStream $ts) : void
|
||||
{
|
||||
if ($ts->isNext('T_HASH')) {
|
||||
$this->parseComment($ts);
|
||||
}
|
||||
}
|
||||
|
||||
private function parseCommentsInsideBlockIfExists(TokenStream $ts) : void
|
||||
{
|
||||
$this->parseCommentIfExists($ts);
|
||||
|
||||
while ($ts->isNext('T_NEWLINE')) {
|
||||
$ts->moveNext();
|
||||
$ts->skipWhile('T_SPACE');
|
||||
$this->parseCommentIfExists($ts);
|
||||
}
|
||||
}
|
||||
|
||||
private function errorIfNextIsNotNewlineOrEOS(TokenStream $ts) : void
|
||||
{
|
||||
if (!$ts->isNextAny(['T_NEWLINE', 'T_EOS'])) {
|
||||
$this->unexpectedTokenError($ts->moveNext(), 'Expected T_NEWLINE or T_EOS.');
|
||||
}
|
||||
}
|
||||
|
||||
private function unexpectedTokenError(Token $token, string $expectedMsg) : void
|
||||
{
|
||||
$name = $token->getName();
|
||||
$line = $token->getLine();
|
||||
$value = $token->getValue();
|
||||
$msg = sprintf('Syntax error: unexpected token "%s" at line %s with value "%s".', $name, $line, $value);
|
||||
|
||||
if (!empty($expectedMsg)) {
|
||||
$msg = $msg.' '.$expectedMsg;
|
||||
}
|
||||
|
||||
throw new SyntaxErrorException($msg);
|
||||
}
|
||||
|
||||
private function syntaxError($msg, Token $token = null) : void
|
||||
{
|
||||
if ($token !== null) {
|
||||
$name = $token->getName();
|
||||
$line = $token->getLine();
|
||||
$value = $token->getValue();
|
||||
$tokenMsg = sprintf('Token: "%s" line: %s value "%s".', $name, $line, $value);
|
||||
$msg .= ' '.$tokenMsg;
|
||||
}
|
||||
|
||||
throw new SyntaxErrorException($msg);
|
||||
}
|
||||
}
|
116
vendor/yosymfony/toml/src/Toml.php
vendored
Normal file
116
vendor/yosymfony/toml/src/Toml.php
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml;
|
||||
|
||||
use Yosymfony\ParserUtils\SyntaxErrorException;
|
||||
use Yosymfony\Toml\Exception\ParseException;
|
||||
|
||||
/**
|
||||
* Parser for TOML format.
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@vpgugr.com>
|
||||
*/
|
||||
class Toml
|
||||
{
|
||||
/**
|
||||
* Parses TOML into a PHP array.
|
||||
*
|
||||
* Usage:
|
||||
* <code>
|
||||
* $array = Toml::parse('key = "[1,2,3]"');
|
||||
* print_r($array);
|
||||
* </code>
|
||||
*
|
||||
* @param string $input A string containing TOML
|
||||
* @param bool $resultAsObject (optional) Returns the result as an object
|
||||
*
|
||||
* @return mixed The TOML converted to a PHP value
|
||||
*
|
||||
* @throws ParseException If the TOML is not valid
|
||||
*/
|
||||
public static function parse(string $input, bool $resultAsObject = false)
|
||||
{
|
||||
try {
|
||||
$data = self::doParse($input, $resultAsObject);
|
||||
} catch (SyntaxErrorException $e) {
|
||||
$exception = new ParseException($e->getMessage(), -1, null, null, $e);
|
||||
|
||||
if ($token = $e->getToken()) {
|
||||
$exception->setParsedLine($token->getLine());
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a TOML file into a PHP array.
|
||||
*
|
||||
* Usage:
|
||||
* <code>
|
||||
* $array = Toml::parseFile('config.toml');
|
||||
* print_r($array);
|
||||
* </code>
|
||||
*
|
||||
* @param string $input A string containing TOML
|
||||
* @param bool $resultAsObject (optional) Returns the result as an object
|
||||
*
|
||||
* @return mixed The TOML converted to a PHP value
|
||||
*
|
||||
* @throws ParseException If the TOML file is not valid
|
||||
*/
|
||||
public static function parseFile(string $filename, bool $resultAsObject = false)
|
||||
{
|
||||
if (!is_file($filename)) {
|
||||
throw new ParseException(sprintf('File "%s" does not exist.', $filename));
|
||||
}
|
||||
|
||||
if (!is_readable($filename)) {
|
||||
throw new ParseException(sprintf('File "%s" cannot be read.', $filename));
|
||||
}
|
||||
|
||||
try {
|
||||
$data = self::doParse(file_get_contents($filename), $resultAsObject);
|
||||
} catch (SyntaxErrorException $e) {
|
||||
$exception = new ParseException($e->getMessage());
|
||||
$exception->setParsedFile($filename);
|
||||
|
||||
if ($token = $e->getToken()) {
|
||||
$exception->setParsedLine($token->getLine());
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function doParse(string $input, bool $resultAsObject = false)
|
||||
{
|
||||
$parser = new Parser(new Lexer());
|
||||
$values = $parser->parse($input);
|
||||
|
||||
if ($resultAsObject) {
|
||||
$object = new \stdClass();
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$object->$key = $value;
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
return empty($values) ? null : $values;
|
||||
}
|
||||
}
|
131
vendor/yosymfony/toml/src/TomlArray.php
vendored
Normal file
131
vendor/yosymfony/toml/src/TomlArray.php
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml;
|
||||
|
||||
/**
|
||||
* Internal class for managing a Toml array
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@vpgugr.com>
|
||||
*/
|
||||
class TomlArray
|
||||
{
|
||||
private const DOT_ESCAPED = '%*%';
|
||||
|
||||
private $result = [];
|
||||
private $currentPointer;
|
||||
private $originInlineTableCurrentPointer;
|
||||
private $ArrayTableKeys = [];
|
||||
private $inlineTablePointers = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->resetCurrentPointer();
|
||||
}
|
||||
|
||||
public function addKeyValue(string $name, $value) : Void
|
||||
{
|
||||
$this->currentPointer[$name] = $value;
|
||||
}
|
||||
|
||||
public function addTableKey(string $name) : Void
|
||||
{
|
||||
$this->resetCurrentPointer();
|
||||
$this->goToKey($name);
|
||||
}
|
||||
|
||||
public function beginInlineTableKey(string $name) : Void
|
||||
{
|
||||
$this->inlineTablePointers[] = &$this->currentPointer;
|
||||
$this->goToKey($name);
|
||||
}
|
||||
|
||||
public function endCurrentInlineTableKey() : Void
|
||||
{
|
||||
$indexLastElement = $this->getKeyLastElementOfArray($this->inlineTablePointers);
|
||||
$this->currentPointer = &$this->inlineTablePointers[$indexLastElement];
|
||||
unset($this->inlineTablePointers[$indexLastElement]);
|
||||
}
|
||||
|
||||
public function addArrayTableKey(string $name) : Void
|
||||
{
|
||||
$this->resetCurrentPointer();
|
||||
$this->goToKey($name);
|
||||
$this->currentPointer[] = [];
|
||||
$this->setCurrentPointerToLastElement();
|
||||
|
||||
if (!$this->existsInArrayTableKey($name)) {
|
||||
$this->ArrayTableKeys[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
public function escapeKey(string $name) : string
|
||||
{
|
||||
return \str_replace('.', self::DOT_ESCAPED, $name);
|
||||
}
|
||||
|
||||
public function getArray() : array
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
private function unescapeKey(string $name) : string
|
||||
{
|
||||
return \str_replace(self::DOT_ESCAPED, '.', $name);
|
||||
}
|
||||
|
||||
private function goToKey(string $name) : Void
|
||||
{
|
||||
$keyParts = explode('.', $name);
|
||||
$accumulatedKey = '';
|
||||
$countParts = count($keyParts);
|
||||
|
||||
foreach ($keyParts as $index => $keyPart) {
|
||||
$keyPart = $this->unescapeKey($keyPart);
|
||||
$isLastKeyPart = $index == $countParts -1;
|
||||
$accumulatedKey .= $accumulatedKey == '' ? $keyPart : '.'.$keyPart;
|
||||
|
||||
if (\array_key_exists($keyPart, $this->currentPointer) === false) {
|
||||
$this->currentPointer[$keyPart] = [];
|
||||
}
|
||||
|
||||
$this->currentPointer = &$this->currentPointer[$keyPart];
|
||||
|
||||
if ($this->existsInArrayTableKey($accumulatedKey) && !$isLastKeyPart) {
|
||||
$this->setCurrentPointerToLastElement();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function setCurrentPointerToLastElement() : void
|
||||
{
|
||||
$indexLastElement = $this->getKeyLastElementOfArray($this->currentPointer);
|
||||
$this->currentPointer = &$this->currentPointer[$indexLastElement];
|
||||
}
|
||||
|
||||
private function resetCurrentPointer() : Void
|
||||
{
|
||||
$this->currentPointer = &$this->result;
|
||||
}
|
||||
|
||||
private function existsInArrayTableKey($name) : bool
|
||||
{
|
||||
return \in_array($this->unescapeKey($name), $this->ArrayTableKeys);
|
||||
}
|
||||
|
||||
private function getKeyLastElementOfArray(array &$arr)
|
||||
{
|
||||
end($arr);
|
||||
|
||||
return key($arr);
|
||||
}
|
||||
}
|
425
vendor/yosymfony/toml/src/TomlBuilder.php
vendored
Normal file
425
vendor/yosymfony/toml/src/TomlBuilder.php
vendored
Normal file
|
@ -0,0 +1,425 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Yosymfony\Toml package.
|
||||
*
|
||||
* (c) YoSymfony <http://github.com/yosymfony>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Yosymfony\Toml;
|
||||
|
||||
use Yosymfony\Toml\Exception\DumpException;
|
||||
|
||||
/**
|
||||
* Create inline TOML strings.
|
||||
*
|
||||
* @author Victor Puertas <vpgugr@gmail.com>
|
||||
*
|
||||
* Usage:
|
||||
* <code>
|
||||
* $tomlString = new TomlBuilder()
|
||||
* ->addTable('server.mail')
|
||||
* ->addValue('ip', '192.168.0.1', 'Internal IP')
|
||||
* ->addValue('port', 25)
|
||||
* ->getTomlString();
|
||||
* </code>
|
||||
*/
|
||||
class TomlBuilder
|
||||
{
|
||||
protected $prefix = '';
|
||||
protected $output = '';
|
||||
protected $currentKey;
|
||||
/** @var KeyStore */
|
||||
protected $keyStore;
|
||||
private $currentLine = 0;
|
||||
/** @var array */
|
||||
private static $specialCharacters;
|
||||
/** @var array */
|
||||
private static $escapedSpecialCharacters;
|
||||
private static $specialCharactersMapping = [
|
||||
'\\' => '\\\\',
|
||||
"\b" => '\\b',
|
||||
"\t" => '\\t',
|
||||
"\n" => '\\n',
|
||||
"\f" => '\\f',
|
||||
"\r" => '\\r',
|
||||
'"' => '\\"',
|
||||
];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $indent The amount of spaces to use for indentation of nested nodes
|
||||
*/
|
||||
public function __construct(int $indent = 4)
|
||||
{
|
||||
$this->keyStore = new KeyStore();
|
||||
$this->prefix = $indent ? str_repeat(' ', $indent) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a key value pair
|
||||
*
|
||||
* @param string $key The key name
|
||||
* @param string|int|bool|float|array|Datetime $val The value
|
||||
* @param string $comment Comment (optional argument).
|
||||
*
|
||||
* @return TomlBuilder The TomlBuilder itself
|
||||
*/
|
||||
public function addValue(string $key, $val, string $comment = '') : TomlBuilder
|
||||
{
|
||||
$this->currentKey = $key;
|
||||
$this->exceptionIfKeyEmpty($key);
|
||||
$this->addKey($key);
|
||||
|
||||
if (!$this->isUnquotedKey($key)) {
|
||||
$key = '"'.$key.'"';
|
||||
}
|
||||
|
||||
$line = "{$key} = {$this->dumpValue($val)}";
|
||||
|
||||
if (!empty($comment)) {
|
||||
$line .= ' '.$this->dumpComment($comment);
|
||||
}
|
||||
|
||||
$this->append($line, true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a table.
|
||||
*
|
||||
* @param string $key Table name. Dot character have a special mean. e.g: "fruit.type"
|
||||
*
|
||||
* @return TomlBuilder The TomlBuilder itself
|
||||
*/
|
||||
public function addTable(string $key) : TomlBuilder
|
||||
{
|
||||
$this->exceptionIfKeyEmpty($key);
|
||||
$addPreNewline = $this->currentLine > 0 ? true : false;
|
||||
$keyParts = explode('.', $key);
|
||||
|
||||
foreach ($keyParts as $keyPart) {
|
||||
$this->exceptionIfKeyEmpty($keyPart, "Table: \"{$key}\".");
|
||||
$this->exceptionIfKeyIsNotUnquotedKey($keyPart);
|
||||
}
|
||||
|
||||
$line = "[{$key}]";
|
||||
$this->addTableKey($key);
|
||||
$this->append($line, true, false, $addPreNewline);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method has been marked as deprecated and will be deleted in version 2.0.0
|
||||
* @deprecated 2.0.0 Use the method "addArrayOfTable" instead
|
||||
*/
|
||||
public function addArrayTables(string $key) : TomlBuilder
|
||||
{
|
||||
return $this->addArrayOfTable($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an array of tables element
|
||||
*
|
||||
* @param string $key The name of the array of tables
|
||||
*
|
||||
* @return TomlBuilder The TomlBuilder itself
|
||||
*/
|
||||
public function addArrayOfTable(string $key) : TomlBuilder
|
||||
{
|
||||
$this->exceptionIfKeyEmpty($key);
|
||||
$addPreNewline = $this->currentLine > 0 ? true : false;
|
||||
$keyParts = explode('.', $key);
|
||||
|
||||
foreach ($keyParts as $keyPart) {
|
||||
$this->exceptionIfKeyEmpty($keyPart, "Array of table: \"{$key}\".");
|
||||
$this->exceptionIfKeyIsNotUnquotedKey($keyPart);
|
||||
}
|
||||
|
||||
$line = "[[{$key}]]";
|
||||
$this->addArrayOfTableKey($key);
|
||||
$this->append($line, true, false, $addPreNewline);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comment line
|
||||
*
|
||||
* @param string $comment The comment
|
||||
*
|
||||
* @return TomlBuilder The TomlBuilder itself
|
||||
*/
|
||||
public function addComment(string $comment) : TomlBuilder
|
||||
{
|
||||
$this->append($this->dumpComment($comment), true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the TOML string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTomlString() : string
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the escaped characters for basic strings
|
||||
*/
|
||||
protected function getEscapedCharacters() : array
|
||||
{
|
||||
if (self::$escapedSpecialCharacters !== null) {
|
||||
return self::$escapedSpecialCharacters;
|
||||
}
|
||||
|
||||
return self::$escapedSpecialCharacters = \array_values(self::$specialCharactersMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the special characters for basic strings
|
||||
*/
|
||||
protected function getSpecialCharacters() : array
|
||||
{
|
||||
if (self::$specialCharacters !== null) {
|
||||
return self::$specialCharacters;
|
||||
}
|
||||
|
||||
return self::$specialCharacters = \array_keys(self::$specialCharactersMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a key to the store
|
||||
*
|
||||
* @param string $key The key name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function addKey(string $key) : void
|
||||
{
|
||||
if (!$this->keyStore->isValidKey($key)) {
|
||||
throw new DumpException("The key \"{$key}\" has already been defined previously.");
|
||||
}
|
||||
|
||||
$this->keyStore->addKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a table key to the store
|
||||
*
|
||||
* @param string $key The table key name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function addTableKey(string $key) : void
|
||||
{
|
||||
if (!$this->keyStore->isValidTableKey($key)) {
|
||||
throw new DumpException("The table key \"{$key}\" has already been defined previously.");
|
||||
}
|
||||
|
||||
if ($this->keyStore->isRegisteredAsArrayTableKey($key)) {
|
||||
throw new DumpException("The table \"{$key}\" has already been defined as previous array of tables.");
|
||||
}
|
||||
|
||||
$this->keyStore->addTableKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an array of table key to the store
|
||||
*
|
||||
* @param string $key The key name
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function addArrayOfTableKey(string $key) : void
|
||||
{
|
||||
if (!$this->keyStore->isValidArrayTableKey($key)) {
|
||||
throw new DumpException("The array of table key \"{$key}\" has already been defined previously.");
|
||||
}
|
||||
|
||||
if ($this->keyStore->isTableImplicitFromArryTable($key)) {
|
||||
throw new DumpException("The key \"{$key}\" has been defined as a implicit table from a previous array of tables.");
|
||||
}
|
||||
|
||||
$this->keyStore->addArrayTableKey($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps a value
|
||||
*
|
||||
* @param string|int|bool|float|array|Datetime $val The value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function dumpValue($val) : string
|
||||
{
|
||||
switch (true) {
|
||||
case is_string($val):
|
||||
return $this->dumpString($val);
|
||||
case is_array($val):
|
||||
return $this->dumpArray($val);
|
||||
case is_int($val):
|
||||
return $this->dumpInteger($val);
|
||||
case is_float($val):
|
||||
return $this->dumpFloat($val);
|
||||
case is_bool($val):
|
||||
return $this->dumpBool($val);
|
||||
case $val instanceof \Datetime:
|
||||
return $this->dumpDatetime($val);
|
||||
default:
|
||||
throw new DumpException("Data type not supporter at the key: \"{$this->currentKey}\".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds content to the output
|
||||
*
|
||||
* @param string $val
|
||||
* @param bool $addPostNewline Indicates if add a newline after the value
|
||||
* @param bool $addIndentation Indicates if add indentation to the line
|
||||
* @param bool $addPreNewline Indicates if add a new line before the value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function append(string $val, bool $addPostNewline = false, bool $addIndentation = false, bool $addPreNewline = false) : void
|
||||
{
|
||||
if ($addPreNewline) {
|
||||
$this->output .= "\n";
|
||||
++$this->currentLine;
|
||||
}
|
||||
|
||||
if ($addIndentation) {
|
||||
$val = $this->prefix.$val;
|
||||
}
|
||||
|
||||
$this->output .= $val;
|
||||
|
||||
if ($addPostNewline) {
|
||||
$this->output .= "\n";
|
||||
++$this->currentLine;
|
||||
}
|
||||
}
|
||||
|
||||
private function dumpString(string $val) : string
|
||||
{
|
||||
if ($this->isLiteralString($val)) {
|
||||
return "'".preg_replace('/@/', '', $val, 1)."'";
|
||||
}
|
||||
|
||||
$normalized = $this->normalizeString($val);
|
||||
|
||||
if (!$this->isStringValid($normalized)) {
|
||||
throw new DumpException("The string has an invalid charters at the key \"{$this->currentKey}\".");
|
||||
}
|
||||
|
||||
return '"'.$normalized.'"';
|
||||
}
|
||||
|
||||
private function isLiteralString(string $val) : bool
|
||||
{
|
||||
return strpos($val, '@') === 0;
|
||||
}
|
||||
|
||||
private function dumpBool(bool $val) : string
|
||||
{
|
||||
return $val ? 'true' : 'false';
|
||||
}
|
||||
|
||||
private function dumpArray(array $val) : string
|
||||
{
|
||||
$result = '';
|
||||
$first = true;
|
||||
$dataType = null;
|
||||
$lastType = null;
|
||||
|
||||
foreach ($val as $item) {
|
||||
$lastType = gettype($item);
|
||||
$dataType = $dataType == null ? $lastType : $dataType;
|
||||
|
||||
if ($lastType != $dataType) {
|
||||
throw new DumpException("Data types cannot be mixed in an array. Key: \"{$this->currentKey}\".");
|
||||
}
|
||||
|
||||
$result .= $first ? $this->dumpValue($item) : ', '.$this->dumpValue($item);
|
||||
$first = false;
|
||||
}
|
||||
|
||||
return '['.$result.']';
|
||||
}
|
||||
|
||||
private function dumpComment(string $val) : string
|
||||
{
|
||||
return '#'.$val;
|
||||
}
|
||||
|
||||
private function dumpDatetime(\Datetime $val) : string
|
||||
{
|
||||
return $val->format('Y-m-d\TH:i:s\Z'); // ZULU form
|
||||
}
|
||||
|
||||
private function dumpInteger(int $val) : string
|
||||
{
|
||||
return strval($val);
|
||||
}
|
||||
|
||||
private function dumpFloat(float $val) : string
|
||||
{
|
||||
return strval($val);
|
||||
}
|
||||
|
||||
private function isStringValid(string $val) : bool
|
||||
{
|
||||
$noSpecialCharacter = \str_replace($this->getEscapedCharacters(), '', $val);
|
||||
$noSpecialCharacter = \preg_replace('/\\\\u([0-9a-fA-F]{4})/', '', $noSpecialCharacter);
|
||||
$noSpecialCharacter = \preg_replace('/\\\\u([0-9a-fA-F]{8})/', '', $noSpecialCharacter);
|
||||
|
||||
$pos = strpos($noSpecialCharacter, '\\');
|
||||
|
||||
if ($pos !== false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function normalizeString(string $val) : string
|
||||
{
|
||||
$normalized = \str_replace($this->getSpecialCharacters(), $this->getEscapedCharacters(), $val);
|
||||
|
||||
return $normalized;
|
||||
}
|
||||
|
||||
private function exceptionIfKeyEmpty(string $key, string $additionalMessage = '') : void
|
||||
{
|
||||
$message = 'A key, table name or array of table name cannot be empty or null.';
|
||||
|
||||
if ($additionalMessage != '') {
|
||||
$message .= " {$additionalMessage}";
|
||||
}
|
||||
|
||||
if (empty(trim($key))) {
|
||||
throw new DumpException($message);
|
||||
}
|
||||
}
|
||||
|
||||
private function exceptionIfKeyIsNotUnquotedKey($key) : void
|
||||
{
|
||||
if (!$this->isUnquotedKey($key)) {
|
||||
throw new DumpException("Only unquoted keys are allowed in this implementation. Key: \"{$key}\".");
|
||||
}
|
||||
}
|
||||
|
||||
private function isUnquotedKey(string $key) : bool
|
||||
{
|
||||
return \preg_match('/^([-A-Z_a-z0-9]+)$/', $key) === 1;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue