Passed
Pull Request — master (#359)
by Tim
13:25
created

Assert::nullOr()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 4
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\Assert;
6
7
use BadMethodCallException; // Requires ext-spl
8
use InvalidArgumentException; // Requires ext-spl
9
use Throwable;
10
use SimpleSAML\Assert\Assert as BaseAssert;
11
use SimpleSAML\Assert\AssertionFailedException;
12
13
use function array_pop;
14
use function array_unshift;
15
use function call_user_func_array;
16
use function end;
17
use function is_object;
18
use function is_resource;
19
use function is_string;
20
use function is_subclass_of;
21
use function lcfirst;
22
use function method_exists;
23
use function preg_match; // Requires ext-pcre
24
use function strval;
25
26
/**
27
 * SimpleSAML\SAML2\Assert\Assert wrapper class
28
 *
29
 * @package simplesamlphp/saml2
30
 *
31
 * @method static void validDateTime(mixed $value, string $message = '', string $exception = '')
32
 * @method static void validURI(mixed $value, string $message = '', string $exception = '')
33
 * @method static void nullOrValidDateTime(mixed $value, string $message = '', string $exception = '')
34
 * @method static void nullOrValidURI(mixed $value, string $message = '', string $exception = '')
35
 * @method static void allValidDateTime(mixed $value, string $message = '', string $exception = '')
36
 * @method static void allValidURI(mixed $value, string $message = '', string $exception = '')
37
 */
38
final class Assert
39
{
40
    use CustomAssertionTrait;
41
42
43
    /**
44
     * @param string $name
45
     * @param array<mixed> $arguments
46
     */
47
    public static function __callStatic(string $name, array $arguments): void
48
    {
49
        // Handle Exception-parameter
50
        $exception = AssertionFailedException::class;
51
52
        $last = end($arguments);
53
        if (is_string($last) && class_exists($last) && is_subclass_of($last, Throwable::class)) {
54
            $exception = $last;
55
            array_pop($arguments);
56
        }
57
58
        try {
59
            // Putting Webmozart first, since the most calls will be to their native assertions
60
            /*if (method_exists(BaseAssert::class, $name)) {
61
                call_user_func_array([BaseAssert::class, $name], $arguments);
62
                return;
63
            } else
64
*/if (method_exists(static::class, $name)) {
65
                call_user_func_array([static::class, $name], $arguments);
66
                return;
67
            } elseif (preg_match('/^nullOr(.*)$/i', $name, $matches)) {
68
                $method = lcfirst($matches[1]);
69
                if (method_exists(BaseAssert::class, $method)) {
70
                    call_user_func_array([static::class, 'nullOr'], [[BaseAssert::class, $method], $arguments]);
71
                } elseif (method_exists(static::class, $method)) {
72
                    call_user_func_array([static::class, 'nullOr'], [[static::class, $method], $arguments]);
73
                } else {
74
                    throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $method));
75
                }
76
            } elseif (preg_match('/^all(.*)$/i', $name, $matches)) {
77
                $method = lcfirst($matches[1]);
78
                if (method_exists(BaseAssert::class, $method)) {
79
                    call_user_func_array([static::class, 'all'], [[BaseAssert::class, $method], $arguments]);
80
                } elseif (method_exists(static::class, $method)) {
81
                    call_user_func_array([static::class, 'all'], [[static::class, $method], $arguments]);
82
                } else {
83
                    throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $method));
84
                }
85
            } else {
86
                throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $name));
87
            }
88
        } catch (InvalidArgumentException $e) {
89
            throw new $exception($e->getMessage());
90
        }
91
    }
92
93
94
    /**
95
     * Handle nullOr* for either Webmozart or for our custom assertions
96
     *
97
     * @param callable $method
98
     * @param array<mixed> $arguments
99
     * @return void
100
     */
101
    private static function nullOr(callable $method, array $arguments): void
102
    {
103
        $value = reset($arguments);
104
        ($value === null) || call_user_func_array($method, $arguments);
105
    }
106
107
108
    /**
109
     * all* for our custom assertions
110
     *
111
     * @param callable $method
112
     * @param array<mixed> $arguments
113
     * @return void
114
     */
115
    private static function all(callable $method, array $arguments): void
116
    {
117
        $values = array_pop($arguments);
118
        foreach ($values as $value) {
119
            $tmp = $arguments;
120
            array_unshift($tmp, $value);
121
            call_user_func_array($method, $tmp);
122
        }
123
    }
124
125
126
    /**
127
     * @param mixed $value
128
     *
129
     * @return string
130
     */
131
    protected static function valueToString(mixed $value): string
132
    {
133
        if (is_resource($value)) {
134
            return 'resource';
135
        }
136
137
        if (null === $value) {
138
            return 'null';
139
        }
140
141
        if (true === $value) {
142
            return 'true';
143
        }
144
145
        if (false === $value) {
146
            return 'false';
147
        }
148
149
        if (is_array($value)) {
150
            return 'array';
151
        }
152
153
        if (is_object($value)) {
154
            if (method_exists($value, '__toString')) {
155
                return $value::class . ': ' . self::valueToString($value->__toString());
156
            }
157
158
            if ($value instanceof DateTime || $value instanceof DateTimeImmutable) {
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Assert\DateTimeImmutable was not found. Did you mean DateTimeImmutable? If so, make sure to prefix the type with \.
Loading history...
Bug introduced by
The type SimpleSAML\SAML2\Assert\DateTime was not found. Did you mean DateTime? If so, make sure to prefix the type with \.
Loading history...
159
                return $value::class . ': ' . self::valueToString($value->format('c'));
160
            }
161
162
            return $value::class;
163
        }
164
165
        if (is_string($value)) {
166
            return '"' . $value . '"';
167
        }
168
169
        return strval($value);
170
    }
171
}
172