summaryrefslogtreecommitdiffstats
path: root/src/Modifier
diff options
context:
space:
mode:
authorIgnace Nyamagana Butera <nyamsprod@gmail.com>2015-02-19 08:49:17 +0100
committerIgnace Nyamagana Butera <nyamsprod@gmail.com>2015-02-19 08:52:39 +0100
commit0a493cecf0216f4c797671601251e3c1a6452ffa (patch)
treea23aeb9c31d7e05ccffa30bd4e5dc46cd27a5139 /src/Modifier
parent959ede56075fec54891fad13744aeed6d42ad345 (diff)
downloadcsv-0a493cecf0216f4c797671601251e3c1a6452ffa.zip
csv-0a493cecf0216f4c797671601251e3c1a6452ffa.tar.gz
csv-0a493cecf0216f4c797671601251e3c1a6452ffa.tar.bz2
final package structure
Diffstat (limited to 'src/Modifier')
-rw-r--r--src/Modifier/MapIterator.php57
-rw-r--r--src/Modifier/QueryFilter.php269
-rw-r--r--src/Modifier/RowFilter.php151
-rw-r--r--src/Modifier/StreamFilter.php271
4 files changed, 748 insertions, 0 deletions
diff --git a/src/Modifier/MapIterator.php b/src/Modifier/MapIterator.php
new file mode 100644
index 0000000..7360f42
--- /dev/null
+++ b/src/Modifier/MapIterator.php
@@ -0,0 +1,57 @@
+<?php
+/**
+* This file is part of the League.csv library
+*
+* @license http://opensource.org/licenses/MIT
+* @link https://github.com/thephpleague/csv/
+* @version 7.0.0
+* @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 IteratorIterator;
+use Traversable;
+
+/**
+ * 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 Traversable $iterator
+ * @param callable $callable
+ */
+ public function __construct(Traversable $iterator, callable $callable)
+ {
+ parent::__construct($iterator);
+ $this->callable = $callable;
+ }
+
+ /**
+ * Get the value of the current element
+ */
+ public function current()
+ {
+ $iterator = $this->getInnerIterator();
+ $callable = $this->callable;
+
+ return $callable($iterator->current(), $iterator->key(), $iterator);
+ }
+}
diff --git a/src/Modifier/QueryFilter.php b/src/Modifier/QueryFilter.php
new file mode 100644
index 0000000..229ea42
--- /dev/null
+++ b/src/Modifier/QueryFilter.php
@@ -0,0 +1,269 @@
+<?php
+/**
+* This file is part of the League.csv library
+*
+* @license http://opensource.org/licenses/MIT
+* @link https://github.com/thephpleague/csv/
+* @version 7.0.0
+* @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 InvalidArgumentException;
+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;
+
+ /**
+ * Set LimitIterator Offset
+ *
+ * @param $offset
+ *
+ * @return $this
+ */
+ public function setOffset($offset = 0)
+ {
+ if (false === filter_var($offset, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) {
+ throw new InvalidArgumentException('the offset must be a positive integer or 0');
+ }
+ $this->iterator_offset = $offset;
+
+ return $this;
+ }
+
+ /**
+ * Set LimitInterator Count
+ *
+ * @param int $limit
+ *
+ * @return $this
+ */
+ public function setLimit($limit = -1)
+ {
+ if (false === filter_var($limit, FILTER_VALIDATE_INT, ['options' => ['min_range' => -1]])) {
+ throw new InvalidArgumentException('the limit must an integer greater or equals to -1');
+ }
+ $this->iterator_limit = $limit;
+
+ return $this;
+ }
+
+ /**
+ * Sort the Iterator
+ *
+ * @param \Iterator $iterator
+ *
+ * @return \LimitIterator
+ */
+ protected function applyIteratorInterval(Iterator $iterator)
+ {
+ if (0 == $this->iterator_offset && -1 == $this->iterator_limit) {
+ return $iterator;
+ }
+ $offset = $this->iterator_offset;
+ $limit = $this->iterator_limit;
+
+ $this->iterator_limit = -1;
+ $this->iterator_offset = 0;
+
+ return new LimitIterator($iterator, $offset, $limit);
+ }
+
+ /**
+ * Set an Iterator sorting callable function
+ *
+ * @param callable $callable
+ *
+ * @return $this
+ */
+ public function addSortBy(callable $callable)
+ {
+ $this->iterator_sort_by[] = $callable;
+
+ return $this;
+ }
+
+ /**
+ * Remove a callable from the collection
+ *
+ * @param callable $callable
+ *
+ * @return $this
+ */
+ public function removeSortBy(callable $callable)
+ {
+ $res = array_search($callable, $this->iterator_sort_by, true);
+ if (false !== $res) {
+ unset($this->iterator_sort_by[$res]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Detect if the callable is already registered
+ *
+ * @param callable $callable
+ *
+ * @return bool
+ */
+ public function hasSortBy(callable $callable)
+ {
+ return false !== array_search($callable, $this->iterator_sort_by, true);
+ }
+
+ /**
+ * Remove all registered callable
+ *
+ * @return $this
+ */
+ public function clearSortBy()
+ {
+ $this->iterator_sort_by = [];
+
+ return $this;
+ }
+
+ /**
+ * Sort the Iterator
+ *
+ * @param \Iterator $iterator
+ *
+ * @return \ArrayIterator
+ */
+ protected function applyIteratorSortBy(Iterator $iterator)
+ {
+ if (! $this->iterator_sort_by) {
+ return $iterator;
+ }
+ $nb_callbacks = count($this->iterator_sort_by);
+ $this->iterator_sort_by = array_values($this->iterator_sort_by);
+ $res = iterator_to_array($iterator, false);
+ uasort($res, function ($rowA, $rowB) use ($nb_callbacks) {
+ $res = 0;
+ $index = 0;
+ while ($index < $nb_callbacks && 0 === $res) {
+ $res = $this->iterator_sort_by[$index]($rowA, $rowB);
+ ++$index;
+ }
+
+ return $res;
+ });
+ $this->clearSortBy();
+
+ return new ArrayIterator($res);
+ }
+
+ /**
+ * Set the Iterator filter method
+ *
+ * @param callable $callable
+ *
+ * @return $this
+ */
+ public function addFilter(callable $callable)
+ {
+ $this->iterator_filters[] = $callable;
+
+ return $this;
+ }
+
+ /**
+ * Remove a filter from the callable collection
+ *
+ * @param callable $callable
+ *
+ * @return $this
+ */
+ public function removeFilter(callable $callable)
+ {
+ $res = array_search($callable, $this->iterator_filters, true);
+ if (false !== $res) {
+ unset($this->iterator_filters[$res]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Detect if the callable filter is already registered
+ *
+ * @param callable $callable
+ *
+ * @return bool
+ */
+ public function hasFilter(callable $callable)
+ {
+ return false !== array_search($callable, $this->iterator_filters, true);
+ }
+
+ /**
+ * Remove all registered callable filter
+ *
+ * @return $this
+ */
+ public function clearFilter()
+ {
+ $this->iterator_filters = [];
+
+ return $this;
+ }
+
+ /**
+ * Filter the Iterator
+ *
+ * @param \Iterator $iterator
+ *
+ * @return \Iterator
+ */
+ protected function applyIteratorFilter(Iterator $iterator)
+ {
+ foreach ($this->iterator_filters as $callable) {
+ $iterator = new CallbackFilterIterator($iterator, $callable);
+ }
+ $this->clearFilter();
+
+ return $iterator;
+ }
+}
diff --git a/src/Modifier/RowFilter.php b/src/Modifier/RowFilter.php
new file mode 100644
index 0000000..b0aec16
--- /dev/null
+++ b/src/Modifier/RowFilter.php
@@ -0,0 +1,151 @@
+<?php
+/**
+* This file is part of the League.csv library
+*
+* @license http://opensource.org/licenses/MIT
+* @link https://github.com/thephpleague/csv/
+* @version 7.0.0
+* @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;
+
+/**
+ * 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);
+ if (false !== $res) {
+ 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 = trim($name);
+ $this->validators[$name] = $callable;
+
+ return $this;
+ }
+
+ /**
+ * Remove a validator from the collection
+ *
+ * @param string $name the validator name
+ *
+ * @return $this
+ */
+ public function removeValidator($name)
+ {
+ $name = trim($name);
+ if (array_key_exists($name, $this->validators)) {
+ 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 = trim($name);
+
+ return array_key_exists($name, $this->validators);
+ }
+
+ /**
+ * Remove all registered validatior
+ *
+ * @return $this
+ */
+ public function clearValidators()
+ {
+ $this->validators = [];
+
+ return $this;
+ }
+}
diff --git a/src/Modifier/StreamFilter.php b/src/Modifier/StreamFilter.php
new file mode 100644
index 0000000..1bbdff5
--- /dev/null
+++ b/src/Modifier/StreamFilter.php
@@ -0,0 +1,271 @@
+<?php
+/**
+* This file is part of the League.csv library
+*
+* @license http://opensource.org/licenses/MIT
+* @link https://github.com/thephpleague/csv/
+* @version 7.0.0
+* @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 SplFileInfo;
+
+/**
+ * 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;
+
+ /**
+ * Internal path setter
+ *
+ * The path must be an SplFileInfo object
+ * an object that implements the `__toString` method
+ * a path to a file
+ *
+ * @param \SplFileObject|string $path The file path
+ */
+ protected function initStreamFilter($path)
+ {
+ if (! is_string($path)) {
+ $this->stream_uri = null;
+ $this->stream_filters = [];
+
+ return;
+ }
+
+ $this->extractStreamSettings($path);
+ }
+
+ /**
+ * Extract Available stream settings from $path
+ *
+ * @param string $path the file path
+ */
+ protected function extractStreamSettings($path)
+ {
+ if (! preg_match(
+ ',^php://filter/(?P<mode>:?read=|write=)?(?P<filters>.*?)/resource=(?P<resource>.*)$,i',
+ $path,
+ $matches
+ )) {
+ $this->stream_uri = $path;
+ $this->stream_filters = [];
+
+ return;
+ }
+ $matches['mode'] = strtolower($matches['mode']);
+ $mode = STREAM_FILTER_ALL;
+ if ('write=' == $matches['mode']) {
+ $mode = STREAM_FILTER_WRITE;
+ } elseif ('read=' == $matches['mode']) {
+ $mode = STREAM_FILTER_READ;
+ }
+ $this->stream_filter_mode = $mode;
+ $this->stream_uri = $matches['resource'];
+ $this->stream_filters = explode('|', $matches['filters']);
+ }
+
+ /**
+ * 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)
+ {
+ $this->assertStreamable();
+ $filter_name = (string) $filter_name;
+
+ return trim($filter_name);
+ }
+
+ /**
+ * 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($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($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;
+ }
+
+ $prefix = '';
+ if (STREAM_FILTER_READ == $this->stream_filter_mode) {
+ $prefix = 'read=';
+ } elseif (STREAM_FILTER_WRITE == $this->stream_filter_mode) {
+ $prefix = 'write=';
+ }
+
+ return 'php://filter/'.$prefix.implode('|', $this->stream_filters).'/resource='.$this->stream_uri;
+ }
+}