Skip to content
This repository was archived by the owner on Oct 20, 2025. It is now read-only.

Commit 5403f5c

Browse files
committed
Refactor StrictTypes trait and InvalidTypesException for enhanced type validation and error handling. Update matchStrictType method to improve parameter handling and add comprehensive documentation. Introduce PHPUnit configuration and initial manual tests.
1 parent c87893c commit 5403f5c

File tree

5 files changed

+149
-42
lines changed

5 files changed

+149
-42
lines changed

Router/MapRoute.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ public function match(string $method, string|array $route): bool|array
215215
$param_value = $value[1];
216216

217217
$parsed_value = static::matchStrictType(
218-
$param_types,
219218
$param_value,
219+
$param_types,
220220
);
221221
$req[$param_name] = $parsed_value;
222222
}

phpunit.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<phpunit>
2+
<testsuites>
3+
<testsuite name="Manual Tests">
4+
<directory>./test/manualTest</directory>
5+
</testsuite>
6+
</testsuites>
7+
<bootstrap>vendor/autoload.php</bootstrap>
8+
</phpunit>

src/Utils/Routes/Exception/InvalidTypesException.php

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,22 @@
77

88
class InvalidTypesException extends \PhpSlides\Exception
99
{
10-
private static array $types = [
10+
/**
11+
* @var array $types List of valid data types for route parameters.
12+
*
13+
* The following types are supported:
14+
* - INT: Integer
15+
* - BOOL: Boolean
16+
* - JSON: JSON string
17+
* - ALPHA: Alphabetic characters
18+
* - ALNUM: Alphanumeric characters
19+
* - ARRAY: Array
20+
* - FLOAT: Floating point number
21+
* - STRING: String
22+
* - BOOLEAN: Boolean (alias for BOOL)
23+
* - INTEGER: Integer (alias for INT)
24+
*/
25+
protected static array $types = [
1126
'INT',
1227
'BOOL',
1328
'JSON',
@@ -16,9 +31,19 @@ class InvalidTypesException extends \PhpSlides\Exception
1631
'ARRAY',
1732
'FLOAT',
1833
'STRING',
34+
'BOOLEN',
1935
'INTEGER',
2036
];
2137

38+
39+
/**
40+
* Catches invalid strict types and throws an exception if any are found.
41+
*
42+
* @param array|string $type The type(s) to check against the recognized URL parameter types.
43+
* @param ?Closure $message Optional closure to generate a custom exception message.
44+
*
45+
* @throws self If any of the provided types are not recognized as URL parameter types.
46+
*/
2247
public static function catchInvalidStrictTypes (array|string $type, ?Closure $message = null): void
2348
{
2449
if (is_array($type))
@@ -54,6 +79,18 @@ public static function catchInvalidStrictTypes (array|string $type, ?Closure $me
5479
}
5580
}
5681

82+
83+
/**
84+
* Handles invalid parameter types by setting the HTTP response code and either
85+
* printing a custom error message or throwing an InvalidTypesException.
86+
*
87+
* @param array $typeRequested The types that were expected.
88+
* @param string $typeGotten The type that was actually received.
89+
* @param string|null $message Optional custom error message.
90+
* @param int $code The HTTP response code to set (default is 400).
91+
*
92+
* @return InvalidTypesException
93+
*/
5794
public static function catchInvalidParameterTypes (array $typeRequested, string $typeGotten, ?string $message = null, int $code = 400): InvalidTypesException
5895
{
5996
http_response_code($code);

src/Utils/Routes/StrictTypes.php

Lines changed: 87 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,38 @@
44

55
use PhpSlides\Src\Utils\Routes\Exception\InvalidTypesException;
66

7+
/**
8+
* Trait StrictTypes
9+
*
10+
* This trait is used to enforce strict type checking in the parameter types
11+
*
12+
* @package PhpSlides\Src\Utils\Routes
13+
*/
714
trait StrictTypes
815
{
916
/**
17+
* Matches the type of a given string against an array of types.
1018
*
11-
* @param string[] $types
12-
* @param string $haystack
13-
* @return int|bool|float|array|string
19+
* @param string $needle The string to check the type of.
20+
* @param array $haystack The array of types to match against.
21+
* @return bool Returns true if the type of the string matches any type in the array, false otherwise.
1422
*/
15-
protected static function matchType (array $types, string $haystack): bool
23+
protected static function matchType (string $needle, array $haystack): bool
1624
{
17-
$typeOfHaystack = self::typeOfString($haystack);
25+
$typeOfNeedle = self::typeOfString($needle);
1826

19-
foreach ($types as $type)
27+
foreach ($haystack as $type)
2028
{
21-
$type = $type === 'INTEGER' ? 'INT' : strtoupper(trim($type));
29+
$type = strtoupper(trim($type));
30+
$type = $type === 'INTEGER' ? 'INT' : $type;
31+
$type = $type === 'BOOLEAN' ? 'BOOL' : $type;
2232

23-
if (self::matches($type, $haystack))
33+
if (self::matches($needle, $type))
2434
{
2535
return true;
2636
}
2737

28-
if (strtoupper($type) === $typeOfHaystack)
38+
if (strtoupper($type) === $typeOfNeedle)
2939
{
3040
return true;
3141
}
@@ -34,76 +44,113 @@ protected static function matchType (array $types, string $haystack): bool
3444
return false;
3545
}
3646

47+
3748
/**
49+
* Matches the given string against a list of types and returns the value
50+
* cast to the matched type.
3851
*
39-
* @param string[] $types
40-
* @param string $haystack
41-
* @return int|bool|float|array|string
52+
* @param string $needle The string to match and cast.
53+
* @param string[] $haystack The list of types to match against.
54+
* @return int|bool|float|array|string The value cast to the matched type.
55+
* @throws InvalidTypesException If the type of the needle does not match any type in the haystack.
4256
*/
4357
protected static function matchStrictType (
44-
array $types,
45-
string $haystack,
58+
string $needle,
59+
array $haystack,
4660
): int|bool|float|array|string {
47-
$types = array_map(fn ($t) => strtoupper($t), $types);
48-
$typeOfHaystack = self::typeOfString($haystack);
61+
$types = array_map(fn ($t) => strtoupper($t), $haystack);
62+
$typeOfNeedle = self::typeOfString($needle);
4963

50-
if (self::matchType($types, $haystack))
64+
if (self::matchType($needle, $types))
5165
{
52-
return match ($typeOfHaystack)
66+
return match ($typeOfNeedle)
5367
{
54-
'INT' => (int) $haystack,
55-
'BOOL' => (bool) $haystack,
56-
'FLOAT' => (float) $haystack,
57-
'ARRAY' => json_decode($haystack, true),
58-
default => $haystack,
68+
'INT' => (int) $needle,
69+
'BOOL' => (bool) $needle,
70+
'FLOAT' => (float) $needle,
71+
'ARRAY' => json_decode($needle, true),
72+
default => $needle,
5973
};
6074
}
6175

62-
throw InvalidTypesException::catchInvalidParameterTypes($types, $typeOfHaystack);
76+
throw InvalidTypesException::catchInvalidParameterTypes($types, $typeOfNeedle);
6377
}
6478

65-
private static function matches ($type, $haystack): bool
79+
80+
/**
81+
* Matches the type of the given needle against the specified haystack type.
82+
*
83+
* This method checks if the type of the needle matches the type specified in the haystack.
84+
* If the haystack specifies an array type, it will recursively check each element of the array.
85+
*
86+
* @param string $needle The value to check.
87+
* @param string $haystack The type specification to match against.
88+
* @return bool Returns true if the needle matches the haystack type, otherwise false.
89+
* @throws InvalidTypesException If the needle does not match the haystack type.
90+
*/
91+
private static function matches (string $needle, string $haystack): bool
6692
{
67-
$typeOfHaystack = self::typeOfString((string) $haystack);
68-
$typeOfHaystack2 = $typeOfHaystack;
69-
$haystack2 = $haystack;
93+
$typeOfNeedle = self::typeOfString((string) $needle);
94+
$typeOfNeedle2 = $typeOfNeedle;
95+
$needle2 = $needle;
7096

97+
/**
98+
* MATCH ARRAY RECURSIVELY
99+
*/
71100
if (
72-
preg_match('/ARRAY<(.+)>/', $type, $matches) &&
73-
$typeOfHaystack === 'ARRAY'
101+
preg_match('/ARRAY<(.+)>/', $haystack, $matches) &&
102+
$typeOfNeedle === 'ARRAY'
74103
)
75104
{
76-
$haystack = json_decode($haystack, true);
105+
$needle = json_decode($needle, true);
77106
$eachArrayTypes = explode(',', $matches[1]);
78107

79108
foreach ($eachArrayTypes as $key => $eachArrayType)
80109
{
81-
$haystack2 = is_array($haystack[$key])
82-
? json_encode($haystack[$key])
83-
: (string) $haystack[$key];
110+
$needle2 = is_array($needle[$key])
111+
? json_encode($needle[$key])
112+
: (string) $needle[$key];
84113

85114
$eachTypes = preg_split('/\|(?![^<]*>)/', trim($eachArrayType));
86-
$typeOfHaystack2 = self::typeOfString($haystack2);
115+
$typeOfNeedle2 = self::typeOfString($needle2);
87116

88-
if (!self::matchType($eachTypes, $haystack2))
117+
if (!self::matchType($needle2, $eachTypes))
89118
{
90119
$requested = implode(', ', $eachTypes);
91120
InvalidTypesException::catchInvalidStrictTypes($eachTypes);
92121
throw InvalidTypesException::catchInvalidParameterTypes(
93122
$eachTypes,
94-
$typeOfHaystack2,
95-
"Invalid request parameter type. {{$requested}} requested on array index $key, but got {{$typeOfHaystack2}}",
123+
$typeOfNeedle2,
124+
"Invalid request parameter type. {{$requested}} requested on array index $key, but got {{$typeOfNeedle2}}",
96125
);
97126
}
98127
}
99128
return true;
100129
}
101130

102-
InvalidTypesException::catchInvalidStrictTypes($type);
131+
InvalidTypesException::catchInvalidStrictTypes($haystack);
103132
return false;
104133
}
105134

106-
private static function typeOfString (string $string)
135+
136+
/**
137+
* Determines the type of a given string.
138+
*
139+
* This method analyzes the input string and returns a string representing its type.
140+
* The possible return values are:
141+
* - 'FLOAT' if the string represents a floating-point number.
142+
* - 'INT' if the string represents an integer.
143+
* - 'BOOL' if the string represents a boolean value ('true' or 'false').
144+
* - 'ALPHA' if the string contains only alphabetic characters.
145+
* - 'ALNUM' if the string contains only alphanumeric characters.
146+
* - 'JSON' if the string is a valid JSON object.
147+
* - 'ARRAY' if the string is a valid JSON array.
148+
* - 'STRING' if the string does not match any of the above types.
149+
*
150+
* @param string $string The input string to be analyzed.
151+
* @return string The type of the input string.
152+
*/
153+
protected static function typeOfString (string $string): string
107154
{
108155
$jd = json_decode($string, false);
109156

test/manualTest/HelloWorldTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
use PHPUnit\Framework\TestCase;
3+
4+
class HelloWorldTest extends TestCase
5+
{
6+
public function testHelloWorld()
7+
{
8+
$this->assertEquals('Hello, World!', 'Hello, World!');
9+
}
10+
11+
public function testAddition()
12+
{
13+
$this->assertEquals(2, 1 + 1);
14+
}
15+
}

0 commit comments

Comments
 (0)