Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
<?php
/**
* @see https://github.com/zendframework/zend-config for the canonical source repository
* @copyright Copyright (c) 2005-2019 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Config\Reader;
use Zend\Config\Exception;
/**
* INI config reader.
*/
class Ini implements ReaderInterface
{
/**
* Separator for nesting levels of configuration data identifiers.
*
* @var string
*/
protected $nestSeparator = '.';
/**
* Directory of the file to process.
*
* @var string
*/
protected $directory;
/**
* Flag which determines whether sections are processed or not.
*
* @see https://www.php.net/parse_ini_file
* @var bool
*/
protected $processSections = true;
/**
* Set nest separator.
*
* @param string $separator
* @return self
*/
public function setNestSeparator($separator)
{
$this->nestSeparator = $separator;
return $this;
}
/**
* Get nest separator.
*
* @return string
*/
public function getNestSeparator()
{
return $this->nestSeparator;
}
/**
* Marks whether sections should be processed.
* When sections are not processed,section names are stripped and section
* values are merged
*
* @see https://www.php.net/parse_ini_file
* @param bool $processSections
* @return $this
*/
public function setProcessSections($processSections)
{
$this->processSections = (bool) $processSections;
return $this;
}
/**
* Get if sections should be processed
* When sections are not processed,section names are stripped and section
* values are merged
*
* @see https://www.php.net/parse_ini_file
* @return bool
*/
public function getProcessSections()
{
return $this->processSections;
}
/**
* fromFile(): defined by Reader interface.
*
* @see ReaderInterface::fromFile()
* @param string $filename
* @return array
* @throws Exception\RuntimeException
*/
public function fromFile($filename)
{
if (! is_file($filename) || ! is_readable($filename)) {
throw new Exception\RuntimeException(sprintf(
"File '%s' doesn't exist or not readable",
$filename
));
}
$this->directory = dirname($filename);
set_error_handler(
function ($error, $message = '') use ($filename) {
throw new Exception\RuntimeException(
sprintf('Error reading INI file "%s": %s', $filename, $message),
$error
);
},
E_WARNING
);
$ini = parse_ini_file($filename, $this->getProcessSections());
restore_error_handler();
return $this->process($ini);
}
/**
* fromString(): defined by Reader interface.
*
* @param string $string
* @return array|bool
* @throws Exception\RuntimeException
*/
public function fromString($string)
{
if (empty($string)) {
return [];
}
$this->directory = null;
set_error_handler(
function ($error, $message = '') {
throw new Exception\RuntimeException(
sprintf('Error reading INI string: %s', $message),
$error
);
},
E_WARNING
);
$ini = parse_ini_string($string, $this->getProcessSections());
restore_error_handler();
return $this->process($ini);
}
/**
* Process data from the parsed ini file.
*
* @param array $data
* @return array
*/
protected function process(array $data)
{
$config = [];
foreach ($data as $section => $value) {
if (is_array($value)) {
if (strpos($section, $this->nestSeparator) !== false) {
$sections = explode($this->nestSeparator, $section);
$config = array_merge_recursive($config, $this->buildNestedSection($sections, $value));
} else {
$config[$section] = $this->processSection($value);
}
} else {
$this->processKey($section, $value, $config);
}
}
return $config;
}
/**
* Process a nested section
*
* @param array $sections
* @param mixed $value
* @return array
*/
private function buildNestedSection($sections, $value)
{
if (! $sections) {
return $this->processSection($value);
}
$nestedSection = [];
$first = array_shift($sections);
$nestedSection[$first] = $this->buildNestedSection($sections, $value);
return $nestedSection;
}
/**
* Process a section.
*
* @param array $section
* @return array
*/
protected function processSection(array $section)
{
$config = [];
foreach ($section as $key => $value) {
$this->processKey($key, $value, $config);
}
return $config;
}
/**
* Process a key.
*
* @param string $key
* @param string $value
* @param array $config
* @return array
* @throws Exception\RuntimeException
*/
protected function processKey($key, $value, array &$config)
{
if (strpos($key, $this->nestSeparator) !== false) {
$pieces = explode($this->nestSeparator, $key, 2);
if ($pieces[0] === '' || $pieces[1] === '') {
throw new Exception\RuntimeException(sprintf('Invalid key "%s"', $key));
}
if (! isset($config[$pieces[0]])) {
if ($pieces[0] === '0' && ! empty($config)) {
$config = [$pieces[0] => $config];
} else {
$config[$pieces[0]] = [];
}
} elseif (! is_array($config[$pieces[0]])) {
throw new Exception\RuntimeException(
sprintf('Cannot create sub-key for "%s", as key already exists', $pieces[0])
);
}
$this->processKey($pieces[1], $value, $config[$pieces[0]]);
} else {
if ($key === '@include') {
if ($this->directory === null) {
throw new Exception\RuntimeException('Cannot process @include statement for a string config');
}
$reader = clone $this;
$include = $reader->fromFile($this->directory . '/' . $value);
$config = array_replace_recursive($config, $include);
} else {
$config[$key] = $value;
}
}
}
}

