Skip to content

Commit

Permalink
Improve conversion API
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Mar 27, 2017
1 parent 046fb87 commit 827e43c
Show file tree
Hide file tree
Showing 21 changed files with 118 additions and 70 deletions.
2 changes: 1 addition & 1 deletion docs/9.0/connections/bom.md
Expand Up @@ -47,7 +47,7 @@ use function League\Csv\bom_match;

bom_match('hello world!'); //returns ''
bom_match(BOM::UTF8.'hello world!'); //returns '\xEF\xBB\xBF'
bom_match('hrllo world!'.BOM::UTF16_BE); //returns ''
bom_match('hello world!'.BOM::UTF16_BE); //returns ''
~~~

## Managing CSV documents BOM sequence
Expand Down
4 changes: 3 additions & 1 deletion docs/9.0/connections/index.md
Expand Up @@ -131,4 +131,6 @@ use League\Csv\Writer;

$reader = Reader::createFromFileObject(new SplFileObject('/path/to/your/csv/file.csv'));
$writer = Writer::createFromFileObject(new SplTempFileObject());
~~~
~~~

<p class="message-warning"> The <code>SplFileObject</code> <strong>MUST</strong> be seekable otherwise a <code>RuntimeException</code> may be thrown.</p>
10 changes: 10 additions & 0 deletions docs/9.0/converter/html.md
Expand Up @@ -14,6 +14,16 @@ Prior to converting your records collection into a HTML table, you may wish to c

<p class="message-warning">Because we are using internally the <a href="/9.0/converter/xml/">XMLConverter</a>, if an error occurs while validating the submitted values a <code>DOMException</code> exception will be thrown.</p>

### HTMLConverter::encoding

~~~php
<?php

public HTMLConverter::encoding(string $encoding): self
~~~

This method sets the HTML encoding charset which default to `UTF-8` if none is supplied.

### HTMLConverter::table

~~~php
Expand Down
2 changes: 1 addition & 1 deletion docs/9.0/converter/index.md
Expand Up @@ -41,7 +41,7 @@ When building a converter object, the methods do not need to be called in any pa
<?php

public Encoder::inputEncoding(string $input_encoding): self
public Encoder::outputEncoding(string $output_encoding = 'UTF-8'): self
public Encoder::outputEncoding(string $output_encoding): self
public Encoder::encodeOne(array $record): array
public Encoder::encodeAll(iterable $records): iterable
~~~
Expand Down
4 changes: 2 additions & 2 deletions docs/9.0/converter/json.md
Expand Up @@ -14,10 +14,10 @@ title: Converting a CSV into a JSON string
~~~php
<?php

public JsonConverter::options(int options, int $depth = 512): self
public JsonConverter::options(int options): self
~~~

This method sets PHP's `json_encode` optional arguments.
This method sets PHP's `json_encode` optional flags.

## Conversion

Expand Down
12 changes: 11 additions & 1 deletion docs/9.0/converter/xml.md
Expand Up @@ -11,7 +11,17 @@ title: Converting a CSV into a XML DOMDocument object

Prior to converting your records collection into XML, you may wish to configure the element and its associated attribute names. To do so `XMLConverter` provides methods to setup theses settings.

<p class="message-warning">Because we are building a <code>DOMDocument</code>, the <code>XMLConverter</code> object throws <code>DOMException</code> exceptions that do not implements <a href="/9.0/connections/exceptions/">CsvException</a>.</p>
<p class="message-warning">Because we are building a <code>DOMDocument</code> object, the <code>XMLConverter</code> object throws <code>DOMException</code> exceptions that do not implements <a href="/9.0/connections/exceptions/">CsvException</a>.</p>

### XMLConverter::encoding

~~~php
<?php

public XMLConverter::encoding(string $encoding): self
~~~

This method sets the XML encoding charset which default to `UTF-8` if none is supplied.

### XMLConverter::rootElement

Expand Down
2 changes: 2 additions & 0 deletions docs/9.0/reader/index.md
Expand Up @@ -111,6 +111,8 @@ $header_offset = $csv->getHeaderOffset(); //returns 1000
$header = $csv->getHeader(); //triggers a Exception
~~~

<p class="message-notice">By setting a header offset you implicitly normalize your CSV document to the field length of the specified header. Missing fields will be added with <code>null</code> content whereas extra fields will be truncated while iterating the CSV records.</p>

## Iterating over the document records

Because the `Reader` class implements the `IteratorAggregate` interface you can iterate over each record using the `foreach` construct. While iterating the `Reader` will:
Expand Down
2 changes: 1 addition & 1 deletion docs/9.0/writer/index.md
Expand Up @@ -94,7 +94,7 @@ public Writer::setFlushThreshold(?int $treshold): self
public Writer::getFlushThreshold(void): int|null
~~~

