Issues (35)

src/Assert/Functions.php (2 issues)

1
<?php
2
declare(strict_types=1);
3
/*
4
 * Copyright (C) 2022 Sebastian Böttger <[email protected]>
5
 * You may use, distribute and modify this code under the
6
 * terms of the MIT license.
7
 *
8
 * You should have received a copy of the MIT license with
9
 * this file. If not, please visit: https://opensource.org/licenses/mit-license.php
10
 */
11
12
namespace Seboettg\Collection\Assert;
13
14
use ReflectionFunction;
15
use Seboettg\Collection\Assert\Exception\NotApplicableCallableException;
16
use Seboettg\Collection\Assert\Exception\NotConvertibleToStringException;
17
use Seboettg\Collection\Assert\Exception\ObjectIsNotComparableException;
18
use Seboettg\Collection\Assert\Exception\TypeIsNotAScalarException;
19
use Seboettg\Collection\Assert\Exception\WrongTypeException;
20
use Seboettg\Collection\Comparable\Comparable;
21
use function is_scalar;
22
use function is_object;
23
use function method_exists;
24
25
final class Functions
26
{
27 56
    final public static function assertScalar($value, string $message): void
28
    {
29 56
        if (!is_scalar($value)) {
30 4
            throw new TypeIsNotAScalarException($message);
31
        }
32 55
    }
33
34 5
    final public static function assertType($value, string $fqcn, string $message)
35
    {
36 5
        if (!$value instanceof $fqcn) {
37 1
            throw new WrongTypeException($message);
38
        }
39 4
    }
40
41 6
    final public static function assertStringable($value, string $message)
42
    {
43 6
        if (!is_scalar($value)) {
44 4
            if (!self::isStrigableObject($value)) {
45 1
                throw new NotConvertibleToStringException($message);
46
            }
47
        }
48 5
    }
49
50 4
    private static function isStrigableObject($value): bool
51
    {
52 4
        return is_object($value) && method_exists($value, "__toString");
53
    }
54
55 11
    final public static function assertValidCallable(callable $callable, array $parameters)
56
    {
57 11
        $reflected = new ReflectionFunction($callable);
58 11
        if (count($reflected->getParameters()) !== count($parameters)) {
59
            throw new NotApplicableCallableException(
60
                "The number of parameters of the given callable does not match the expected number."
61
            );
62
        }
63 11
        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...
64 11
            $reflectedParamType = $reflected->getParameters()[$i]->getType();
65 11
            $expectedParam = $parameters[$i];
66 11
            switch ($expectedParam) {
67 11
                case "scalar":
68 5
                    if (!in_array($reflectedParamType, ["int", "string", "bool", "float", null])) {
69 1
                        self::throwNotApplicableCallableException($i, "scalar", $reflectedParamType);
70
                    }
71 4
                    break;
72 10
                case "mixed":
73
                    //ignore, since every type is allowed
74 4
                    break;
75
                default:
76 7
                    if ($reflectedParamType->getName() !== $expectedParam) {
0 ignored issues
show
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

76
                    if ($reflectedParamType->/** @scrutinizer ignore-call */ getName() !== $expectedParam) {
Loading history...
77
                        self::throwNotApplicableCallableException($i, $expectedParam, $reflectedParamType);
78
                    }
79
            }
80
        }
81 10
    }
82
83 1
    private static function throwNotApplicableCallableException($paramNumber, $expectedType, $actualType)
84
    {
85 1
        throw new NotApplicableCallableException(
86 1
            sprintf(
87 1
                "Parameter %d of type %s does not match the expected type of %s",
88
                $paramNumber,
89
                $actualType,
90
                $expectedType
91
            )
92
        );
93
    }
94
95
    /**
96
     * @param $object
97
     * @param string $message
98
     * @return void
99
     */
100
    final public static function assertComparable($object, string $message): void {
101
        if (is_scalar($object)) {
102
            return;
103
        }
104
        if (method_exists($object, '__toString')) {
105
            return;
106
        }
107
        if ($object instanceof Comparable) {
108
            return;
109
        }
110
        throw new ObjectIsNotComparableException($message);
111
    }
112
}
113
114
/**
115
 * @param $value
116
 * @param string $message description that will be included in the failure message if the assertion fails.
117
 * @return void
118
 */
119
function assertScalar($value, string $message): void
120
{
121 56
    Functions::assertScalar($value, $message);
122 55
}
123
124
/**
125
 * @param $value
126
 * @param string $fqcn full qualified class name
127
 * @param string $message description that will be included in the failure message if the assertion fails.
128
 * @return void
129
 */
130
function assertType($value, string $fqcn, string $message): void
131
{
132 5
    Functions::assertType($value, $fqcn, $message);
133 4
}
134
135
/**
136
 * @param $value
137
 * @param string $message description that will be included in the failure message if the assertion fails.
138
 * @return void
139
 */
140
function assertStringable($value, string $message): void
141
{
142 6
    Functions::assertStringable($value, $message);
143 5
}
144
145
146
function assertValidCallable(callable $callable, array $parameters)
147
{
148 11
    Functions::assertValidCallable($callable, $parameters);
149 10
}
150
151
152
function assertComparable($object, string $message): void
153
{
154
    Functions::assertComparable($object, $message);
155
}
156