From 473ecf420ec619f674a2216a4e2d8522961d2fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=B6ller?= Date: Mon, 13 Aug 2018 09:49:50 +0200 Subject: [PATCH] Enhancement: Extract NewLine value object --- src/Format/Format.php | 41 +++----- src/Format/FormatInterface.php | 11 +-- src/Format/Formatter.php | 2 +- src/Format/NewLine.php | 51 ++++++++++ src/Format/NewLineInterface.php | 19 ++++ src/Format/Sniffer.php | 6 +- test/Unit/Format/FormatTest.php | 154 +++++------------------------ test/Unit/Format/FormatterTest.php | 27 +++-- test/Unit/Format/NewLineTest.php | 96 ++++++++++++++++++ test/Unit/Format/SnifferTest.php | 6 +- 10 files changed, 226 insertions(+), 187 deletions(-) create mode 100644 src/Format/NewLine.php create mode 100644 src/Format/NewLineInterface.php create mode 100644 test/Unit/Format/NewLineTest.php diff --git a/src/Format/Format.php b/src/Format/Format.php index d1de93e1..64d1dc28 100644 --- a/src/Format/Format.php +++ b/src/Format/Format.php @@ -15,11 +15,6 @@ final class Format implements FormatInterface { - /** - * Constant for a regular expression matching valid new-line character sequence. - */ - private const PATTERN_NEW_LINE = '/^(?>\r\n|\n|\r)$/'; - /** * @var int */ @@ -31,24 +26,24 @@ final class Format implements FormatInterface private $indent; /** - * @var bool + * @var NewLineInterface */ - private $hasFinalNewLine; + private $newLine; /** - * @var string + * @var bool */ - private $newLine; + private $hasFinalNewLine; /** - * @param int $jsonEncodeOptions - * @param IndentInterface $indent - * @param string $newLine - * @param bool $hasFinalNewLine + * @param int $jsonEncodeOptions + * @param IndentInterface $indent + * @param NewLineInterface $newLine + * @param bool $hasFinalNewLine * * @throws \InvalidArgumentException */ - public function __construct(int $jsonEncodeOptions, IndentInterface $indent, string $newLine, bool $hasFinalNewLine) + public function __construct(int $jsonEncodeOptions, IndentInterface $indent, NewLineInterface $newLine, bool $hasFinalNewLine) { if (0 > $jsonEncodeOptions) { throw new \InvalidArgumentException(\sprintf( @@ -57,13 +52,6 @@ public function __construct(int $jsonEncodeOptions, IndentInterface $indent, str )); } - if (1 !== \preg_match(self::PATTERN_NEW_LINE, $newLine)) { - throw new \InvalidArgumentException(\sprintf( - '"%s" is not a valid new-line character sequence.', - $newLine - )); - } - $this->jsonEncodeOptions = $jsonEncodeOptions; $this->indent = $indent; $this->newLine = $newLine; @@ -80,7 +68,7 @@ public function indent(): IndentInterface return $this->indent; } - public function newLine(): string + public function newLine(): NewLineInterface { return $this->newLine; } @@ -115,15 +103,8 @@ public function withIndent(IndentInterface $indent): FormatInterface return $mutated; } - public function withNewLine(string $newLine): FormatInterface + public function withNewLine(NewLineInterface $newLine): FormatInterface { - if (1 !== \preg_match(self::PATTERN_NEW_LINE, $newLine)) { - throw new \InvalidArgumentException(\sprintf( - '"%s" is not a valid new-line character sequence.', - $newLine - )); - } - $mutated = clone $this; $mutated->newLine = $newLine; diff --git a/src/Format/FormatInterface.php b/src/Format/FormatInterface.php index e2347a4f..d5356e88 100644 --- a/src/Format/FormatInterface.php +++ b/src/Format/FormatInterface.php @@ -19,7 +19,7 @@ public function jsonEncodeOptions(): int; public function indent(): IndentInterface; - public function newLine(): string; + public function newLine(): NewLineInterface; public function hasFinalNewLine(): bool; @@ -34,14 +34,7 @@ public function withJsonEncodeOptions(int $jsonEncodeOptions): self; public function withIndent(IndentInterface $indent): self; - /** - * @param string $newLine - * - * @throws \InvalidArgumentException - * - * @return FormatInterface - */ - public function withNewLine(string $newLine): self; + public function withNewLine(NewLineInterface $newLine): self; public function withHasFinalNewLine(bool $hasFinalNewLine): self; } diff --git a/src/Format/Formatter.php b/src/Format/Formatter.php index 85889129..a27b4318 100644 --- a/src/Format/Formatter.php +++ b/src/Format/Formatter.php @@ -46,7 +46,7 @@ public function format(string $json, FormatInterface $format): string $printed = $this->printer->print( $encoded, (string) $format->indent(), - $format->newLine() + (string) $format->newLine() ); if (!$format->hasFinalNewLine()) { diff --git a/src/Format/NewLine.php b/src/Format/NewLine.php new file mode 100644 index 00000000..08554be4 --- /dev/null +++ b/src/Format/NewLine.php @@ -0,0 +1,51 @@ +string = $string; + } + + public function __toString(): string + { + return $this->string; + } + + /** + * @param string $string + * + * @throws \InvalidArgumentException + * + * @return NewLineInterface + */ + public static function fromString(string $string): NewLineInterface + { + if (1 !== \preg_match('/^(?>\r\n|\n|\r)$/', $string)) { + throw new \InvalidArgumentException(\sprintf( + '"%s" is not a valid new-line character sequence.', + $string + )); + } + + return new self($string); + } +} diff --git a/src/Format/NewLineInterface.php b/src/Format/NewLineInterface.php new file mode 100644 index 00000000..b51edf67 --- /dev/null +++ b/src/Format/NewLineInterface.php @@ -0,0 +1,19 @@ +\r\n|\n|\r)/', $json, $match)) { - return $match['newLine']; + return NewLine::fromString($match['newLine']); } - return \PHP_EOL; + return NewLine::fromString(\PHP_EOL); } private function hasFinalNewLine(string $json): bool diff --git a/test/Unit/Format/FormatTest.php b/test/Unit/Format/FormatTest.php index 6af87aa8..310892f8 100644 --- a/test/Unit/Format/FormatTest.php +++ b/test/Unit/Format/FormatTest.php @@ -16,6 +16,7 @@ use Localheinz\Json\Normalizer\Format\Format; use Localheinz\Json\Normalizer\Format\FormatInterface; use Localheinz\Json\Normalizer\Format\IndentInterface; +use Localheinz\Json\Normalizer\Format\NewLineInterface; use Localheinz\Test\Util\Helper; use PHPUnit\Framework; @@ -35,7 +36,7 @@ public function testConstructorRejectsInvalidEncodeOptions(): void { $jsonEncodeOptions = -1; $indent = $this->prophesize(IndentInterface::class); - $newLine = \PHP_EOL; + $newLine = $this->prophesize(NewLineInterface::class); $hasFinalNewLine = true; $this->expectException(\InvalidArgumentException::class); @@ -47,92 +48,36 @@ public function testConstructorRejectsInvalidEncodeOptions(): void new Format( $jsonEncodeOptions, $indent->reveal(), - $newLine, + $newLine->reveal(), $hasFinalNewLine ); } /** - * @dataProvider providerInvalidNewLine - * - * @param string $newLine - */ - public function testConstructorRejectsInvalidNewLine(string $newLine): void - { - $jsonEncodeOptions = 0; - $indent = $this->prophesize(IndentInterface::class); - $hasFinalNewLine = true; - - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(\sprintf( - '"%s" is not a valid new-line character sequence.', - $newLine - )); - - new Format( - $jsonEncodeOptions, - $indent->reveal(), - $newLine, - $hasFinalNewLine - ); - } - - public function providerInvalidNewLine(): \Generator - { - $values = [ - "\t", - " \r ", - " \r\n ", - " \n ", - ' ', - "\f", - "\x0b", - "\x85", - ]; - - foreach ($values as $value) { - yield [ - $value, - ]; - } - } - - /** - * @dataProvider providerNewLineAndFinalNewLine + * @dataProvider providerHasFinalNewLine * * @param string $newLine * @param bool $hasFinalNewLine */ - public function testConstructorSetsValues(string $newLine, bool $hasFinalNewLine): void + public function testConstructorSetsValues(bool $hasFinalNewLine): void { $jsonEncodeOptions = \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES; $indent = $this->prophesize(IndentInterface::class); + $newLine = $this->prophesize(NewLineInterface::class); $format = new Format( $jsonEncodeOptions, $indent->reveal(), - $newLine, + $newLine->reveal(), $hasFinalNewLine ); $this->assertSame($jsonEncodeOptions, $format->jsonEncodeOptions()); $this->assertSame($indent->reveal(), $format->indent()); - $this->assertSame($newLine, $format->newLine()); + $this->assertSame($newLine->reveal(), $format->newLine()); $this->assertSame($hasFinalNewLine, $format->hasFinalNewLine()); } - public function providerNewLineAndFinalNewLine(): \Generator - { - foreach ($this->newLines() as $newLine) { - foreach ($this->hasFinalNewLines() as $hasFinalNewLine) { - yield [ - $newLine, - $hasFinalNewLine, - ]; - } - } - } - public function testWithJsonEncodeOptionsRejectsInvalidJsonEncodeOptions(): void { $jsonEncodeOptions = -1; @@ -140,7 +85,7 @@ public function testWithJsonEncodeOptionsRejectsInvalidJsonEncodeOptions(): void $format = new Format( \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES, $this->prophesize(IndentInterface::class)->reveal(), - \PHP_EOL, + $this->prophesize(NewLineInterface::class)->reveal(), true ); @@ -158,7 +103,7 @@ public function testWithJsonEncodeOptionsClonesFormatAndSetsJsonEncodeOptions(): $format = new Format( \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES, $this->prophesize(IndentInterface::class)->reveal(), - \PHP_EOL, + $this->prophesize(NewLineInterface::class)->reveal(), true ); @@ -178,7 +123,7 @@ public function testWithIndentClonesFormatAndSetsIndent(): void $format = new Format( \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES, $this->prophesize(IndentInterface::class)->reveal(), - \PHP_EOL, + $this->prophesize(NewLineInterface::class)->reveal(), true ); @@ -189,57 +134,22 @@ public function testWithIndentClonesFormatAndSetsIndent(): void $this->assertSame($indent->reveal(), $mutated->indent()); } - /** - * @dataProvider providerInvalidNewLine - * - * @param string $newLine - */ - public function testWithNewLineRejectsInvalidNewLine(string $newLine): void + public function testWithNewLineClonesFormatAndSetsNewLine(): void { - $format = new Format( - \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES, - $this->prophesize(IndentInterface::class)->reveal(), - \PHP_EOL, - true - ); - - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage(\sprintf( - '"%s" is not a valid new-line character sequence.', - $newLine - )); + $newLine = $this->prophesize(NewLineInterface::class); - $format->withNewLine($newLine); - } - - /** - * @dataProvider providerNewLine - * - * @param string $newLine - */ - public function testWithNewLineClonesFormatAndSetsNewLine(string $newLine): void - { $format = new Format( \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES, $this->prophesize(IndentInterface::class)->reveal(), - \PHP_EOL, + $this->prophesize(NewLineInterface::class)->reveal(), true ); - $mutated = $format->withNewLine($newLine); + $mutated = $format->withNewLine($newLine->reveal()); $this->assertInstanceOf(FormatInterface::class, $mutated); $this->assertNotSame($format, $mutated); - $this->assertSame($newLine, $mutated->newLine()); - } - - public function providerNewLine(): \Generator - { - foreach ($this->newLines() as $newLine) { - yield [ - $newLine, - ]; - } + $this->assertSame($newLine->reveal(), $mutated->newLine()); } /** @@ -252,7 +162,7 @@ public function testWithHasFinalNewLineClonesFormatAndSetsFinalNewLine(bool $has $format = new Format( \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES, $this->prophesize(IndentInterface::class)->reveal(), - \PHP_EOL, + $this->prophesize(NewLineInterface::class)->reveal(), false ); @@ -265,33 +175,15 @@ public function testWithHasFinalNewLineClonesFormatAndSetsFinalNewLine(bool $has public function providerHasFinalNewLine(): \Generator { - foreach ($this->hasFinalNewLines() as $key => $hasFinalNewLine) { + $hasFinalNewLines = [ + 'yes' => true, + 'no' => false, + ]; + + foreach ($hasFinalNewLines as $key => $hasFinalNewLine) { yield $key => [ $hasFinalNewLine, ]; } } - - /** - * @return string[] - */ - private function newLines(): array - { - return [ - "\r\n", - "\n", - "\r", - ]; - } - - /** - * @return bool[] - */ - private function hasFinalNewLines(): array - { - return [ - 'yes' => true, - 'no' => false, - ]; - } } diff --git a/test/Unit/Format/FormatterTest.php b/test/Unit/Format/FormatterTest.php index 19801517..f06569de 100644 --- a/test/Unit/Format/FormatterTest.php +++ b/test/Unit/Format/FormatterTest.php @@ -17,6 +17,7 @@ use Localheinz\Json\Normalizer\Format\Formatter; use Localheinz\Json\Normalizer\Format\FormatterInterface; use Localheinz\Json\Normalizer\Format\IndentInterface; +use Localheinz\Json\Normalizer\Format\NewLineInterface; use Localheinz\Json\Printer; use Localheinz\Test\Util\Helper; use PHPUnit\Framework; @@ -29,7 +30,7 @@ final class FormatterTest extends Framework\TestCase { use Helper; - public function testImplementsFormatterInterface() + public function testImplementsFormatterInterface(): void { $this->assertClassImplementsInterface(FormatterInterface::class, Formatter::class); } @@ -63,6 +64,11 @@ public function testFormatEncodesWithJsonEncodeOptionsIndentsAndPossiblySuffixes $jsonEncodeOptions = $faker->numberBetween(1); $indentString = \str_repeat(' ', $faker->numberBetween(1, 5)); + $newLineString = $faker->randomElement([ + "\r\n", + "\n", + "\r", + ]); $indent = $this->prophesize(IndentInterface::class); @@ -71,11 +77,12 @@ public function testFormatEncodesWithJsonEncodeOptionsIndentsAndPossiblySuffixes ->shouldBeCalled() ->willReturn($indentString); - $newLine = $faker->randomElement([ - "\r\n", - "\n", - "\r", - ]); + $newLine = $this->prophesize(NewLineInterface::class); + + $newLine + ->__toString() + ->shouldBeCalled() + ->willReturn($newLineString); $json = <<<'JSON' { @@ -106,12 +113,12 @@ public function testFormatEncodesWithJsonEncodeOptionsIndentsAndPossiblySuffixes $format ->indent() ->shouldBeCalled() - ->willReturn($indent); + ->willReturn($indent->reveal()); $format ->newLine() ->shouldBeCalled() - ->willReturn($newLine); + ->willReturn($newLine->reveal()); $format ->hasFinalNewLine() @@ -124,7 +131,7 @@ public function testFormatEncodesWithJsonEncodeOptionsIndentsAndPossiblySuffixes ->print( Argument::is($encoded), Argument::is($indentString), - Argument::is($newLine) + Argument::is($newLineString) ) ->shouldBeCalled() ->willReturn($printed); @@ -136,7 +143,7 @@ public function testFormatEncodesWithJsonEncodeOptionsIndentsAndPossiblySuffixes $format->reveal() ); - $suffix = $hasFinalNewLine ? $newLine : ''; + $suffix = $hasFinalNewLine ? $newLineString : ''; $this->assertSame($printed . $suffix, $formatted); } diff --git a/test/Unit/Format/NewLineTest.php b/test/Unit/Format/NewLineTest.php new file mode 100644 index 00000000..0d259cb7 --- /dev/null +++ b/test/Unit/Format/NewLineTest.php @@ -0,0 +1,96 @@ +assertClassImplementsInterface(NewLineInterface::class, NewLine::class); + } + + /** + * @dataProvider providerInvalidNewLineString + * + * @param string $string + */ + public function testFromStringRejectsInvalidNewLineString(string $string): void + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage(\sprintf( + '"%s" is not a valid new-line character sequence.', + $string + )); + + NewLine::fromString($string); + } + + public function providerInvalidNewLineString(): \Generator + { + $strings = [ + "\t", + " \r ", + " \r\n ", + " \n ", + ' ', + "\f", + "\x0b", + "\x85", + ]; + + foreach ($strings as $string) { + yield [ + $string, + ]; + } + } + + /** + * @dataProvider providerValidNewLineString + * + * @param string $string + */ + public function testFromStringReturnsNewLine(string $string): void + { + $newLine = NewLine::fromString($string); + + $this->assertInstanceOf(NewLineInterface::class, $newLine); + $this->assertSame($string, $newLine->__toString()); + } + + public function providerValidNewLineString(): \Generator + { + $strings = [ + "\n", + "\r", + "\r\n", + ]; + + foreach ($strings as $string) { + yield [ + $string, + ]; + } + } +} diff --git a/test/Unit/Format/SnifferTest.php b/test/Unit/Format/SnifferTest.php index ad78b2f8..7d1d0dd9 100644 --- a/test/Unit/Format/SnifferTest.php +++ b/test/Unit/Format/SnifferTest.php @@ -251,7 +251,7 @@ public function testSniffReturnsFormatWithDefaultNewLineIfUnableToSniff(string $ $format = $sniffer->sniff($json); $this->assertInstanceOf(FormatInterface::class, $format); - $this->assertSame(\PHP_EOL, $format->newLine()); + $this->assertSame(\PHP_EOL, $format->newLine()->__toString()); } /** @@ -270,7 +270,7 @@ public function testSniffReturnsFormatWithNewLineSniffedFromArray(string $newLin $format = $sniffer->sniff($json); $this->assertInstanceOf(FormatInterface::class, $format); - $this->assertSame($newLine, $format->newLine()); + $this->assertSame($newLine, $format->newLine()->__toString()); } /** @@ -289,7 +289,7 @@ public function testSniffReturnsFormatWithNewLineNewLineSniffedFromObject(string $format = $sniffer->sniff($json); $this->assertInstanceOf(FormatInterface::class, $format); - $this->assertSame($newLine, $format->newLine()); + $this->assertSame($newLine, $format->newLine()->__toString()); } public function providerNewLine(): \Generator