From e149b4f8eb78bd8d415d722b6f1f39008e354a62 Mon Sep 17 00:00:00 2001 From: ignace nyamagana butera Date: Tue, 10 Dec 2024 14:01:27 +0100 Subject: [PATCH] Adding Writer::noEnclosure method --- CHANGELOG.md | 1 + docs/9.0/converter/html.md | 1 - docs/9.0/converter/xml.md | 2 +- docs/9.0/writer/index.md | 8 ++++---- src/HTMLConverter.php | 7 ++++--- src/JsonConverter.php | 6 +++--- src/Query/Constraint/Column.php | 2 +- src/Query/Ordering/Column.php | 16 +++++++--------- src/Writer.php | 15 ++++++++------- src/WriterTest.php | 6 +++--- src/XMLConverter.php | 7 ++++--- 11 files changed, 36 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b276a40..8caa711a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All Notable changes to `Csv` will be documented in this file ### Fixed - `JsonConverter::formatter` now accepts callable before only `Closure` where accepted. +- The protected property `Writer::$enclose_all` is no longer a boolean but an integer ### Removed diff --git a/docs/9.0/converter/html.md b/docs/9.0/converter/html.md index 2e796ed5..2c119245 100644 --- a/docs/9.0/converter/html.md +++ b/docs/9.0/converter/html.md @@ -44,7 +44,6 @@ This method sets the optional attribute name for the field name on the HTML `td`

If none is used or an empty string is given, the field name information won't be exported to the HTML table.

- ### HTMLConverter::formatter

New feature introduced in version 9.20.0

diff --git a/docs/9.0/converter/xml.md b/docs/9.0/converter/xml.md index db84f279..4f94c038 100644 --- a/docs/9.0/converter/xml.md +++ b/docs/9.0/converter/xml.md @@ -54,7 +54,7 @@ public XMLConverter::formatter(?callback $formatter): mixed ``` This method allow to apply a callback prior to converting your collection individual item. -This callback allows you to specify how each item will be converted. The formatter should +This callback allows you to specify how each item will be converted. The formatter should return an associative array suitable for conversion. ## Conversion diff --git a/docs/9.0/writer/index.md b/docs/9.0/writer/index.md index 2cf56062..a875a182 100644 --- a/docs/9.0/writer/index.md +++ b/docs/9.0/writer/index.md @@ -137,18 +137,18 @@ public Writer::forceEnclosure(): self public Writer::relaxEnclosure(): self public Writer::noEnclosure(): self public Writer::encloseAll(): bool -public Writer::encloseRelax(): bool +public Writer::encloseSelective(): bool public Writer::encloseNone(): bool ``` By default, the `Writer` adds enclosures only around records that requires them. For all other records no enclosure character is present, With this feature, you can: -- force the enclosure to be present on every record entry or CSV cell. -- completely remove the presence of enclosure +- force the enclosure to be present on every record entry or CSV cell; +- completely remove the presence of enclosure;

When this feature is activated the $escape character is completely ignored (it is the same as setting it to the empty string.)

-

When no enclosure is used, the library DOES NOT CHECK for multiline fields.

+

When no enclosure is used, the library DO NOT CHECK for multiline fields.

