AssertionFailedException::getLocation()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Terah\Assert;
4
5
/**
6
 * Assert
7
 *
8
 * LICENSE
9
 *
10
 * This source file is subject to the new BSD license that is bundled
11
 * with this package in the file LICENSE.txt.
12
 * If you did not receive a copy of the license and are unable to
13
 * obtain it through the world-wide-web, please send an email
14
 * to [email protected] so I can send you a copy immediately.
15
 */
16
17
/**
18
 * AssertionFailedException
19
 *
20
 * @author Benjamin Eberlei <[email protected]>
21
 * @author Terry Cullen <[email protected]>
22
 *
23
 */
24
class AssertionFailedException extends \Exception
25
{
26
    private $fieldName;
27
    private $value;
28
    private $constraints;
29
    private $level;
30
    private $propertyPath;
31
    private $location;
32
33
    /**
34
     * AssertionFailedException constructor.
35
     *
36
     * @param string $message
37
     * @param int    $code
38
     * @param string $fieldName
39
     * @param        $value
40
     * @param array  $constraints
41
     * @param string $level
42
     * @param string $propertyPath
43
     */
44
    public function __construct(string $message, int $code, string $fieldName='', $value='', array $constraints=[], string $level='critical', string $propertyPath='')
45
    {
46
        parent::__construct($message, $code);
47
        $this->fieldName        = $fieldName;
48
        $this->value            = $value;
49
        $this->constraints      = $constraints;
50
        $this->level            = $level;
51
        $this->propertyPath     = $propertyPath;
52
        foreach ( $this->getTrace() as $point )
53
        {
54
            $class = $point['class'] ??0?: '';
55
            if ( $class !== Assert::class )
56
            {
57
                $this->location = (object)$point;
58
59
                break;
60
            }
61
        }
62
    }
63
64
    /**
65
     * Get the field name that was set for the assertion object.
66
     *
67
     * @return string
68
     */
69
    public function getFieldName() : string
70
    {
71
        return $this->fieldName;
72
    }
73
74
    /**
75
     * Get the value that caused the assertion to fail.
76
     *
77
     * @return mixed
78
     */
79
    public function getValue()
80
    {
81
        return $this->value;
82
    }
83
84
    /**
85
     * Get the constraints that applied to the failed assertion.
86
     *
87
     * @return array
88
     */
89
    public function getConstraints() : array
90
    {
91
        return $this->constraints;
92
    }
93
94
    /**
95
     * Get the error level.
96
     *
97
     * @return string
98
     */
99
    public function getLevel() : string
100
    {
101
        return $this->level ? $this->level : 'critical';
102
    }
103
104
    /**
105
     * User controlled way to define a sub-property causing
106
     * the failure of a currently asserted objects.
107
     *
108
     * Useful to transport information about the nature of the error
109
     * back to higher layers.
110
     *
111
     * @return string
112
     */
113
    public function getPropertyPath() : string
114
    {
115
        return $this->propertyPath ? $this->propertyPath : 'General Error';
116
    }
117
118
    /**
119
     * Get the propertyPath, combined with the calling file and line location.
120
     *
121
     * @return string
122
     */
123
    public function getPropertyPathAndCallingLocation() : string
124
    {
125
        return $this->getPropertyPath() . ' in ' . $this->getCallingFileAndLine();
126
    }
127
128
    /**
129
     * Get the calling file and line from where the failing assertion
130
     * was called.
131
     *
132
     * @return string
133
     */
134
    protected function getCallingFileAndLine() : string
135
    {
136
        foreach ( $this->getTrace() as $trace )
137
        {
138
            $trace = (object)$trace;
139
            if ( empty($trace->file) )
140
            {
141
                continue;
142
            }
143
            $file = static::beforeLast('.php', static::afterLast('/', $trace->file));
144
            if ( in_array($file, ['AssertionChain', 'Assertion']) )
145
            {
146
                continue;
147
            }
148
            return "{$trace->file}:{$trace->line}";
149
        }
150
151
        return '';
152
    }
153
154
    /**
155
     * Get the trace location of where the failing assertion
156
     * was called.
157
     *
158
     * @return object
159
     */
160
    public function getLocation() : \stdClass
161
    {
162
        return $this->location;
163
    }
164
165
    /**
166
     * @param string $needle
167
     * @param string $haystack
168
     * @param bool $returnOriginal
169
     * @return string
170
     */
171
    public static function afterLast(string $needle, string $haystack, bool $returnOriginal=false) : string
172
    {
173
        if ( static::strrevpos($haystack, $needle) !== -1 )
174
        {
175
            return mb_substr($haystack, static::strrevpos($haystack, $needle) + mb_strlen($needle));
176
        }
177
178
        return $returnOriginal ? $haystack : '';
179
    }
180
181
    /**
182
     * @param string $string
183
     * @param string $needle
184
     * @return int
185
     */
186
    public static function strrevpos(string $string, string $needle) : int
187
    {
188
        $revStr = mb_strpos(strrev($string), strrev($needle));
189
190
        return $revStr === false ? -1 : mb_strlen($string) - $revStr - mb_strlen($needle);
191
    }
192
193
    /**
194
     * @param string $needle
195
     * @param string $haystack
196
     * @return string
197
     */
198
    public static function beforeLast(string $needle, string $haystack) : string
199
    {
200
        $position   = static::strrevpos($haystack, $needle);
201
202
        return $position === -1 ? '' : mb_substr($haystack, 0, static::strrevpos($haystack, $needle));
203
    }
204
}