Assertion   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 166
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 0
loc 166
rs 10
c 0
b 0
f 0
wmc 18
lcom 1
cbo 3

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getResponder() 0 4 1
A __call() 0 8 2
A __get() 0 19 4
A request() 0 10 2
A extend() 0 12 4
A setActual() 0 6 1
A getActual() 0 4 1
A assert() 0 18 2
1
<?php
2
3
namespace Peridot\Leo;
4
5
use Peridot\Leo\Matcher\MatcherInterface;
6
use Peridot\Leo\Responder\ResponderInterface;
7
8
/**
9
 * Assertion is responsible for asserting it's actual value
10
 * against a MatcherInterface and responding to the results of a match.
11
 *
12
 * @method Assertion equal(mixed $expected, string $message = "") Asserts that actual and expected values are strictly equal
13
 * @method Assertion with(array $args) Stores an array of values to be used with callable assertions
14
 * @method Assertion throw(string $exceptionType, string $exceptionMessage = "", $message = "") Invokes the actual value as a function and matches the exception type was thrown, and optionally matches the exception message
15
 * @method Assertion a(string $expected, string $message = "") Asserts that the actual value given has the same type as the expected type string
16
 * @method Assertion an(string $expected, string $message = "") Asserts that the actual value given has the same type as the expected type string
17
 * @method Assertion include(mixed $expected, string $message = "") Asserts that the actual string or array includes the expected value
18
 * @method Assertion contain(mixed $expected, string $message = "") Asserts that the actual string or array includes the expected value
19
 * @method Assertion ok(string $message = "") Asserts that the actual value is truthy - that is true when cast to (bool)
20
 * @method Assertion true(string $message = "") Asserts that the actual value is strictly equal to true
21
 * @method Assertion false(string $message = "") Asserts that the actual value is strictly equal to false
22
 * @method Assertion null(string $message = "") Asserts that the actual value is null
23
 * @method Assertion empty(string $message = "") Asserts that the actual value is empty
24
 * @method Assertion above(mixed $expected, string $message = "") Asserts that the actual value is greater than the expected value
25
 * @method Assertion least(mixed $expected, string $message = "") Asserts that the actual value is greater than or equal to the expected value
26
 * @method Assertion below(mixed $expected, string $message = "") Asserts that the actual value is less than the expected value
27
 * @method Assertion most(mixed $expected, string $message = "") Asserts that the actual value is less than or equal to the expected value
28
 * @method Assertion within(int $lowerBound, int $upperBound, string $message = "") Asserts that the actual value is between the upper and lower bounds (inclusive)
29
 * @method Assertion instanceof(string $expected, string $message = "") Asserts that the actual value is an instance of the expected class string
30
 * @method Assertion property(string $name, mixed $value = "", string $message = "") Asserts that the actual array or object has the expected property and optionally asserts the property value against an expected value
31
 * @method Assertion length(mixed $expected, string $message = "") Asserts the actual array, string, or Countable has the expected length
32
 * @method Assertion match(string $pattern, string $message = "") Asserts that the actual value matches the expected regular expression
33
 * @method Assertion string(string $expected, string $message = "") Asserts that the actual string contains the expected substring
34
 * @method Assertion keys(array $keys, string $message = "") Asserts the actual object or array has keys equivalent to the expected keys
35
 * @method Assertion satisfy(callable $predicate, string $message = "") Asserts that the actual value satisfies the expected predicate. The expected predicate will be passed the actual value and should return true or false
36
 *
37
 * @property-read Assertion $to a language chain
38
 * @property-read Assertion $be a language chain
39
 * @property-read Assertion $been a language chain
40
 * @property-read Assertion $is a language chain
41
 * @property-read Assertion $and a language chain
42
 * @property-read Assertion $has a language chain
43
 * @property-read Assertion $have a language chain
44
 * @property-read Assertion $with a language chain
45
 * @property-read Assertion $that a language chain
46
 * @property-read Assertion $at a language chain
47
 * @property-read Assertion $of a language chain
48
 * @property-read Assertion $same a language chain
49
 * @property-read Assertion $an a language chain
50
 * @property-read Assertion $a a language chain
51
 * @property-read Assertion $not flags the Assertion as negated
52
 * @property-read Assertion $loosely enables loose equality assertion using the ->equal() assertion
53
 * @property-read Assertion $contain enables the contain flag for use with the ->keys() assertion
54
 * @property-read Assertion $include enables the contain flag for use with the ->keys() assertion
55
 * @property-read Assertion $ok a lazy property that performs an ->ok() assertion
56
 * @property-read Assertion $true a lazy property that performs a ->true() assertion
57
 * @property-read Assertion $false a lazy property that performs a ->false() assertion
58
 * @property-read Assertion $null a lazy property that performs a ->null() assertion
59
 * @property-read Assertion $empty a lazy property that performs an ->empty() assertion
60
 * @property-read Assertion $length enables the length flag for use with countable assertions such as ->above(), ->least(), ->below(), ->most(), and ->within()
61
 * @property-read Assertion $deep enables the deep flag for use with assertions that need to traverse structures like the ->property() assertion
62
 *
63
 * @package Peridot\Leo
64
 */
