Passed
Pull Request — master (#359)
by Tim
02:47
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 SimpleSAML\Assert\Assert as BaseAssert;
10
use SimpleSAML\Assert\AssertionFailedException;
11
use Throwable;
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
            if (method_exists(static::class, $name)) {
60
                call_user_func_array([static::class, $name], $arguments);
61
                return;
62
            } elseif (preg_match('/^nullOr(.*)$/i', $name, $matches)) {
63
                $method = lcfirst($matches[1]);
64
                if (method_exists(BaseAssert::class, $method)) {
65
                    call_user_func_array([static::class, 'nullOr'], [[BaseAssert::class, $method], $arguments]);
66
                } elseif (method_exists(static::class, $method)) {
67
                    call_user_func_array([static::class, 'nullOr'], [[static::class, $method], $arguments]);
68
                } else {
69
                    throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $method));
70
                }
71
            } elseif (preg_match('/^all(.*)$/i', $name, $matches)) {
72
                $method = lcfirst($matches[1]);
73
                if (method_exists(BaseAssert::class, $method)) {
74
                    call_user_func_array([static::class, 'all'], [[BaseAssert::class, $method], $arguments]);
75
                } elseif (method_exists(static::class, $method)) {
76
                    call_user_func_array([static::class, 'all'], [[static::class, $method], $arguments]);
77
                } else {
78
                    throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $method));
79
                }
80
            } else {
81
                throw new BadMethodCallException(sprintf("Assertion named `%s` does not exists.", $name));
82
            }
83
        } catch (InvalidArgumentException $e) {
84
            throw new $exception($e->getMessage());
85
        }
86
    }
87
88
89
    /**
90
     * Handle nullOr* for either Webmozart or for our custom assertions
91
     *
92
     * @param callable $method
93
     * @param array<mixed> $arguments
94
     * @return void
95
     */
96
    private static function nullOr(callable $method, array $arguments): void
97
    {
98
        $value = reset($arguments);
99
        ($value === null) || call_user_func_array($method, $arguments);
100
    }
101
102
103
    /**
104
     * all* for our custom assertions
105
     *
106
     * @param callable $method
107
     * @param array<mixed> $arguments
108
     * @return void
109
     */
110
    private static function all(callable $method, array $arguments): void
111
    {
112
        $values = array_pop($arguments);
113
        foreach ($values as $value) {
114
            $tmp = $arguments;
115
            array_unshift($tmp, $value);
116
            call_user_func_array($method, $tmp);
117
        }
118
    }
119
120
121
    /**
122
     * @param mixed $value
123
     *
124
     * @return string
125
     */
126
    protected static function valueToString(mixed $value): string
127
    {
128
        if (is_resource($value)) {
129
            return 'resource';
130
        }
131
132
        if (null === $value) {
133
            return 'null';
134
        }
135
136
        if (true === $value) {
137
            return 'true';
138
        }
139
140
        if (false === $value) {
141
            return 'false';
142
        }
143
144
        if (is_array($value)) {
145
            return 'array';
146
        }
147
148
        if (is_object($value)) {
149
            if (method_exists($value, '__toString')) {
150
                return $value::class . ': ' . self::valueToString($value->__toString());
151
            }
152
153
            if ($value instanceof DateTime || $value instanceof DateTimeImmutable) {
0 ignored issues
show
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...
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...
154
                return $value::class . ': ' . self::valueToString($value->format('c'));
155
            }
156
157
            return $value::class;
158
        }
159
160
        if (is_string($value)) {
161
            return '"' . $value . '"';
162
        }
163
164
        return strval($value);
165
    }
166
}
167