Completed
Push — master ( 4fdf9b...3e8bcb )
by BENOIT
02:40
created

Specification::withLabel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
rs 9.4285
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
     * @param             $specification
89
     * @param null|string $label
90
     * @return Specification
91
     * @throws \RuntimeException
92
     */
93
    final public static function factory($specification, ?string $label = null): Specification
94
    {
95
        if ($specification instanceof Specification) {
96
            return (null !== $label && $label !== $specification->getLabel()) ? $specification->withLabel($label) : $specification;
97
        } elseif (is_bool($specification)) {
98
            return new BooleanSpecification($specification, $label);
99
        } elseif (is_callable($specification)) {
100
            return new CallbackSpecification($specification, $label);
101
        }
102
        throw new \RuntimeException("Unable to determine specificaton type.");
103
    }
104
}
105