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,56 @@
<?php
/**
* This file is part of the League.csv library
*
* @license http://opensource.org/licenses/MIT
* @link https://github.com/thephpleague/csv/
* @version 8.2.3
* @package League.csv
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Csv\Modifier;
use Iterator;
use IteratorIterator;
/**
* A simple MapIterator
*
* @package League.csv
* @since 3.3.0
* @internal used internally to modify CSV content
*
*/
class MapIterator extends IteratorIterator
{
/**
* The function to be apply on all InnerIterator element
*
* @var callable
*/
private $callable;
/**
* The Constructor
*
* @param Iterator $iterator
* @param callable $callable
*/
public function __construct(Iterator $iterator, callable $callable)
{
parent::__construct($iterator);
$this->callable = $callable;
}
/**
* Get the value of the current element
*/
public function current()
{
$iterator = $this->getInnerIterator();
return call_user_func($this->callable, $iterator->current(), $iterator->key(), $iterator);
}
}

View File

@@ -0,0 +1,298 @@
<?php
/**
* This file is part of the League.csv library
*
* @license http://opensource.org/licenses/MIT
* @link https://github.com/thephpleague/csv/
* @version 8.2.3
* @package League.csv
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Csv\Modifier;
use ArrayIterator;
use CallbackFilterIterator;
use Iterator;
use LimitIterator;
/**
* A Trait to Query rows against a SplFileObject
*
* @package League.csv
* @since 4.2.1
*
*/
trait QueryFilter
{
/**
* Callables to filter the iterator
*
* @var callable[]
*/
protected $iterator_filters = [];
/**
* Callables to sort the iterator
*
* @var callable[]
*/
protected $iterator_sort_by = [];
/**
* iterator Offset
*
* @var int
*/
protected $iterator_offset = 0;
/**
* iterator maximum length
*
* @var int
*/
protected $iterator_limit = -1;
/**
* Stripping BOM status
*
* @var boolean
*/
protected $strip_bom = false;
/**
* Stripping BOM setter
*
* @param bool $status
*
* @return $this
*/
public function stripBom($status)
{
$this->strip_bom = (bool) $status;
return $this;
}
/**
* @inheritdoc
*/
abstract public function getInputBOM();
/**
* Set LimitIterator Offset
*
* @param $offset
*
* @return $this
*/
public function setOffset($offset = 0)
{
$this->iterator_offset = $this->validateInteger($offset, 0, 'the offset must be a positive integer or 0');
return $this;
}
/**
* @inheritdoc
*/
abstract protected function validateInteger($int, $minValue, $errorMessage);
/**
* Set LimitIterator Count
*
* @param int $limit
*
* @return $this
*/
public function setLimit($limit = -1)
{
$this->iterator_limit = $this->validateInteger($limit, -1, 'the limit must an integer greater or equals to -1');
return $this;
}
/**
* Set an Iterator sorting callable function
*
* @param callable $callable
*
* @return $this
*/
public function addSortBy(callable $callable)
{
$this->iterator_sort_by[] = $callable;
return $this;
}
/**
* Set the Iterator filter method
*
* @param callable $callable
*
* @return $this
*/
public function addFilter(callable $callable)
{
$this->iterator_filters[] = $callable;
return $this;
}
/**
* @inheritdoc
*/
abstract public function getEnclosure();
/**
* Returns the CSV Iterator
*
* @return Iterator
*/
protected function getQueryIterator()
{
$normalizedCsv = function ($row) {
return is_array($row) && $row != [null];
};
array_unshift($this->iterator_filters, $normalizedCsv);
$iterator = $this->getIterator();
$iterator = $this->applyBomStripping($iterator);
$iterator = $this->applyIteratorFilter($iterator);
$iterator = $this->applyIteratorSortBy($iterator);
$iterator = $this->applyIteratorInterval($iterator);
return $iterator;
}
/**
* @inheritdoc
*/
abstract public function getIterator();
/**
* Remove the BOM sequence from the CSV
*
* @param Iterator $iterator
*
* @return Iterator
*/
protected function applyBomStripping(Iterator $iterator)
{
if (!$this->strip_bom) {
return $iterator;
}
if (!$this->isBomStrippable()) {
$this->strip_bom = false;
return $iterator;
}
$this->strip_bom = false;
return $this->getStripBomIterator($iterator);
}
/**
* Tell whether we can strip or not the leading BOM sequence
*
* @return bool
*/
protected function isBomStrippable()
{
return !empty($this->getInputBOM()) && $this->strip_bom;
}
/**
* Return the Iterator without the BOM sequence
*
* @param Iterator $iterator
*
* @return Iterator
*/
protected function getStripBomIterator(Iterator $iterator)
{
$bom_length = mb_strlen($this->getInputBOM());
$enclosure = $this->getEnclosure();
$strip_bom = function ($row, $index) use ($bom_length, $enclosure) {
if (0 != $index) {
return $row;
}
$row[0] = mb_substr($row[0], $bom_length);
if (mb_substr($row[0], 0, 1) === $enclosure && mb_substr($row[0], -1, 1) === $enclosure) {
$row[0] = mb_substr($row[0], 1, -1);
}
return $row;
};
return new MapIterator($iterator, $strip_bom);
}
/**
* Filter the Iterator
*
* @param Iterator $iterator
*
* @return Iterator
*/
protected function applyIteratorFilter(Iterator $iterator)
{
$reducer = function ($iterator, $callable) {
return new CallbackFilterIterator($iterator, $callable);
};
$iterator = array_reduce($this->iterator_filters, $reducer, $iterator);
$this->iterator_filters = [];
return $iterator;
}
/**
* Sort the Iterator
*
* @param Iterator $iterator
*
* @return Iterator
*/
protected function applyIteratorSortBy(Iterator $iterator)
{
if (!$this->iterator_sort_by) {
return $iterator;
}
$obj = new ArrayIterator(iterator_to_array($iterator));
$obj->uasort(function ($row_a, $row_b) {
$res = 0;
foreach ($this->iterator_sort_by as $compare) {
if (0 !== ($res = call_user_func($compare, $row_a, $row_b))) {
break;
}
}
return $res;
});
$this->iterator_sort_by = [];
return $obj;
}
/**
* Sort the Iterator
*
* @param Iterator $iterator
*
* @return Iterator
*/
protected function applyIteratorInterval(Iterator $iterator)
{
$offset = $this->iterator_offset;
$limit = $this->iterator_limit;
$this->iterator_limit = -1;
$this->iterator_offset = 0;
return new LimitIterator($iterator, $offset, $limit);
}
}