```php formatter = $formatter; + $clone->formatter = ($formatter instanceof Closure || null === $formatter) ? $formatter : $formatter(...); return $clone; } diff --git a/src/JsonConverter.php b/src/JsonConverter.php index 17bdadcb..53a6b6bf 100644 --- a/src/JsonConverter.php +++ b/src/JsonConverter.php @@ -104,8 +104,8 @@ final class JsonConverter public readonly int $depth; /** @var int<1, max> */ public readonly int $indentSize; - /** @var ?callable(T, array-key): mixed */ - public readonly mixed $formatter; + /** @var ?Closure(T, array-key): mixed */ + public readonly ?Closure $formatter; /** @var int<1, max> */ public readonly int $chunkSize; /** @var non-empty-string */ @@ -151,7 +151,7 @@ private function __construct(int $flags, int $depth, int $indentSize, ?callable $this->flags = $flags; $this->depth = $depth; $this->indentSize = $indentSize; - $this->formatter = $formatter; + $this->formatter = ($formatter instanceof Closure || null === $formatter) ? $formatter : $formatter(...); $this->chunkSize = $chunkSize; // Initialize settings and closure to use for conversion. diff --git a/src/Query/Constraint/Column.php b/src/Query/Constraint/Column.php index 4f4b713f..81ad21c5 100644 --- a/src/Query/Constraint/Column.php +++ b/src/Query/Constraint/Column.php @@ -54,7 +54,7 @@ public static function filterOn( } if (is_callable($operator)) { - return new self($column, Closure::fromCallable($operator), $value); + return new self($column, $operator(...), $value); } return new self( diff --git a/src/Query/Ordering/Column.php b/src/Query/Ordering/Column.php index 10ecb72a..aafe746d 100644 --- a/src/Query/Ordering/Column.php +++ b/src/Query/Ordering/Column.php @@ -68,15 +68,13 @@ public static function sortOn( default => throw new QueryException('Unknown or unsupported ordering operator value: '.$direction), }; - if (is_callable($callback)) { - $callback = Closure::fromCallable($callback); - } - - return new self( - $operator, - $column, - $callback ?? static fn (mixed $first, mixed $second): int => $first <=> $second - ); + $callback = match (true) { + null === $callback => static fn (mixed $first, mixed $second): int => $first <=> $second, + $callback instanceof Closure => $callback, + default => $callback(...), + }; + + return new self($operator, $column, $callback); } /** diff --git a/src/Writer.php b/src/Writer.php index d6e6d2d5..f1c3c808 100644 --- a/src/Writer.php +++ b/src/Writer.php @@ -31,8 +31,8 @@ class Writer extends AbstractCsv implements TabularDataWriter { protected const ENCLOSE_ALL = 1; - protected const ENCLOSE_RELAX = 2; - protected const ENCLOSE_NONE = 3; + protected const ENCLOSE_SELECTIVE = 0; + protected const ENCLOSE_NONE = -2; protected const STREAM_FILTER_MODE = STREAM_FILTER_WRITE; /** @var array callable collection to format the record before insertion. */ @@ -95,7 +95,7 @@ public function encloseAll(): bool } /** - * Tells whether new entries will all be enclosed on writing. + * Tells whether new entries will never be enclosed on writing. */ public function encloseNone(): bool { @@ -103,11 +103,12 @@ public function encloseNone(): bool } /** - * Tells whether new entries will all be enclosed on writing. + * Tells whether new entries will be selectively enclosed on writing + * if the field content requires encoding. */ - public function encloseRelax(): bool + public function encloseSelective(): bool { - return self::ENCLOSE_RELAX === $this->enclose_all; + return self::ENCLOSE_SELECTIVE === $this->enclose_all; } /** @@ -227,7 +228,7 @@ public function setFlushThreshold(?int $threshold): self public function relaxEnclosure(): self { - $this->enclose_all = self::ENCLOSE_RELAX; + $this->enclose_all = self::ENCLOSE_SELECTIVE; $this->resetProperties(); return $this; diff --git a/src/WriterTest.php b/src/WriterTest.php index 85104f37..f29d185f 100644 --- a/src/WriterTest.php +++ b/src/WriterTest.php @@ -96,7 +96,7 @@ public function testInsertNormalFile(): void self::assertFalse($csv->encloseAll()); self::assertFalse($csv->encloseNone()); - self::assertTrue($csv->encloseRelax()); + self::assertTrue($csv->encloseSelective()); self::assertStringContainsString('jane,doe,jane.doe@example.com', $csv->toString()); } @@ -310,7 +310,7 @@ public function testEncloseAll(): void self::assertTrue($csv->encloseAll()); self::assertFalse($csv->encloseNone()); - self::assertFalse($csv->encloseRelax()); + self::assertFalse($csv->encloseSelective()); self::assertStringContainsString($expected, $csv->toString()); } @@ -344,7 +344,7 @@ public function testEncloseNothing(): void self::assertFalse($csv->encloseAll()); self::assertTrue($csv->encloseNone()); - self::assertFalse($csv->encloseRelax()); + self::assertFalse($csv->encloseSelective()); self::assertStringContainsString($expected, $csv->toString()); } } diff --git a/src/XMLConverter.php b/src/XMLConverter.php index be6146bd..2f69fcb7 100644 --- a/src/XMLConverter.php +++ b/src/XMLConverter.php @@ -13,6 +13,7 @@ namespace League\Csv; +use Closure; use DOMAttr; use DOMDocument; use DOMElement; @@ -34,8 +35,8 @@ class XMLConverter protected string $column_attr = ''; /** XML offset attribute name. */ protected string $offset_attr = ''; - /** @var ?callable(array, array-key): array */ - public mixed $formatter = null; + /** @var ?Closure(array, array-key): array */ + public ?Closure $formatter = null; public static function create(): self { @@ -161,7 +162,7 @@ public function rootElement(string $node_name): self public function formatter(?callable $formatter): self { $clone = clone $this; - $clone->formatter = $formatter; + $clone->formatter = ($formatter instanceof Closure || null === $formatter) ? $formatter : $formatter(...); return $clone; }