View File

@@ -0,0 +1,179 @@
<?php
/**
* @see https://github.com/zendframework/zend-config for the canonical source repository
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Config\Reader;
use Zend\Config\Exception;
/**
* Java-style properties config reader.
*/
class JavaProperties implements ReaderInterface
{
const DELIMITER_DEFAULT = ':';
const WHITESPACE_TRIM = true;
const WHITESPACE_KEEP = false;
/**
* Directory of the Java-style properties file
*
* @var string
*/
protected $directory;
/**
* Delimiter for key/value pairs.
*/
private $delimiter;
/*
* Whether or not to trim whitespace from discovered keys and values.
*
* @var bool
*/
private $trimWhitespace;
/**
* @param string $delimiter Delimiter to use for key/value pairs; defaults
* to self::DELIMITER_DEFAULT (':')
* @param bool $trimWhitespace
* @throws Exception\InvalidArgumentException for invalid $delimiter values.
*/
public function __construct($delimiter = self::DELIMITER_DEFAULT, $trimWhitespace = self::WHITESPACE_KEEP)
{
if (! is_string($delimiter) || '' === $delimiter) {
throw new Exception\InvalidArgumentException(sprintf(
'Invalid delimiter of type "%s"; must be a non-empty string',
is_object($delimiter) ? get_class($delimiter) : gettype($delimiter)
));
}
$this->delimiter = $delimiter;
$this->trimWhitespace = (bool) $trimWhitespace;
}
/**
* fromFile(): defined by Reader interface.
*
* @see ReaderInterface::fromFile()
* @param string $filename
* @return array
* @throws Exception\RuntimeException if the file cannot be read
*/
public function fromFile($filename)
{
if (! is_file($filename) || ! is_readable($filename)) {
throw new Exception\RuntimeException(sprintf(
"File '%s' doesn't exist or not readable",
$filename
));
}
$this->directory = dirname($filename);
$config = $this->parse(file_get_contents($filename));
return $this->process($config);
}
/**
* fromString(): defined by Reader interface.
*
* @see ReaderInterface::fromString()
* @param string $string
* @return array
* @throws Exception\RuntimeException if an @include key is found
*/
public function fromString($string)
{
if (empty($string)) {
return [];
}
$this->directory = null;
$config = $this->parse($string);
return $this->process($config);
}
/**
* Process the array for @include
*
* @param array $data
* @return array
* @throws Exception\RuntimeException if an @include key is found
*/
protected function process(array $data)
{
foreach ($data as $key => $value) {
if (trim($key) === '@include') {
if ($this->directory === null) {
throw new Exception\RuntimeException('Cannot process @include statement for a string');
}
$reader = clone $this;
unset($data[$key]);
$data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value));
}
}
return $data;
}
/**
* Parse Java-style properties string
*
* @todo Support use of the equals sign "key=value" as key-value delimiter
* @todo Ignore whitespace that precedes text past the first line of multiline values
*
* @param string $string
* @return array
*/
protected function parse($string)
{
$delimiter = $this->delimiter;
$delimLength = strlen($delimiter);
$result = [];
$lines = explode("\n", $string);
$key = '';
$isWaitingOtherLine = false;
foreach ($lines as $i => $line) {
// Ignore empty lines and commented lines
if (empty($line)
|| (! $isWaitingOtherLine && strpos($line, "#") === 0)
|| (! $isWaitingOtherLine && strpos($line, "!") === 0)
) {
continue;
}
// Add a new key-value pair or append value to a previous pair
if (! $isWaitingOtherLine) {
$key = substr($line, 0, strpos($line, $delimiter));
$value = substr($line, strpos($line, $delimiter) + $delimLength, strlen($line));
} else {
$value .= $line;
}
// Check if ends with single '\' (indicating another line is expected)
if (strrpos($value, "\\") === strlen($value) - strlen("\\")) {
$value = substr($value, 0, -1);
$isWaitingOtherLine = true;
} else {
$isWaitingOtherLine = false;
}
$key = $this->trimWhitespace ? trim($key) : $key;
$value = $this->trimWhitespace && ! $isWaitingOtherLine
? trim($value)
: $value;
$result[$key] = stripslashes($value);
unset($lines[$i]);
}
return $result;
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* @see https://github.com/zendframework/zend-config for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Config\Reader;
use Zend\Config\Exception;
/**
* JSON config reader.
*/
class Json implements ReaderInterface
{
/**
* Directory of the JSON file
*
* @var string
*/
protected $directory;
/**
* fromFile(): defined by Reader interface.
*
* @see ReaderInterface::fromFile()
* @param string $filename
* @return array
* @throws Exception\RuntimeException
*/
public function fromFile($filename)
{
if (! is_file($filename) || ! is_readable($filename)) {
throw new Exception\RuntimeException(sprintf(
"File '%s' doesn't exist or not readable",
$filename
));
}
$this->directory = dirname($filename);
$config = $this->decode(file_get_contents($filename));
return $this->process($config);
}
/**
* fromString(): defined by Reader interface.
*
* @see ReaderInterface::fromString()
* @param string $string
* @return array|bool
* @throws Exception\RuntimeException
*/
public function fromString($string)
{
if (empty($string)) {
return [];
}
$this->directory = null;
$config = $this->decode($string);
return $this->process($config);
}
/**
* Process the array for @include
*
* @param array $data
* @return array
* @throws Exception\RuntimeException
*/
protected function process(array $data)
{
foreach ($data as $key => $value) {
if (is_array($value)) {
$data[$key] = $this->process($value);
}
if (trim($key) === '@include') {
if ($this->directory === null) {
throw new Exception\RuntimeException('Cannot process @include statement for a JSON string');
}
$reader = clone $this;
unset($data[$key]);
$data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value));
}
}
return $data;
}
/**
* Decode JSON configuration.
*
* Determines if ext/json is present, and, if so, uses that to decode the
* configuration. Otherwise, it uses zend-json, and, if that is missing,
* raises an exception indicating inability to decode.
*
* @param string $data
* @return array
* @throws Exception\RuntimeException for any decoding errors.
*/
private function decode($data)
{
$config = json_decode($data, true);
if (null !== $config && ! is_array($config)) {
throw new Exception\RuntimeException(
'Invalid JSON configuration; did not return an array or object'
);
}
if (null !== $config) {
return $config;
}
if (JSON_ERROR_NONE === json_last_error()) {
return $config;
}
throw new Exception\RuntimeException(json_last_error_msg());
}
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* @see https://github.com/zendframework/zend-config for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Config\Reader;
interface ReaderInterface
{
/**
* Read from a file and create an array
*
* @param string $filename
* @return array
*/
public function fromFile($filename);
/**
* Read from a string and create an array
*
* @param string $string
* @return array|bool
*/
public function fromString($string);
}

