Skip to content

Commit

Permalink
Merge pull request #29 from localheinz/feature/mutate
Browse files Browse the repository at this point in the history
Enhancement: Allow to mutate format
  • Loading branch information
localheinz authored Jan 27, 2018
2 parents 511d004 + 602328a commit 97d20eb
Show file tree
Hide file tree
Showing 3 changed files with 207 additions and 13 deletions.
48 changes: 47 additions & 1 deletion src/Format/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

final class Format implements FormatInterface
{
/**
* Constant for a regular expression matching valid indents.
*/
private const PATTERN_INDENT = '/^[ \t]+$/';

/**
* @var int
*/
Expand Down Expand Up @@ -46,7 +51,7 @@ public function __construct(int $jsonEncodeOptions, string $indent, bool $hasFin
));
}

if (1 !== \preg_match('/^[ \t]+$/', $indent)) {
if (1 !== \preg_match(self::PATTERN_INDENT, $indent)) {
throw new \InvalidArgumentException(\sprintf(
'"%s" is not a valid indent.',
$indent
Expand All @@ -72,4 +77,45 @@ public function hasFinalNewLine(): bool
{
return $this->hasFinalNewLine;
}

public function withJsonEncodeOptions(int $jsonEncodeOptions): FormatInterface
{
if (0 > $jsonEncodeOptions) {
throw new \InvalidArgumentException(\sprintf(
'"%s" is not valid options for json_encode().',
$jsonEncodeOptions
));
}

$mutated = clone $this;

$mutated->jsonEncodeOptions = $jsonEncodeOptions;

return $mutated;
}

public function withIndent(string $indent): FormatInterface
{
if (1 !== \preg_match(self::PATTERN_INDENT, $indent)) {
throw new \InvalidArgumentException(\sprintf(
'"%s" is not a valid indent.',
$indent
));
}

$mutated = clone $this;

$mutated->indent = $indent;

return $mutated;
}

public function withHasFinalNewLine(bool $hasFinalNewLine): FormatInterface
{
$mutated = clone $this;

$mutated->hasFinalNewLine = $hasFinalNewLine;

return $mutated;
}
}
20 changes: 20 additions & 0 deletions src/Format/FormatInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,24 @@ public function jsonEncodeOptions(): int;
public function indent(): string;

public function hasFinalNewLine(): bool;

/**
* @param string $indent
*
* @throws \InvalidArgumentException
*
* @return FormatInterface
*/
public function withIndent(string $indent): self;

/**
* @param int $jsonEncodeOptions
*
* @throws \InvalidArgumentException
*
* @return FormatInterface
*/
public function withJsonEncodeOptions(int $jsonEncodeOptions): self;

public function withHasFinalNewLine(bool $hasFinalNewLine): self;
}
152 changes: 140 additions & 12 deletions test/Unit/Format/FormatTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,23 +106,151 @@ public function testConstructorSetsValues(string $indent, bool $hasFinalNewLine)

public function providerJsonIndentAndFinalNewLine(): \Generator
{
$indents = [
' ',
"\t",
];

$hasFinalNewLines = [
true,
false,
];

foreach ($indents as $indent) {
foreach ($hasFinalNewLines as $hasFinalNewLine) {
foreach ($this->indents() as $indent) {
foreach ($this->hasFinalNewLines() as $hasFinalNewLine) {
yield [
$indent,
$hasFinalNewLine,
];
}
}
}

public function testWithJsonEncodeOptionsRejectsInvalidJsonEncodeOptions(): void
{
$jsonEncodeOptions = -1;

$format = new Format(
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
' ',
true
);

$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage(\sprintf(
'"%s" is not valid options for json_encode().',
$jsonEncodeOptions
));

$format->withJsonEncodeOptions($jsonEncodeOptions);
}

public function testWithIndentClonesFormatAndSetsJsonEncodeOptions(): void
{
$format = new Format(
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
' ',
true
);

$jsonEncodeOptions = 9000;

$mutated = $format->withJsonEncodeOptions($jsonEncodeOptions);

$this->assertInstanceOf(FormatInterface::class, $mutated);
$this->assertNotSame($format, $mutated);
$this->assertSame($jsonEncodeOptions, $mutated->jsonEncodeOptions());
}

/**
* @dataProvider providerInvalidIndent
*
* @param string $indent
*/
public function testWithIndentRejectsInvalidIndent(string $indent): void
{
$format = new Format(
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
' ',
true
);

$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage(\sprintf(
'"%s" is not a valid indent.',
$indent
));

$format->withIndent($indent);
}

/**
* @dataProvider providerIndent
*
* @param string $indent
*/
public function testWithIndentClonesFormatAndSetsIndent(string $indent): void
{
$format = new Format(
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
' ',
true
);

$mutated = $format->withIndent($indent);

$this->assertInstanceOf(FormatInterface::class, $mutated);
$this->assertNotSame($format, $mutated);
$this->assertSame($indent, $mutated->indent());
}

public function providerIndent(): \Generator
{
foreach ($this->indents() as $key => $indent) {
yield $key => [
$indent,
];
}
}

/**
* @dataProvider providerHasFinalNewLine
*
* @param bool $hasFinalNewLine
*/
public function testWithHasFinalNewLineClonesFormatAndSetsFinalNewLine(bool $hasFinalNewLine): void
{
$format = new Format(
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES,
' ',
false
);

$mutated = $format->withHasFinalNewLine($hasFinalNewLine);

$this->assertInstanceOf(FormatInterface::class, $mutated);
$this->assertNotSame($format, $mutated);
$this->assertSame($hasFinalNewLine, $mutated->hasFinalNewLine());
}

public function providerHasFinalNewLine(): \Generator
{
foreach ($this->hasFinalNewLines() as $key => $hasFinalNewLine) {
yield $key => [
$hasFinalNewLine,
];
}
}

/**
* @return string[]
*/
private function indents(): array
{
return [
'space' => ' ',
'tab' => "\t",
];
}

/**
* @return bool[]
*/
private function hasFinalNewLines(): array
{
return [
'yes' => true,
'no' => false,
];
}
}

0 comments on commit 97d20eb

Please sign in to comment.