Completed
Push — master ( d700db...5d2291 )
by Terry
02:29
created

AssertionFailedException::getPropertyPath()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
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 $propertyPath
39
     * @param        $value
40
     * @param array  $constraints
41
     * @param string $level
42
     */
43
    public function __construct(string $message, int $code, string $fieldName = '', $value, array $constraints=[], string $level='critical', string $propertyPath = '')
44
    {
45
        parent::__construct($message, $code);
46
        $this->fieldName        = $fieldName;
47
        $this->value            = $value;
48
        $this->constraints      = $constraints;
49
        $this->level            = $level;
50
        $this->propertyPath     = $propertyPath;
51
        foreach ( $this->getTrace() as $point )
52
        {
53
            if ( $this->location )
54
            {
55
                continue;
56
            }
57
            $class = $point['class'] ??0?: '';
58
            if ( $class !== 'Terah\\Assert\\Assert' )
59
            {
60
                $this->location = (object)$point;
61
            }
62
        }
63
    }
64
65
    /**
66
     * Get the field name that was set for the assertion object.
67
     *
68
     * @return string
69
     */
70
    public function getFieldName() : string
71
    {
72
        return $this->fieldName;
73
    }
74
75
    /**
76
     * Get the value that caused the assertion to fail.
77
     *
78
     * @return mixed
79
     */
80
    public function getValue()
81
    {
82
        return $this->value;
83
    }
84
85
    /**
86
     * Get the constraints that applied to the failed assertion.
87
     *
88
     * @return array
89
     */
90
    public function getConstraints() : array
91
    {
92
        return $this->constraints;
93
    }
94
95
    /**
96
     * Get the error level.
97
     *
98
     * @return string
99
     */
100
    public function getLevel() : string
101
    {
102
        return $this->level ? $this->level : 'critical';
103
    }
104
105
    /**
106
     * User controlled way to define a sub-property causing
107
     * the failure of a currently asserted objects.
108
     *
109
     * Useful to transport information about the nature of the error
110
     * back to higher layers.
111
     *
112
     * @return string
113
     */
114
    public function getPropertyPath() : string
115
    {
116
        return $this->propertyPath ? $this->propertyPath : 'General Error';
117
    }
118
119
    /**
120
     * Get the propertyPath, combined with the calling file and line location.
121
     *
122
     * @return string
123
     */
124
    public function getPropertyPathAndCallingLocation() : string
125
    {
126
        return $this->getPropertyPath() . ' in ' . $this->getCallingFileAndLine();
127
    }
128
129
    /**
130
     * Get the calling file and line from where the failing assertion
131
     * was called.
132
     *
133
     * @return string
134
     */
135
    protected function getCallingFileAndLine() : string
136
    {
137
        foreach ( $this->getTrace() as $trace )
138
        {
139
            $trace = (object)$trace;
140
            if ( empty($trace->file) )
141
            {
142
                continue;
143
            }
144
            $file = static::beforeLast('.php', static::afterLast('/', $trace->file));
145
            if ( in_array($file, ['AssertionChain', 'Assertion']) )
146
            {
147
                continue;
148
            }
149
            return "{$trace->file}:{$trace->line}";
150
        }
151
152
        return '';
153
    }
154
155
    /**
156
     * Get the trace location of where the failing assertion
157
     * was called.
158
     *
159
     * @return object
160
     */
161
    public function getLocation() : object
162
    {
163
        return $this->location;
164
    }
165
166
    /**
167
     * @param string $needle
168
     * @param string $haystack
169
     * @param bool $return_original
170
     * @return string
171
     */
172
    public static function afterLast(string $needle, string $haystack, bool $return_original=false) : string
173
    {
174
        if ( static::strrevpos($haystack, $needle) !== -1 )
175
        {
176
            return mb_substr($haystack, static::strrevpos($haystack, $needle) + mb_strlen($needle));
177
        }
178
179
        return $return_original ? $haystack : '';
180
    }
181
182
    /**
183
     * @param string $string
184
     * @param string $needle
185
     * @return int
186
     */
187
    public static function strrevpos(string $string, string $needle) : int
188
    {
189
        $revStr = mb_strpos(strrev($string), strrev($needle));
190
191
        return $revStr === false ? -1 : mb_strlen($string) - $revStr - mb_strlen($needle);
192
    }
193
194
    /**
195
     * @param string $needle
196
     * @param string $haystack
197
     * @return string
198
     */
199
    public static function beforeLast(string $needle, string $haystack) : string
200
    {
201
        $position   = static::strrevpos($haystack, $needle);
202
203
        return $position === -1 ? '' : mb_substr($haystack, 0, static::strrevpos($haystack, $needle));
204
    }
205
}