View File

@@ -0,0 +1,201 @@
<?php
/**
* @see https://github.com/zendframework/zend-config for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Config\Reader;
use XMLReader;
use Zend\Config\Exception;
/**
* XML config reader.
*/
class Xml implements ReaderInterface
{
/**
* XML Reader instance.
*
* @var XMLReader
*/
protected $reader;
/**
* Directory of the file to process.
*
* @var string
*/
protected $directory;
/**
* Nodes to handle as plain text.
*
* @var array
*/
protected $textNodes = [
XMLReader::TEXT,
XMLReader::CDATA,
XMLReader::WHITESPACE,
XMLReader::SIGNIFICANT_WHITESPACE
];
/**
* fromFile(): defined by Reader interface.
*
* @see ReaderInterface::fromFile()
* @param string $filename
* @return array
* @throws Exception\RuntimeException
*/
public function fromFile($filename)
{
if (! is_file($filename) || ! is_readable($filename)) {
throw new Exception\RuntimeException(sprintf(
"File '%s' doesn't exist or not readable",
$filename
));
}
$this->reader = new XMLReader();
$this->reader->open($filename, null, LIBXML_XINCLUDE);
$this->directory = dirname($filename);
set_error_handler(
function ($error, $message = '') use ($filename) {
throw new Exception\RuntimeException(
sprintf('Error reading XML file "%s": %s', $filename, $message),
$error
);
},
E_WARNING
);
$return = $this->process();
restore_error_handler();
$this->reader->close();
return $return;
}
/**
* fromString(): defined by Reader interface.
*
* @see ReaderInterface::fromString()
* @param string $string
* @return array|bool
* @throws Exception\RuntimeException
*/
public function fromString($string)
{
if (empty($string)) {
return [];
}
$this->reader = new XMLReader();
$this->reader->XML($string, null, LIBXML_XINCLUDE);
$this->directory = null;
set_error_handler(
function ($error, $message = '') {
throw new Exception\RuntimeException(
sprintf('Error reading XML string: %s', $message),
$error
);
},
E_WARNING
);
$return = $this->process();
restore_error_handler();
$this->reader->close();
return $return;
}
/**
* Process data from the created XMLReader.
*
* @return array
*/
protected function process()
{
return $this->processNextElement();
}
/**
* Process the next inner element.
*
* @return mixed
*/
protected function processNextElement()
{
$children = [];
$text = '';
while ($this->reader->read()) {
if ($this->reader->nodeType === XMLReader::ELEMENT) {
if ($this->reader->depth === 0) {
return $this->processNextElement();
}
$attributes = $this->getAttributes();
$name = $this->reader->name;
if ($this->reader->isEmptyElement) {
$child = [];
} else {
$child = $this->processNextElement();
}
if ($attributes) {
if (is_string($child)) {
$child = ['_' => $child];
}
if (! is_array($child)) {
$child = [];
}
$child = array_merge($child, $attributes);
}
if (isset($children[$name])) {
if (! is_array($children[$name]) || ! array_key_exists(0, $children[$name])) {
$children[$name] = [$children[$name]];
}
$children[$name][] = $child;
} else {
$children[$name] = $child;
}
} elseif ($this->reader->nodeType === XMLReader::END_ELEMENT) {
break;
} elseif (in_array($this->reader->nodeType, $this->textNodes)) {
$text .= $this->reader->value;
}
}
return $children ?: $text;
}
/**
* Get all attributes on the current node.
*
* @return array
*/
protected function getAttributes()
{
$attributes = [];
if ($this->reader->hasAttributes) {
while ($this->reader->moveToNextAttribute()) {
$attributes[$this->reader->localName] = $this->reader->value;
}
$this->reader->moveToElement();
}
return $attributes;
}
}

