Skip to content

Commit

Permalink
refactor: Move code from matchers to formatters
Browse files Browse the repository at this point in the history
  • Loading branch information
tienvx committed Dec 31, 2023
1 parent 9d2c67d commit a98ca6f
Show file tree
Hide file tree
Showing 37 changed files with 394 additions and 160 deletions.
20 changes: 20 additions & 0 deletions src/PhpPact/Consumer/Matcher/Formatters/MinimalFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters;

use PhpPact\Consumer\Matcher\Model\FormatterInterface;
use PhpPact\Consumer\Matcher\Model\GeneratorInterface;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class MinimalFormatter implements FormatterInterface
{
/**
* @return array<string, string>
*/
public function format(MatcherInterface $matcher, ?GeneratorInterface $generator, mixed $value): array
{
return [
'pact:matcher:type' => $matcher->getType(),
] + $matcher->getAttributes()->getData();
}
}
26 changes: 26 additions & 0 deletions src/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters;

use PhpPact\Consumer\Matcher\Model\FormatterInterface;
use PhpPact\Consumer\Matcher\Model\GeneratorInterface;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class ValueOptionalFormatter implements FormatterInterface
{
/**
* @return array<string, mixed>
*/
public function format(MatcherInterface $matcher, ?GeneratorInterface $generator, mixed $value): array
{
$data = [
'pact:matcher:type' => $matcher->getType(),
];

if ($generator) {
return $data + ['pact:generator:type' => $generator->getType()] + $matcher->getAttributes()->merge($generator->getAttributes())->getData();
}

return $data + $matcher->getAttributes()->getData() + ['value' => $value];
}
}
17 changes: 17 additions & 0 deletions src/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters;

use PhpPact\Consumer\Matcher\Model\GeneratorInterface;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class ValueRequiredFormatter extends ValueOptionalFormatter
{
/**
* @return array<string, mixed>
*/
public function format(MatcherInterface $matcher, ?GeneratorInterface $generator, mixed $value): array
{
return parent::format($matcher, $generator, $value) + ['value' => $value];
}
}
1 change: 1 addition & 0 deletions src/PhpPact/Consumer/Matcher/Matchers/AbstractDateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ abstract class AbstractDateTime extends GeneratorAwareMatcher
{
public function __construct(protected string $format, private ?string $value = null)
{
parent::__construct();
}

/**
Expand Down
49 changes: 49 additions & 0 deletions src/PhpPact/Consumer/Matcher/Matchers/AbstractMatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace PhpPact\Consumer\Matcher\Matchers;

use PhpPact\Consumer\Matcher\Formatters\ValueOptionalFormatter;
use PhpPact\Consumer\Matcher\Model\Attributes;
use PhpPact\Consumer\Matcher\Model\FormatterAwareInterface;
use PhpPact\Consumer\Matcher\Model\FormatterInterface;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

abstract class AbstractMatcher implements MatcherInterface, FormatterAwareInterface
{
private FormatterInterface $formatter;

public function __construct()
{
$this->formatter = new ValueOptionalFormatter();
}

public function setFormatter(FormatterInterface $formatter): void
{
$this->formatter = $formatter;
}

public function getFormatter(): FormatterInterface
{
return $this->formatter;
}

/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
{
return $this->getFormatter()->format($this, null, $this->getValue());
}

public function getAttributes(): Attributes
{
return new Attributes($this, $this->getAttributesData());
}

/**
* @return array<string, mixed>
*/
abstract protected function getAttributesData(): array;

abstract protected function getValue(): mixed;
}
20 changes: 13 additions & 7 deletions src/PhpPact/Consumer/Matcher/Matchers/ArrayContains.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,35 @@

namespace PhpPact\Consumer\Matcher\Matchers;

use PhpPact\Consumer\Matcher\Model\MatcherInterface;
use PhpPact\Consumer\Matcher\Formatters\MinimalFormatter;

/**
* Checks if all the variants are present in an array.
*/
class ArrayContains implements MatcherInterface
class ArrayContains extends AbstractMatcher
{
/**
* @param array<mixed> $variants
*/
public function __construct(private array $variants)
{
$this->setFormatter(new MinimalFormatter());
}

/**
* @return array<string, mixed>
*/
public function jsonSerialize(): array
protected function getAttributesData(): array
{
return [
'pact:matcher:type' => $this->getType(),
'variants' => array_values($this->variants),
];
return ['variants' => array_values($this->variants)];
}

/**
* @todo Change return type to `null`
*/
protected function getValue(): mixed
{
return null;
}

public function getType(): string
Expand Down
1 change: 1 addition & 0 deletions src/PhpPact/Consumer/Matcher/Matchers/Boolean.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public function __construct(private ?bool $value = null)
if ($value === null) {
$this->setGenerator(new RandomBoolean());
}
parent::__construct();
}

public function getType(): string
Expand Down
20 changes: 9 additions & 11 deletions src/PhpPact/Consumer/Matcher/Matchers/ContentType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,24 @@

namespace PhpPact\Consumer\Matcher\Matchers;

use PhpPact\Consumer\Matcher\Model\MatcherInterface;

/**
* Match binary data by its content type (magic file check)
*/
class ContentType implements MatcherInterface
class ContentType extends AbstractMatcher
{
public function __construct(private string $contentType)
{
parent::__construct();
}

protected function getAttributesData(): array
{
return [];
}

/**
* @return array<string, string>
*/
public function jsonSerialize(): array
protected function getValue(): string
{
return [
'value' => $this->contentType,
'pact:matcher:type' => $this->getType(),
];
return $this->contentType;
}

public function getType(): string
Expand Down
1 change: 1 addition & 0 deletions src/PhpPact/Consumer/Matcher/Matchers/Decimal.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public function __construct(private ?float $value = null)
if ($value === null) {
$this->setGenerator(new RandomDecimal());
}
parent::__construct();
}

