Completed
Push — master ( 8f4851...229728 )
by Terry
04:10
created

AssertionFailedException::getLocation()   A

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