smartemailing/types

View on GitHub
src/ZipCode.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

declare(strict_types = 1);

namespace SmartEmailing\Types;

use Nette\Utils\Strings;
use SmartEmailing\Types\Comparable\ComparableInterface;
use SmartEmailing\Types\Comparable\StringComparableTrait;
use SmartEmailing\Types\ExtractableTraits\StringExtractableTrait;
use SmartEmailing\Types\Helpers\StringHelpers;

// phpcs:disable SlevomatCodingStandard.Files.LineLength.LineTooLong
final class ZipCode implements ToStringInterface, ComparableInterface
{

    use StringExtractableTrait;
    use ToStringTrait;
    use StringComparableTrait;

    private string $value;

    /**
     * @var array<string>
     */
    private static array $patternsByCountry = [
        CountryCode::CZ => '#^\d{3}?\d{2}\z#',
        CountryCode::SK => '#^\d{3}?\d{2}\z#',
        CountryCode::AT => '#^\d{4}\z#',
        CountryCode::BE => '#^\d{4}\z#',
        CountryCode::FR => '#^\d{2}?\d{3}\z#',
        CountryCode::HU => '#^\d{4}\z#',
        CountryCode::GB => '#^GIR?0AA|(?:(?:AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|BX|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(?:\d[\dA-Z]??\d[ABD-HJLN-UW-Z]{2}))|BFPO?\d{1,4}\z#',
        CountryCode::DE => '#^\d{5}\z#',
        CountryCode::US => '#^(\d{5})(?:[\-](\d{4}))?\z#',
        CountryCode::PL => '#^\d{2}-\d{3}\z#',
        CountryCode::IT => '#^\d{5}\z#',
        CountryCode::SE => '#^\d{3}?\d{2}\z#',
        CountryCode::SI => '#^\d{4}\z#',
        CountryCode::MH => '#^(969[67]\d)(?:[\-](\d{4}))?\z#',
        CountryCode::NL => '#^\d{4}?[A-Z]{2}\z#',
        CountryCode::CY => '#^\d{4}\z#',
        CountryCode::IE => '#^[\dA-Z]{3}?[\dA-Z]{4}\z#',
        CountryCode::DK => '#^\d{4}\z#',
        CountryCode::FI => '#^\d{5}\z#',
        CountryCode::LU => '#^\d{4}\z#',
        CountryCode::MT => '#^[A-Z]{3}?\d{2,4}\z#',
    ];

    private function __construct(
        string $value
    ) {
        $value = StringHelpers::removeWhitespace($value);
        $value = Strings::upper($value);

        if (!$this->isValid($value)) {
            throw new InvalidTypeException('Invalid ZIP code: ' . $value);
        }

        $this->value = $value;
    }

    public function getValue(): string
    {
        return $this->value;
    }

    private function isValid(
        string $value
    ): bool {
        foreach (self::$patternsByCountry as $pattern) {
            if (Strings::match($value, $pattern)) {
                return true;
            }
        }

        return false;
    }

}