Passed
Branch version-4 (8b03a3)
by Sebastian
02:18
created

Functions::assertValidCallable()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 23
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 10.4218

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 7
eloc 17
c 1
b 0
f 1
nc 7
nop 2
dl 0
loc 23
ccs 10
cts 17
cp 0.5881
crap 10.4218
rs 8.8333
1
<?php
2
declare(strict_types=1);
3
4
namespace Seboettg\Collection\Assert;
5
6
use ReflectionException;
7
use ReflectionFunction;
8
use Seboettg\Collection\Assert\Exception\NotApplicableCallableException;
9
use Seboettg\Collection\Assert\Exception\NotConvertibleToStringException;
10
use Seboettg\Collection\Assert\Exception\TypeIsNotAScalarException;
11
use Seboettg\Collection\Assert\Exception\WrongTypeException;
12
use function is_scalar;
13
use function is_object;
14
use function method_exists;
15
16
final class Functions
17
{
18 22
    public static final function assertScalar($value, string $message): void
0 ignored issues
show
Coding Style introduced by
As per PSR2, final should precede the visibility keyword.
Loading history...
19
    {
20 22
        if (!is_scalar($value)) {
21 3
            throw new TypeIsNotAScalarException($message);
22
        }
23 22
    }
24
25 1
    public static final function assertType($value, string $fqcn, string $message)
0 ignored issues
show
Coding Style introduced by
As per PSR2, final should precede the visibility keyword.
Loading history...
26
    {
27 1
        if (!$value instanceof $fqcn) {
28
            throw new WrongTypeException($message);
29
        }
30 1
    }
31
32 4
    public static final function assertStringable($value, string $message)
0 ignored issues
show
Coding Style introduced by
As per PSR2, final should precede the visibility keyword.
Loading history...
33
    {
34 4
        if (!is_scalar($value)) {
35 2
            if (!self::isStrigableObject($value)) {
36 1
                throw new NotConvertibleToStringException($message);
37
            }
38
        }
39 3
    }
40
41 2
    private static function isStrigableObject($value): bool
42
    {
43 2
        return is_object($value) && method_exists($value, "__toString");
44
    }
45
46 2
    public static function assertValidCallable(callable $callable, array $parameters)
47
    {
48 2
        $reflected = new ReflectionFunction($callable);
49 2
        if (count($reflected->getParameters()) !== count($parameters)) {
50
            throw new NotApplicableCallableException(
51
                "The number of parameters of the given callable does not match the expected number."
52
            );
53
        }
54 2
        for ($i = 0; $i < count($reflected->getParameters()); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
55 2
            $reflectedParamType = $reflected->getParameters()[$i]->getType()->getName();
0 ignored issues
show
Bug introduced by
The method getName() does not exist on ReflectionType. It seems like you code against a sub-type of ReflectionType such as ReflectionNamedType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

55
            $reflectedParamType = $reflected->getParameters()[$i]->getType()->/** @scrutinizer ignore-call */ getName();
Loading history...
56 2
            $expectedParam = $parameters[$i];
57 2
            switch ($expectedParam) {
58 2
                case "scalar":
59
                    if (!in_array($reflectedParamType, ["int", "string", "bool", "float"])) {
60
                        self::throwNotApplicableCallableException($i, "scalar", $reflectedParamType);
61
                    }
62
                    break;
63 2
                case "mixed":
64
                    //ignore, since every type is allowed
65
                    break;
66
                default:
67 2
                    if ($reflectedParamType !== $expectedParam) {
68
                        self::throwNotApplicableCallableException($i, $expectedParam, $reflectedParamType);
69
                    }
70
            }
71
        }
72 2
    }
73
74
    private static function throwNotApplicableCallableException($paramNumber, $expectedType, $actualType)
75
    {
76
        throw new NotApplicableCallableException(
77
            sprintf(
78
                "Parameter %d of type %s does not match the expected type of %s",
79
                $paramNumber,
80
                $actualType,
81
                $expectedType
82
            )
83
        );
84
    }
85
}
86
87
/**
88
 * @param $value
89
 * @param string $message description that will be included in the failure message if the assertion fails.
90
 * @return void
91
 */
92
function assertScalar($value, string $message): void
93
{
94 22
    Functions::assertScalar($value, $message);
95 22
}
96
97
/**
98
 * @param $value
99
 * @param string $fqcn full qualified class name
100
 * @param string $message description that will be included in the failure message if the assertion fails.
101
 * @return void
102
 */
103
function assertType($value, string $fqcn, string $message): void
104
{
105 1
    Functions::assertType($value, $fqcn, $message);
106 1
}
107
108
/**
109
 * @param $value
110
 * @param string $message description that will be included in the failure message if the assertion fails.
111
 * @return void
112
 */
113
function assertStringable($value, string $message): void
114
{
115 4
    Functions::assertStringable($value, $message);
116 3
}
117
118
119
function assertValidCallable(callable $callable, array $parameters)
120
{
121
    Functions::assertValidCallable($callable, $parameters);
122
}