65
final class Assertion
66
{
67
    use DynamicObjectTrait;
68
69
    /**
70
     * A static cache for memoized properties.
71
     *
72
     * @var array
73
     */
74
    private static $propertyCache = [];
75
76
    /**
77
     * @var ResponderInterface
78
     */
79
    protected $responder;
80
81
    /**
82
     * @var mixed
83
     */
84
    protected $actual;
85
86
    /**
87
     * @param ResponderInterface $responder
88
     */
89
    public function __construct(ResponderInterface $responder, $actual = null)
90
    {
91
        $this->responder = $responder;
92
        $this->actual = $actual;
93
    }
94
95
    /**
96
     * Returns the current ResponderInterface assigned to this Assertion.
97
     *
98
     * @return ResponderInterface
99
     */
100
    public function getResponder()
101
    {
102
        return $this->responder;
103
    }
104
105
    /**
106
     * Delegate methods to assertion methods.
107
     *
108
     * @param $method
109
     * @param $args
110
     * @return mixed
111
     */
112
    public function __call($method, $args)
113
    {
114
        if (!isset($this->methods[$method])) {
115
            throw new \BadMethodCallException("Method $method does not exist");
116
        }
117
118
        return $this->request($this->methods[$method], $args);
119
    }
120
121
    /**
122
     * @param $name
123
     * @return mixed
124
     */
125
    public function __get($name)
126
    {
127
        if (!isset($this->properties[$name])) {
128
            throw new \DomainException("Property $name not found");
129
        }
130
131
        if (array_key_exists($name, self::$propertyCache)) {
132
            return self::$propertyCache[$name];
133
        }
134
135
        $property = $this->properties[$name];
136
        $result = $this->request($property['factory']);
137
138
        if ($property['memoize']) {
139
            self::$propertyCache[$name] = $result;
140
        }
141
142
        return $result;
143
    }
144
145
    /**
146
     * A request to an Assertion will attempt to resolve
147
     * the result as an assertion before returning the result.
148
     *
149
     * @param  callable $fn
150
     * @return mixed
151
     */
152
    public function request(callable $fn, array $arguments = [])
153
    {
154
        $result = call_user_func_array($fn, $arguments);
155
156
        if ($result instanceof MatcherInterface) {
157
            return $this->assert($result);
158
        }
159
160
        return $result;
161
    }
162
163
    /**
164
     * Extend calls the given callable - or file that returns a callable - and passes the current Assertion instance
165
     * to it. Assertion can be extended via the ->addMethod(), ->flag(), and ->addProperty()
166
     * methods.
167
     *
168
     * @param callable $fn
169
     */
170
    public function extend($fn)
171
    {
172
        if (is_string($fn) && file_exists($fn)) {
173
            $fn = include $fn;
174
        }
175
176
        if (is_callable($fn)) {
177
            return call_user_func($fn, $this);
178
        }
179
180
        throw new \InvalidArgumentException('Assertion::extend requires a callable or a file that returns one');
181
    }
182
183
    /**
184
     * Set the actual value used for matching expectations against.
185
     *
186
     * @param $actual
187
     * @return $this
188
     */
189
    public function setActual($actual)
190
    {
191
        $this->actual = $actual;
192
193
        return $this;
194
    }
195
196
    /**
197
     * Return the actual value being asserted against.
198
     *
199
     * @return mixed
200
     */
201
    public function getActual()
202
    {
203
        return $this->actual;
204
    }
205
206
    /**
207
     * Assert against the given matcher.
208
     *
209
     * @param $result
210
     * @return $this
211
     */
212
    public function assert(MatcherInterface $matcher)
213
    {
214
        if ($this->flag('not')) {
215
            $matcher->invert();
216
        }
217
218
        $match = $matcher
219
            ->setAssertion($this)
220
            ->match($this->getActual());
221
222
        $message = $this->flag('message');
223
224
        $this->clearFlags();
225
226
        $this->responder->respond($match, $matcher->getTemplate(), $message);
227
228
        return $this;
229
    }
230
}
231