61 lines
1.8 KiB
PHP
61 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Tax;
|
|
|
|
use App\Models\Customer;
|
|
|
|
/**
|
|
* The register, for tests.
|
|
*
|
|
* Answers UNAVAILABLE for anything it was not told about, which is deliberately
|
|
* the awkward default: a test that forgets to arm a number finds out, instead of
|
|
* quietly proving that an unchecked number earns a reverse charge.
|
|
*/
|
|
final class FakeVatIdVerifier implements VatIdVerifier
|
|
{
|
|
/** @var array<string, VatIdCheck> */
|
|
private array $answers = [];
|
|
|
|
/** @var array<int, string> every number that was asked about, in order */
|
|
public array $asked = [];
|
|
|
|
public function registered(string $vatId, ?string $name = null): self
|
|
{
|
|
$this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::valid($name);
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function notRegistered(string $vatId): self
|
|
{
|
|
$this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::invalid();
|
|
|
|
return $this;
|
|
}
|
|
|
|
/** The register is down — the case that must never clear a verification. */
|
|
public function down(string $vatId): self
|
|
{
|
|
$this->answers[Customer::normaliseVatId($vatId)] = VatIdCheck::unavailable('test');
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function check(string $vatId): VatIdCheck
|
|
{
|
|
$normalised = Customer::normaliseVatId($vatId);
|
|
|
|
// Refused before it is recorded as asked, exactly as the real verifier
|
|
// refuses before it spends a request. Without this the fake would answer
|
|
// where VIES would never have been consulted, and a test could prove the
|
|
// opposite of what the product does.
|
|
if (! VatIdShape::verifiable($normalised)) {
|
|
return VatIdCheck::invalid();
|
|
}
|
|
|
|
$this->asked[] = $normalised;
|
|
|
|
return $this->answers[$normalised] ?? VatIdCheck::unavailable('not armed in this test');
|
|
}
|
|
}
|