View File

@@ -0,0 +1,187 @@
<?php
/**
* This file is part of the League.csv library
*
* @license http://opensource.org/licenses/MIT
* @link https://github.com/thephpleague/csv/
* @version 8.2.3
* @package League.csv
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Csv\Modifier;
use League\Csv\Exception\InvalidRowException;
/**
* Trait to format and validate the row before insertion
*
* @package League.csv
* @since 7.0.0
*
*/
trait RowFilter
{
/**
* Callables to validate the row before insertion
*
* @var callable[]
*/
protected $validators = [];
/**
* Callables to format the row before insertion
*
* @var callable[]
*/
protected $formatters = [];
/**
* add a formatter to the collection
*
* @param callable $callable
*
* @return $this
*/
public function addFormatter(callable $callable)
{
$this->formatters[] = $callable;
return $this;
}
/**
* Remove a formatter from the collection
*
* @param callable $callable
*
* @return $this
*/
public function removeFormatter(callable $callable)
{
$res = array_search($callable, $this->formatters, true);
unset($this->formatters[$res]);
return $this;
}
/**
* Detect if the formatter is already registered
*
* @param callable $callable
*
* @return bool
*/
public function hasFormatter(callable $callable)
{
return false !== array_search($callable, $this->formatters, true);
}
/**
* Remove all registered formatter
*
* @return $this
*/
public function clearFormatters()
{
$this->formatters = [];
return $this;
}
/**
* add a Validator to the collection
*
* @param callable $callable
* @param string $name the rule name
*
* @return $this
*/
public function addValidator(callable $callable, $name)
{
$name = $this->validateString($name);
$this->validators[$name] = $callable;
return $this;
}
/**
* @inheritdoc
*/
abstract protected function validateString($str);
/**
* Remove a validator from the collection
*
* @param string $name the validator name
*
* @return $this
*/
public function removeValidator($name)
{
$name = $this->validateString($name);
unset($this->validators[$name]);
return $this;
}
/**
* Detect if a validator is already registered
*
* @param string $name the validator name
*
* @return bool
*/
public function hasValidator($name)
{
$name = $this->validateString($name);
return isset($this->validators[$name]);
}
/**
* Remove all registered validators
*
* @return $this
*/
public function clearValidators()
{
$this->validators = [];
return $this;
}
/**
* Format the given row
*
* @param array $row
*
* @return array
*/
protected function formatRow(array $row)
{
foreach ($this->formatters as $formatter) {
$row = call_user_func($formatter, $row);
}
return $row;
}
/**
* Validate a row
*
* @param array $row
*
* @throws InvalidRowException If the validation failed
*/
protected function validateRow(array $row)
{
foreach ($this->validators as $name => $validator) {
if (true !== call_user_func($validator, $row)) {
throw new InvalidRowException($name, $row, 'row validation failed');
}
}
}
}

