Passed
Pull Request — master (#359)
by Tim
02:55
created

Assert::__callStatic()   C

Complexity

Conditions 12
Paths 36

Size

Total Lines 38
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 29
c 1
b 0
f 0
nc 36
nop 2
dl 0
loc 38
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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