public function getType(): string
Expand Down
21 changes: 13 additions & 8 deletions src/PhpPact/Consumer/Matcher/Matchers/EachKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,31 @@
/**
* Allows defining matching rules to apply to the keys in a map
*/
class EachKey implements MatcherInterface
class EachKey extends AbstractMatcher
{
/**
* @param array<mixed>|object $value
* @param MatcherInterface[] $rules
*/
public function __construct(private object|array $value, private array $rules)
{
parent::__construct();
}

/**
* @return array<string, mixed>
* @return array<string, MatcherInterface[]>
*/
public function jsonSerialize(): array
protected function getAttributesData(): array
{
return [
'pact:matcher:type' => $this->getType(),
'value' => $this->value,
'rules' => array_map(fn (MatcherInterface $rule) => $rule, $this->rules),
];
return ['rules' => array_map(fn (MatcherInterface $rule) => $rule, $this->rules)];
}

/**
* @return array<mixed>|object
*/
protected function getValue(): object|array
{
return $this->value;
}

public function getType(): string
Expand Down
21 changes: 13 additions & 8 deletions src/PhpPact/Consumer/Matcher/Matchers/EachValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,31 @@
/**
* Allows defining matching rules to apply to the values in a collection. For maps, delgates to the Values matcher.
*/
class EachValue implements MatcherInterface
class EachValue extends AbstractMatcher
{
/**
* @param array<mixed>|object $value
* @param MatcherInterface[] $rules
*/
public function __construct(private object|array $value, private array $rules)
{
parent::__construct();
}

/**
* @return array<string, mixed>
* @return array<string, MatcherInterface[]>
*/
public function jsonSerialize(): array
protected function getAttributesData(): array
{
return [
'pact:matcher:type' => $this->getType(),
'value' => $this->value,
'rules' => array_map(fn (MatcherInterface $rule) => $rule, $this->rules),
];
return ['rules' => array_map(fn (MatcherInterface $rule) => $rule, $this->rules)];
}

/**
* @return array<mixed>|object
*/
protected function getValue(): object|array
{
return $this->value;
}

public function getType(): string
Expand Down
19 changes: 10 additions & 9 deletions src/PhpPact/Consumer/Matcher/Matchers/Equality.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,30 @@

namespace PhpPact\Consumer\Matcher\Matchers;

use PhpPact\Consumer\Matcher\Model\MatcherInterface;

/**
* This is the default matcher, and relies on the equals operator
*/
class Equality implements MatcherInterface
class Equality extends AbstractMatcher
{
/**
* @param object|array<mixed>|string|float|int|bool|null $value
*/
public function __construct(private object|array|string|float|int|bool|null $value)
{
parent::__construct();
}

protected function getAttributesData(): array
{
return [];
}

/**
* @return array<string, mixed>
* @return object|array<mixed>|string|float|int|bool|null
*/
public function jsonSerialize(): array
protected function getValue(): object|array|string|float|int|bool|null
{
return [
'pact:matcher:type' => $this->getType(),
'value' => $this->value
];
return $this->value;
}

public function getType(): string
Expand Down
29 changes: 3 additions & 26 deletions src/PhpPact/Consumer/Matcher/Matchers/GeneratorAwareMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@

use PhpPact\Consumer\Matcher\Exception\GeneratorNotRequiredException;
use PhpPact\Consumer\Matcher\Exception\GeneratorRequiredException;
use PhpPact\Consumer\Matcher\Model\Attributes;
use PhpPact\Consumer\Matcher\Model\GeneratorAwareInterface;
use PhpPact\Consumer\Matcher\Model\GeneratorInterface;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

abstract class GeneratorAwareMatcher implements MatcherInterface, GeneratorAwareInterface
abstract class GeneratorAwareMatcher extends AbstractMatcher implements GeneratorAwareInterface
{
private ?GeneratorInterface $generator = null;

Expand All @@ -28,37 +26,16 @@ public function getGenerator(): ?GeneratorInterface
*/
public function jsonSerialize(): array
{
$data = [
'pact:matcher:type' => $this->getType(),
];

if (null === $this->getValue()) {
if (!$this->generator) {
throw new GeneratorRequiredException(sprintf("Generator is required for matcher '%s' when example value is not set", $this->getType()));
}

return $data + ['pact:generator:type' => $this->generator->getType()] + $this->getMergedAttributes()->getData();
return $this->getFormatter()->format($this, $this->generator, null);
} elseif ($this->generator) {
throw new GeneratorNotRequiredException(sprintf("Generator '%s' is not required for matcher '%s' when example value is set", $this->generator->getType(), $this->getType()));
}

return $data + $this->getAttributes()->getData() + ['value' => $this->getValue()];
}

protected function getAttributes(): Attributes
{
return new Attributes($this, $this->getAttributesData());
}

protected function getMergedAttributes(): Attributes
{
return $this->getAttributes()->merge($this->generator->getAttributes());
return $this->getFormatter()->format($this, $this->generator, $this->getValue());
}

/**
* @return array<string, mixed>
*/
abstract protected function getAttributesData(): array;

abstract protected function getValue(): mixed;
}
Loading

0 comments on commit a98ca6f

Please sign in to comment.