Issues (6)

src/LazyAssertion.php (1 issue)

1
<?php declare(strict_types=1);
2
/**
3
 * This file is part of the daikon-cqrs/interop project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace Daikon\Interop;
10
11
use Assert\AssertionChain;
12
use Assert\LazyAssertion as BaseLazyAssertion;
13
use LogicException;
14
15
class LazyAssertion extends BaseLazyAssertion
16
{
17
    /** @var bool */
18
    private $currentChainFailed = false;
19
20
    /** @var bool */
21
    private $alwaysTryAll = false;
22
23
    /** @var bool */
24
    private $thisChainTryAll = false;
25
26
    /** @var null|AssertionChain */
27
    private $currentChain;
28
29
    /** @var array */
30
    private $errors = [];
31
32
    /** @var string The class to use as AssertionChain factory */
33
    private $assertClass = Assert::class;
34
35
    /** @var string|LazyAssertionException The class to use for exceptions */
36
    private $exceptionClass = LazyAssertionException::class;
37
38
    /**
39
     * @param mixed $value
40
     * @param string|callable|null $defaultMessage
41
     * @return static
42
     */
43
    public function that($value, string $propertyPath = null, $defaultMessage = null)
44
    {
45
        $this->currentChainFailed = false;
46
        $this->thisChainTryAll = false;
47
        $assertClass = $this->assertClass;
48
        $this->currentChain = $assertClass::that($value, $defaultMessage, $propertyPath);
49
50
        return $this;
51
    }
52
53
    /** @return static */
54
    public function tryAll()
55
    {
56
        if (!$this->currentChain) {
57
            $this->alwaysTryAll = true;
58
        }
59
60
        $this->thisChainTryAll = true;
61
62
        return $this;
63
    }
64
65
    /**
66
     * @param string $method
67
     * @param array $args
68
     * @return static
69
     */
70
    public function __call($method, $args)
71
    {
72
        if (false === $this->alwaysTryAll
73
            && false === $this->thisChainTryAll
74
            && true === $this->currentChainFailed
75
        ) {
76
            return $this;
77
        }
78
79
        try {
80
            call_user_func_array([$this->currentChain, $method], $args);
81
        } catch (AssertionFailedException $e) {
82
            $this->errors[] = $e;
83
            $this->currentChainFailed = true;
84
        }
85
86
        return $this;
87
    }
88
89
    /** @throws LazyAssertionException */
90
    public function verifyNow(): bool
91
    {
92
        if ($this->errors) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->errors of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
93
            throw call_user_func([$this->exceptionClass, 'fromErrors'], $this->errors);
94
        }
95
96
        return true;
97
    }
98
99
    /** @return static */
100
    public function setAssertClass(string $className): LazyAssertion
101
    {
102
        if (Assert::class !== $className && !is_subclass_of($className, Assert::class)) {
103
            throw new LogicException($className.' is not (a subclass of) '.Assert::class);
104
        }
105
106
        $this->assertClass = $className;
107
108
        return $this;
109
    }
110
111
    /** @return static */
112
    public function setExceptionClass(string $className): LazyAssertion
113
    {
114
        if (LazyAssertionException::class !== $className
115
            && !is_subclass_of($className, LazyAssertionException::class)
116
        ) {
117
            throw new LogicException($className.' is not (a subclass of) '.LazyAssertionException::class);
118
        }
119
120
        $this->exceptionClass = $className;
121
122
        return $this;
123
    }
124
}
125