Completed
Push — master ( 3e8bcb...baab87 )
by BENOIT
03:54
created

Specification::validate()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
nc 1
dl 0
loc 1
c 0
b 0
f 0
1
<?php
2
3
namespace BenTools\Specification;
4
5
use BenTools\Specification\Exception\UnmetSpecificationException;
6
use BenTools\Specification\Helper\BooleanSpecification;
7
use BenTools\Specification\Helper\CallbackSpecification;
8
use BenTools\Specification\Logical\AndSpecification;
9
use BenTools\Specification\Logical\GroupSpecification;
10
use BenTools\Specification\Logical\NotSpecification;
11
use BenTools\Specification\Logical\OrSpecification;
12
13
abstract class Specification
14
{
15
    /**
16
     * @var string
17
     */
18
    protected $label;
19
20
    /**
21
     * @return null|string
22
     */
23
    final public function getLabel(): ?string
24
    {
25
        return $this->label;
26
    }
27
28
    /**
29
     * @param null|string $label
30
     * @return Specification
31
     */
32
    final public function withLabel(?string $label): Specification
33
    {
34
        $clone = clone $this;
35
        $clone->label = $label;
36
        return $clone;
37
    }
38
39
    /**
40
     * @param             $specification
41
     * @param null|string $label
42
     * @return Specification
43
     * @throws \RuntimeException
44
     */
45
    final public function and($specification, ?string $label = null): Specification
46
    {
47
        return new AndSpecification($this, self::factory($specification, $label), $label);
48
    }
49
50
    /**
51
     * @param             $specification
52
     * @param null|string $label
53
     * @return Specification
54
     * @throws \RuntimeException
55
     */
56
    final public function or($specification, ?string $label = null): Specification
57
    {
58
        return new OrSpecification($this, self::factory($specification, $label), $label);
59
    }
60
61
    /**
62
     * @param null|string $label
63
     * @return Specification
64
     */
65
    final public function negate(?string $label = null): Specification
66
    {
67
        return new NotSpecification($this, $label);
68
    }
69
70
    /**
71
     * @param null|string $label
72
     * @return Specification
73
     */
74
    final public function asGroup(?string $label = null): Specification
75
    {
76
        return new GroupSpecification($this, $label);
77
    }
78
79
    /**
80
     * Validate the specification.
81
     * If the specification is unmet the implementation MUST throw an UnmetSpecificationException.
82
     *
83
     * @throws UnmetSpecificationException
84
     */
85
    abstract public function validate(): void;
86
87
    /**
88
     * @return bool
89
     */
90
    final public function isSatisfied(): bool
91
    {
92
        try {
93
            $this->validate();
94
            return true;
95
        } catch (UnmetSpecificationException $e) {
96
            return false;
97
        }
98
    }
99
100
    /**
101
     * @param             $specification
102
     * @param null|string $label
103
     * @return Specification
104
     * @throws \RuntimeException
105
     */
106
    final public static function factory($specification, ?string $label = null): Specification
107
    {
108
        if ($specification instanceof Specification) {
109
            return (null !== $label && $label !== $specification->getLabel()) ? $specification->withLabel($label) : $specification;
110
        }
111
        if (is_bool($specification)) {
112
            return new BooleanSpecification($specification, $label);
113
        }
114
        if (is_callable($specification)) {
115
            return new CallbackSpecification($specification, $label);
116
        }
117
        throw new \RuntimeException("Unable to determine specificaton type.");
118
    }
119
}
120