diff options
Diffstat (limited to 'src/Config')
-rw-r--r-- | src/Config/Controls.php | 266 | ||||
-rw-r--r-- | src/Config/StreamFilter.php | 260 |
2 files changed, 526 insertions, 0 deletions
diff --git a/src/Config/Controls.php b/src/Config/Controls.php new file mode 100644 index 0000000..61bbe77 --- /dev/null +++ b/src/Config/Controls.php @@ -0,0 +1,266 @@ +<?php +/** +* This file is part of the League.csv library +* +* @license http://opensource.org/licenses/MIT +* @link https://github.com/thephpleague/csv/ +* @version 5.5.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\Config; + +use Traversable; +use SplFileObject; +use InvalidArgumentException; +use League\Csv\Iterator\MapIterator; + +/** + * A trait to configure and check CSV file and content + * + * @package League.csv + * @since 5.5.0 + * + */ +trait Controls +{ + /** + * 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 = '\\'; + + /** + * the \SplFileObject flags holder + * + * @var integer + */ + protected $flags = SplFileObject::READ_CSV; + + /** + * Charset Encoding for the CSV + * + * @var string + */ + protected $encodingFrom = 'UTF-8'; + + /** + * set the field delimeter + * + * @param string $delimiter + * + * @return self + * + * @throws \InvalidArgumentException If $delimeter is not a single character + */ + public function setDelimiter($delimiter = ',') + { + if (1 != mb_strlen($delimiter)) { + throw new InvalidArgumentException('The delimiter must be a single character'); + } + $this->delimiter = $delimiter; + + return $this; + } + + /** + * return the current field delimiter + * + * @return string + */ + public function getDelimiter() + { + return $this->delimiter; + } + + /** + * set the field enclosure + * + * @param string $enclosure + * + * @return self + * + * @throws \InvalidArgumentException If $enclosure is not a single character + */ + public function setEnclosure($enclosure = '"') + { + if (1 != mb_strlen($enclosure)) { + throw new InvalidArgumentException('The enclosure must be a single character'); + } + $this->enclosure = $enclosure; + + return $this; + } + + /** + * return the current field enclosure + * + * @return string + */ + public function getEnclosure() + { + return $this->enclosure; + } + + /** + * set the field escape character + * + * @param string $escape + * + * @return self + * + * @throws \InvalidArgumentException If $escape is not a single character + */ + public function setEscape($escape = "\\") + { + if (1 != mb_strlen($escape)) { + throw new InvalidArgumentException('The escape character must be a single character'); + } + $this->escape = $escape; + + return $this; + } + + /** + * return the current field escape character + * + * @return string + */ + public function getEscape() + { + return $this->escape; + } + + /** + * Set the Flags associated to the CSV SplFileObject + * + * @param integer $flags + * + * @return self + */ + public function setFlags($flags) + { + if (false === filter_var($flags, FILTER_VALIDATE_INT, ['options' => ['min_range' => 0]])) { + throw new InvalidArgumentException('you should use a `SplFileObject` Constant'); + } + + $this->flags = $flags|SplFileObject::READ_CSV|SplFileObject::DROP_NEW_LINE; + + return $this; + } + + /** + * Returns the file Flags + * + * @return integer + */ + public function getFlags() + { + return $this->flags; + } + + /** + * DEPRECATION WARNING! This method will be removed in the next major point release + * + * @deprecated deprecated since version 5.5 + * + * @param string $str + * + * @return self + */ + public function setEncoding($str) + { + return $this->setEncodingFrom($str); + } + + /** + * DEPRECATION WARNING! This method will be removed in the next major point release + * + * @deprecated deprecated since version 5.5 + * + * @return string + */ + public function getEncoding() + { + return $this->getEncodingFrom(); + } + + /** + * Set the CSV encoding charset + * + * @param string $str + * + * @return self + */ + public function setEncodingFrom($str) + { + $str = str_replace('_', '-', $str); + $str = filter_var($str, FILTER_SANITIZE_STRING, ['flags' => FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH]); + if (empty($str)) { + throw new InvalidArgumentException('you should use a valid charset'); + } + $this->encodingFrom = strtoupper($str); + + return $this; + } + + /** + * Get the source CSV encoding charset + * + * @return string + */ + public function getEncodingFrom() + { + return $this->encodingFrom; + } + + /** + * Convert Csv file into UTF-8 + * + * @return \Traversable + */ + protected function convertToUtf8(Traversable $iterator) + { + if (strpos($this->encodingFrom, 'UTF-8') !== false) { + return $iterator; + } + + return new MapIterator($iterator, function ($row) { + foreach ($row as &$value) { + $value = mb_convert_encoding($value, 'UTF-8', $this->encodingFrom); + } + unset($value); + + return $row; + }); + } + + /** + * Validate a variable to be stringable + * + * @param mixed $str + * + * @return boolean + */ + public static function isValidString($str) + { + return is_scalar($str) || (is_object($str) && method_exists($str, '__toString')); + } +} diff --git a/src/Config/StreamFilter.php b/src/Config/StreamFilter.php new file mode 100644 index 0000000..58267e1 --- /dev/null +++ b/src/Config/StreamFilter.php @@ -0,0 +1,260 @@ +<?php +/** +* This file is part of the League.csv library +* +* @license http://opensource.org/licenses/MIT +* @link https://github.com/thephpleague/csv/ +* @version 5.5.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\Config; + +use SplFileInfo; +use SplTempFileObject; +use InvalidArgumentException; +use RuntimeException; +use OutOfBoundsException; + +/** + * A Trait to ease PHP Stream Filters manipulation + * with a SplFileObject + * + * @package League.csv + * @since 5.5.0 + * + */ +trait StreamFilter +{ + /** + * collection of stream filters + * + * @var array + */ + protected $stream_filters = []; + + /** + * Stream filtering mode to apply on all filters + * + * @var integer + */ + protected $stream_filter_mode = STREAM_FILTER_ALL; + + /** + *the real path + * + * @var string the real path to the file + * + */ + protected $stream_real_path; + + /** + * Internal path setter + * + * @param mixed $path can be a SplFileInfo object or the path to a file + * + * @return self + * + * @throws InvalidArgumentException If $path is invalid + */ + protected function initStreamFilter($path) + { + if ($path instanceof SplTempFileObject) { + $this->stream_real_path = null; + + return $this; + + } elseif ($path instanceof SplFileInfo) { + //$path->getRealPath() returns false for php stream wrapper + $path = $path->getPath().'/'.$path->getBasename(); + } + + $path = trim($path); + //if we are submitting a filter meta wrapper + //we extract and inject the mode, the filter and the path + if (preg_match( + ',^php://filter/(?P<mode>:?read=|write=)?(?P<filters>.*?)/resource=(?P<resource>.*)$,i', + $path, + $matches + )) { + $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_real_path = $matches['resource']; + $this->stream_filters = explode('|', $matches['filters']); + + return $this; + } + + $this->stream_real_path = $path; + $this->stream_filters = []; + + return $this; + } + + /** + * stream filter mode Setter + * + * Set the new Stream Filter mode and remove all + * previously attached stream filters + * + * @param integer $mode + * + * @return self + */ + public function setStreamFilterMode($mode) + { + 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 integer + */ + public function getStreamFilterMode() + { + return $this->stream_filter_mode; + } + + /** + * Sanitize the stream filter name + * + * @param string $filter_name the stream filter name + * + * @return string + * + * @throws \InvalidArgumentException If $filter_name is not a string + */ + protected function sanitizeStreamFilter($filter_name) + { + if (! is_string($filter_name)) { + throw new InvalidArgumentException( + 'the filtername variable must be a string' + ); + } + + return trim($filter_name); + } + + /** + * append a stream filter + * + * @param string $filter_name a string or an object that implements the '__toString' method + * + * @return self + * + * @throws \InvalidArgumentException If what you try to add is invalid + * @throws \RuntimeException If adding Stream Filter is not possible + */ + public function appendStreamFilter($filter_name) + { + if (is_null($this->stream_real_path)) { + throw new RuntimeException( + 'no stream path found, you can not append a stream filter' + ); + } + $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 self + * + * @throws \InvalidArgumentException If what you try to add is invalid + * @throws \RuntimeException If adding Stream Filter is not possible + */ + public function prependStreamFilter($filter_name) + { + if (is_null($this->stream_real_path)) { + throw new RuntimeException( + 'no stream path found, you can not prepend a stream filter' + ); + } + + array_unshift($this->stream_filters, $this->sanitizeStreamFilter($filter_name)); + + return $this; + } + + /** + * Detect if the stream filter is already present + * + * @param string $filter_name + * + * @return boolean + */ + public function hasStreamFilter($filter_name) + { + return false !== array_search($filter_name, $this->stream_filters, true); + } + + /** + * Remove a filter from the collection + * + * @param string $filter_name + * + * @return self + */ + public function removeStreamFilter($filter_name) + { + $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 self + */ + public function clearStreamFilter() + { + $this->stream_filters = []; + + return $this; + } + + /** + * Return the filter path + * + * @return string + */ + protected function getStreamFilterPath() + { + if (! $this->stream_filters) { + return $this->stream_real_path; + } + + $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_real_path; + } +} |