View File

@@ -0,0 +1,299 @@
<?php
/**
* This file is part of the League.csv library
*
* @license http://opensource.org/licenses/MIT
* @link https://github.com/thephpleague/csv/
* @version 8.2.3
* @package League.csv
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Csv\Modifier;
use LogicException;
use OutOfBoundsException;
use SplFileObject;
/**
* A Trait to ease PHP Stream Filters manipulation
* with a SplFileObject
*
* @package League.csv
* @since 6.0.0
*
*/
trait StreamFilter
{
/**
* collection of stream filters
*
* @var array
*/
protected $stream_filters = [];
/**
* Stream filtering mode to apply on all filters
*
* @var int
*/
protected $stream_filter_mode = STREAM_FILTER_ALL;
/**
*the real path
*
* @var string the real path to the file
*
*/
protected $stream_uri;
/**
* PHP Stream Filter Regex
*
* @var string
*/
protected $stream_regex = ',^
php://filter/
(?P<mode>:?read=|write=)? # The resource open mode
(?P<filters>.*?) # The resource registered filters
/resource=(?P<resource>.*) # The resource path
$,ix';
/**
* Internal path setter
*
* The path must be an SplFileInfo object
* an object that implements the `__toString` method
* a path to a file
*
* @param StreamIterator|SplFileObject|string $path The file path
*/
protected function initStreamFilter($path)
{
$this->stream_filters = [];
if (!is_string($path)) {
$this->stream_uri = null;
return;
}
if (!preg_match($this->stream_regex, $path, $matches)) {
$this->stream_uri = $path;
return;
}
$this->stream_uri = $matches['resource'];
$this->stream_filters = array_map('urldecode', explode('|', $matches['filters']));
$this->stream_filter_mode = $this->fetchStreamModeAsInt($matches['mode']);
}
/**
* Get the stream mode
*
* @param string $mode
*
* @return int
*/
protected function fetchStreamModeAsInt($mode)
{
$mode = strtolower($mode);
$mode = rtrim($mode, '=');
if ('write' == $mode) {
return STREAM_FILTER_WRITE;
}
if ('read' == $mode) {
return STREAM_FILTER_READ;
}
return STREAM_FILTER_ALL;
}
/**
* Check if the trait methods can be used
*
* @throws LogicException If the API can not be use
*/
protected function assertStreamable()
{
if (!is_string($this->stream_uri)) {
throw new LogicException('The stream filter API can not be used');
}
}
/**
* Tells whether the stream filter capabilities can be used
*
* @return bool
*/
public function isActiveStreamFilter()
{
return is_string($this->stream_uri);
}
/**
* stream filter mode Setter
*
* Set the new Stream Filter mode and remove all
* previously attached stream filters
*
* @param int $mode
*
* @throws OutOfBoundsException If the mode is invalid
*
* @return $this
*/
public function setStreamFilterMode($mode)
{
$this->assertStreamable();
if (!in_array($mode, [STREAM_FILTER_ALL, STREAM_FILTER_READ, STREAM_FILTER_WRITE])) {
throw new OutOfBoundsException('the $mode should be a valid `STREAM_FILTER_*` constant');
}
$this->stream_filter_mode = $mode;
$this->stream_filters = [];
return $this;
}
/**
* stream filter mode getter
*
* @return int
*/
public function getStreamFilterMode()
{
$this->assertStreamable();
return $this->stream_filter_mode;
}
/**
* append a stream filter
*
* @param string $filter_name a string or an object that implements the '__toString' method
*
* @return $this
*/
public function appendStreamFilter($filter_name)
{
$this->assertStreamable();
$this->stream_filters[] = $this->sanitizeStreamFilter($filter_name);
return $this;
}
/**
* prepend a stream filter
*
* @param string $filter_name a string or an object that implements the '__toString' method
*
* @return $this
*/
public function prependStreamFilter($filter_name)
{
$this->assertStreamable();
array_unshift($this->stream_filters, $this->sanitizeStreamFilter($filter_name));
return $this;
}
/**
* Sanitize the stream filter name
*
* @param string $filter_name the stream filter name
*
* @return string
*/
protected function sanitizeStreamFilter($filter_name)
{
return urldecode($this->validateString($filter_name));
}
/**
* @inheritdoc
*/
abstract public function validateString($str);
/**
* Detect if the stream filter is already present
*
* @param string $filter_name
*
* @return bool
*/
public function hasStreamFilter($filter_name)
{
$this->assertStreamable();
return false !== array_search(urldecode($filter_name), $this->stream_filters, true);
}
/**
* Remove a filter from the collection
*
* @param string $filter_name
*
* @return $this
*/
public function removeStreamFilter($filter_name)
{
$this->assertStreamable();
$res = array_search(urldecode($filter_name), $this->stream_filters, true);
if (false !== $res) {
unset($this->stream_filters[$res]);
}
return $this;
}
/**
* Remove all registered stream filter
*
* @return $this
*/
public function clearStreamFilter()
{
$this->assertStreamable();
$this->stream_filters = [];
return $this;
}
/**
* Return the filter path
*
* @return string
*/
protected function getStreamFilterPath()
{
$this->assertStreamable();
if (!$this->stream_filters) {
return $this->stream_uri;
}
return 'php://filter/'
.$this->getStreamFilterPrefix()
.implode('|', array_map('urlencode', $this->stream_filters))
.'/resource='.$this->stream_uri;
}
/**
* Return PHP stream filter prefix
*
* @return string
*/
protected function getStreamFilterPrefix()
{
if (STREAM_FILTER_READ == $this->stream_filter_mode) {
return 'read=';
}
if (STREAM_FILTER_WRITE == $this->stream_filter_mode) {
return 'write=';
}
return '';
}
}