View File

@@ -0,0 +1,157 @@
<?php
/**
* @see https://github.com/zendframework/zend-config for the canonical source repository
* @copyright Copyright (c) 2005-2017 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-config/blob/master/LICENSE.md New BSD License
*/
namespace Zend\Config\Reader;
use Zend\Config\Exception;
/**
* YAML config reader.
*/
class Yaml implements ReaderInterface
{
/**
* Directory of the YAML file
*
* @var string
*/
protected $directory;
/**
* YAML decoder callback
*
* @var callable
*/
protected $yamlDecoder;
/**
* Constructor
*
* @param callable $yamlDecoder
*/
public function __construct($yamlDecoder = null)
{
if ($yamlDecoder !== null) {
$this->setYamlDecoder($yamlDecoder);
} else {
if (function_exists('yaml_parse')) {
$this->setYamlDecoder('yaml_parse');
}
}
}
/**
* Set callback for decoding YAML
*
* @param string|callable $yamlDecoder the decoder to set
* @return self
* @throws Exception\RuntimeException
*/
public function setYamlDecoder($yamlDecoder)
{
if (! is_callable($yamlDecoder)) {
throw new Exception\RuntimeException(
'Invalid parameter to setYamlDecoder() - must be callable'
);
}
$this->yamlDecoder = $yamlDecoder;
return $this;
}
/**
* Get callback for decoding YAML
*
* @return callable
*/
public function getYamlDecoder()
{
return $this->yamlDecoder;
}
/**
* fromFile(): defined by Reader interface.
*
* @see ReaderInterface::fromFile()
* @param string $filename
* @return array
* @throws Exception\RuntimeException
*/
public function fromFile($filename)
{
if (! is_file($filename) || ! is_readable($filename)) {
throw new Exception\RuntimeException(sprintf(
"File '%s' doesn't exist or not readable",
$filename
));
}
if (null === $this->getYamlDecoder()) {
throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder");
}
$this->directory = dirname($filename);
$config = call_user_func($this->getYamlDecoder(), file_get_contents($filename));
if (null === $config) {
throw new Exception\RuntimeException("Error parsing YAML data");
}
return $this->process($config);
}
/**
* fromString(): defined by Reader interface.
*
* @see ReaderInterface::fromString()
* @param string $string
* @return array|bool
* @throws Exception\RuntimeException
*/
public function fromString($string)
{
if (null === $this->getYamlDecoder()) {
throw new Exception\RuntimeException("You didn't specify a Yaml callback decoder");
}
if (empty($string)) {
return [];
}
$this->directory = null;
$config = call_user_func($this->getYamlDecoder(), $string);
if (null === $config) {
throw new Exception\RuntimeException("Error parsing YAML data");
}
return $this->process($config);
}
/**
* Process the array for @include
*
* @param array $data
* @return array
* @throws Exception\RuntimeException
*/
protected function process(array $data)
{
foreach ($data as $key => $value) {
if (is_array($value)) {
$data[$key] = $this->process($value);
}
if (trim($key) === '@include') {
if ($this->directory === null) {
throw new Exception\RuntimeException('Cannot process @include statement for a json string');
}
$reader = clone $this;
unset($data[$key]);
$data = array_replace_recursive($data, $reader->fromFile($this->directory . '/' . $value));
}
}
return $data;
}
}