By default, the flush mechanism deactivate `getFlushTreshold` returns `null`.
By default, `getFlushTreshold` returns `null`.

<p class="message-info"><code>Writer::insertAll</code> always flush its buffer when all records are inserted regardless of the threshold value.</p>

Expand Down
6 changes: 4 additions & 2 deletions docs/upgrading/upgrading-9.0.md
Expand Up @@ -59,7 +59,7 @@ $writer = Writer::createFromFileObject(new SplTempFileObject());
$str = 'john,doe,john.doe@example.com';
$record = str_getcsv($str, ',', '"', '\\');
$writer->insertOne($record);
$writer->insertAll(str_getcsv([$record]);
$writer->insertAll([$record]);
~~~

### Reduced method chaining
Expand Down Expand Up @@ -237,7 +237,7 @@ $reader = Reader::createFromPath('/path/to/file.csv');
$pairs_without_duplicates = $reader
->setOffset(3)
->setLimit(2)
->fetchfetchPairsWithoutDuplicates()
->fetchPairsWithoutDuplicates()
;

foreach ($pairs_without_duplicates as $key => $value) {
Expand Down Expand Up @@ -460,6 +460,8 @@ All convertion methods are no longer attached to the `Reader` or the `Writer` cl
- `AbstractCsv::toHTML`
- `AbstractCsv::toXML`

And you can no longer convert a `Writer` class.

Before:

~~~php
Expand Down
4 changes: 2 additions & 2 deletions src/AbstractCsv.php
Expand Up @@ -403,11 +403,11 @@ public function addStreamFilter(string $filtername): self
public function __destruct()
{
if ($this->document instanceof StreamIterator) {
$mapper = function ($filter): bool {
$walker = function ($filter): bool {
return $this->document->removeFilter($filter);
};

array_walk_recursive($this->stream_filters, $mapper);
array_walk_recursive($this->stream_filters, $walker);
}

$this->document = null;
Expand Down
21 changes: 0 additions & 21 deletions src/Encoder.php
Expand Up @@ -15,7 +15,6 @@
namespace League\Csv;

use Iterator;
use League\Csv\Exception\InvalidArgumentException;
use Traversable;

/**
Expand Down Expand Up @@ -132,26 +131,6 @@ public function inputEncoding(string $encoding): self
return $clone;
}

/**
* Filter encoding charset
*
* @param string $encoding
*
* @throws InvalidArgumentException if the charset is malformed
*
* @return string
*/
protected function filterEncoding(string $encoding)
{
$encoding = strtoupper(str_replace('_', '-', $encoding));
$test = filter_var($encoding, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH);
if ($test === $encoding && $encoding != '') {
return $encoding;
}

throw new InvalidArgumentException('Invalid Character Error');
}

/**
* Sets the records output encoding charset
*
Expand Down
15 changes: 15 additions & 0 deletions src/HTMLConverter.php
Expand Up @@ -56,6 +56,21 @@ public function __construct()
;
}

/**
* HTML encoding
*
* @param string $encoding
*
* @return static
*/
public function encoding(string $encoding): self
{
$clone = clone $this;
$clone->xml_converter = $this->xml_converter->encoding($encoding);

return $clone;
}

/**
* HTML table class name setter
*
Expand Down
17 changes: 4 additions & 13 deletions src/JsonConverter.php
Expand Up @@ -36,25 +36,16 @@ class JsonConverter implements Converter
protected $options = 0;

/**
* json_encode depth
*
* @var int
*/
protected $depth = 512;

/**
* Json encode Options
* json_encode $options flag setter
*
* @param int $options
* @param int $depth
*
* @return self
*/
public function options(int $options, int $depth = 512): self
public function options(int $options): self
{
$clone = clone $this;
$clone->options = $this->filterInteger($options, 0, __METHOD__.': the options must be a positive integer or 0');
$clone->depth = $this->filterInteger($depth, 2, __METHOD__.': the depth must be a positive integer greater or equal to 2');
$clone->options = $this->filterMinRange($options, 0, __METHOD__.': the options must be a positive integer or 0');

return $clone;
}
Expand All @@ -73,7 +64,7 @@ public function convert($records)
$records = iterator_to_array($records);
}

$json = @json_encode($records, $this->options, $this->depth);
$json = @json_encode($records, $this->options, 2);
if (JSON_ERROR_NONE === json_last_error()) {
return $json;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Plugin/ColumnConsistencyValidator.php
Expand Up @@ -50,7 +50,7 @@ class ColumnConsistencyValidator
public function setColumnsCount(int $value)
{
$this->detect_columns_count = false;
$this->columns_count = $this->filterInteger($value, -1, __METHOD__.': the column count must be greater or equal to -1');
$this->columns_count = $this->filterMinRange($value, -1, __METHOD__.': the column count must be greater or equal to -1');
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Reader.php
Expand Up @@ -97,7 +97,7 @@ public function fetchDelimitersOccurrence(array $delimiters, int $nb_records = 1
return 1 == strlen($value);
};

$nb_records = $this->filterInteger($nb_records, 1, __METHOD__.': the number of rows to consider must be a valid positive integer');
$nb_records = $this->filterMinRange($nb_records, 1, __METHOD__.': the number of rows to consider must be a valid positive integer');
$delimiters = array_unique(array_filter($delimiters, $filter));
$reducer = function (array $res, string $delimiter) use ($nb_records): array {
$res[$delimiter] = $this->getCellCount($delimiter, $nb_records);
Expand Down Expand Up @@ -279,7 +279,7 @@ protected function removeBOM(array $row, int $bom_length, string $enclosure): ar
public function setHeaderOffset($offset): self
{
if (null !== $offset) {
$offset = $this->filterInteger($offset, 0, __METHOD__.': the header offset index must be a positive integer or 0');
$offset = $this->filterMinRange($offset, 0, __METHOD__.': the header offset index must be a positive integer or 0');
}

if ($offset !== $this->header_offset) {
Expand Down
4 changes: 2 additions & 2 deletions src/RecordSet.php
Expand Up @@ -156,7 +156,7 @@ public function fetchAll(): array
*/
public function fetchOne(int $offset = 0): array
{
$offset = $this->filterInteger($offset, 0, __METHOD__.': the submitted offset is invalid');
$offset = $this->filterMinRange($offset, 0, __METHOD__.': the submitted offset is invalid');
$it = new LimitIterator($this->iterator, $offset, 1);
$it->rewind();

Expand Down Expand Up @@ -209,7 +209,7 @@ protected function getColumnIndex($field, string $error_message)
throw new InvalidArgumentException(sprintf($error_message, $field));
}

$index = $this->filterInteger($field, 0, $error_message);
$index = $this->filterMinRange($field, 0, $error_message);
if (empty($this->column_names)) {
return $index;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Statement.php
Expand Up @@ -129,7 +129,7 @@ public function orderBy(callable $callable): self
*/
public function offset(int $offset): self
{
$offset = $this->filterInteger($offset, 0, __METHOD__.': the offset must be a positive integer or 0');
$offset = $this->filterMinRange($offset, 0, __METHOD__.': the offset must be a positive integer or 0');
if ($offset === $this->offset) {
return $this;
}
Expand All @@ -149,7 +149,7 @@ public function offset(int $offset): self
*/
public function limit(int $limit): self
{
$limit = $this->filterInteger($limit, -1, __METHOD__.': the limit must an integer greater or equals to -1');
$limit = $this->filterMinRange($limit, -1, __METHOD__.': the limit must an integer greater or equals to -1');
if ($limit === $this->limit) {
return $this;
}
Expand Down
24 changes: 22 additions & 2 deletions src/ValidatorTrait.php
Expand Up @@ -29,7 +29,7 @@
trait ValidatorTrait
{
/**
* Validate an integer
* Validate an integer minimal range
*
* @param int $value
* @param int $min_value
Expand All @@ -39,7 +39,7 @@ trait ValidatorTrait
*
* @return int
*/
protected function filterInteger(int $value, int $min_value, string $error_message): int
protected function filterMinRange(int $value, int $min_value, string $error_message): int
{
if ($value >= $min_value) {
return $value;
Expand Down Expand Up @@ -104,4 +104,24 @@ protected function filterColumnNames(array $keys): array

throw new InvalidArgumentException('Use a flat array with unique string values');
}

/**
* Filter encoding charset
*
* @param string $encoding
*
* @throws InvalidArgumentException if the charset is malformed
*
* @return string
*/
protected function filterEncoding(string $encoding)
{
$encoding = strtoupper(str_replace('_', '-', $encoding));
$test = filter_var($encoding, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH);
if ($test === $encoding && $encoding != '') {
return $encoding;
}

throw new InvalidArgumentException('Invalid Character Error');
}
}
2 changes: 1 addition & 1 deletion src/Writer.php
Expand Up @@ -239,7 +239,7 @@ public function setNewline(string $newline): self
public function setFlushThreshold($val): self
{
if (null !== $val) {
$val = $this->filterInteger($val, 1, __METHOD__.': The flush threshold must be a valid positive integer or null');
$val = $this->filterMinRange($val, 1, __METHOD__.': The flush threshold must be a valid positive integer or null');
}

if ($val === $this->flush_threshold) {
Expand Down

0 comments on commit 827e43c

Please sign in to comment.