View File

@@ -0,0 +1,334 @@
<?php
/**
* This file is part of the League.csv library
*
* @license http://opensource.org/licenses/MIT
* @link https://github.com/thephpleague/csv/
* @version 8.2.3
* @package League.csv
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace League\Csv\Modifier;
use InvalidArgumentException;
use Iterator;
use SplFileObject;
/**
* A Stream Iterator
*
* @package League.csv
* @since 8.2.0
* @internal used internally to iterate over a stream resource
*
*/
class StreamIterator implements Iterator
{
/**
* Stream pointer
*
* @var resource
*/
protected $stream;
/**
* Current iterator value
*
* @var mixed
*/
protected $current_line;
/**
* Current iterator key
*
* @var int
*/
protected $current_line_number;
/**
* Flags for the StreamIterator
*
* @var int
*/
protected $flags = 0;
/**
* the field delimiter (one character only)
*
* @var string
*/
protected $delimiter = ',';
/**
* the field enclosure character (one character only)
*
* @var string
*/
protected $enclosure = '"';
/**
* the field escape character (one character only)
*
* @var string
*/
protected $escape = '\\';
/**
* New instance
*
* @param resource $stream stream type resource
*/
public function __construct($stream)
{
if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
throw new InvalidArgumentException(sprintf(
'Expected resource to be a stream, received %s instead',
is_object($stream) ? get_class($stream) : gettype($stream)
));
}
$data = stream_get_meta_data($stream);
if (!$data['seekable']) {
throw new InvalidArgumentException('The stream must be seekable');
}
$this->stream = $stream;
}
/**
* Set CSV control
*
* @see http://php.net/manual/en/splfileobject.setcsvcontrol.php
*
* @param string $delimiter
* @param string $enclosure
* @param string $escape
*/
public function setCsvControl($delimiter = ',', $enclosure = '"', $escape = '\\')
{
$this->delimiter = $this->filterControl($delimiter, 'delimiter');
$this->enclosure = $this->filterControl($enclosure, 'enclosure');
$this->escape = $this->filterControl($escape, 'escape');
}
/**
* Filter Csv control character
*
* @param string $char Csv control character
* @param string $type Csv control character type
*
* @throws InvalidArgumentException If the Csv control character is not one character only.
*
* @return string
*/
private function filterControl($char, $type)
{
if (1 == strlen($char)) {
return $char;
}
throw new InvalidArgumentException(sprintf('The %s character must be a single character', $type));
}
/**
* Set Flags
*
* @see http://php.net/manual/en/splfileobject.setflags.php
*
* @param int $flags
*/
public function setFlags($flags)
{
if (false === filter_var($flags, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
throw new InvalidArgumentException('The flags must be a positive integer');
}
$this->flags = $flags;
}
/**
* Write a field array as a CSV line
*
* @see http://php.net/manual/en/splfileobject.fputcsv.php
*
* @param array $fields
* @param string $delimiter
* @param string $enclosure
* @param string $escape
*
* @return int
*/
public function fputcsv(array $fields, $delimiter = ',', $enclosure = '"', $escape = '\\')
{
return fputcsv(
$this->stream,
$fields,
$this->filterControl($delimiter, 'delimiter'),
$this->filterControl($enclosure, 'enclosure'),
$this->filterControl($escape, 'escape')
);
}
/**
* Retrieves the current line of the file.
*
* @return mixed
*/
public function current()
{
if (false !== $this->current_line) {
return $this->current_line;
}
if (($this->flags & SplFileObject::READ_CSV) == SplFileObject::READ_CSV) {
$this->current_line = $this->getCurrentRecord();
return $this->current_line;
}
$this->current_line = $this->getCurrentLine();
return $this->current_line;
}
/**
* Retrieves the current line as a CSV Record
*
* @return array
*/
protected function getCurrentRecord()
{
do {
$ret = fgetcsv($this->stream, 0, $this->delimiter, $this->enclosure, $this->escape);
} while ($this->flags & SplFileObject::SKIP_EMPTY && $ret !== false && $ret[0] === null);
return $ret;
}
/**
* Retrieves the current line as a string
*
* @return string
*/
protected function getCurrentLine()
{
do {
$line = fgets($this->stream);
} while ($this->flags & SplFileObject::SKIP_EMPTY && $line !== false && rtrim($line, "\r\n") !== '');
return $line;
}
/**
* Get line number
*
* @return int
*/
public function key()
{
return $this->current_line_number;
}
/**
* Read next line
*/
public function next()
{
$this->current_line = false;
$this->current_line_number++;
}
/**
* Rewind the file to the first line
*/
public function rewind()
{
rewind($this->stream);
$this->current_line_number = 0;
$this->current_line = false;
if ($this->flags & SplFileObject::READ_AHEAD) {
$this->current();
}
}
/**
* Not at EOF
*
* @return bool
*/
public function valid()
{
if ($this->flags & SplFileObject::READ_AHEAD) {
return $this->current() !== false;
}
return !feof($this->stream);
}
/**
* Gets line from file
*
* @see http://php.net/manual/en/splfileobject.fgets.php
*
* @return string
*/
public function fgets()
{
if (false !== $this->current_line) {
$this->next();
}
return $this->current_line = $this->getCurrentLine();
}
/**
* Output all remaining data on a file pointer
*
* @see http://php.net/manual/en/splfileobject.fpatssthru.php
*
* @return int
*/
public function fpassthru()
{
return fpassthru($this->stream);
}
/**
* Seek to a position
*
* @see http://php.net/manual/en/splfileobject.fseek.php
*
* @param int $offset
* @param int $whence
*
* @return int
*/
public function fseek($offset, $whence = SEEK_SET)
{
return fseek($this->stream, $offset, $whence);
}
/**
* Write to stream
*
* @see http://php.net/manual/en/splfileobject.fwrite.php
*
* @param string $str
* @param int $length
*
* @return int
*/
public function fwrite($str, $length = 0)
{
return fwrite($this->stream, $str, $length);
}
/**
* close the file pointer
*/
public function __destruct()
{
$this->stream = null;
}
}