Skip to content

Commit d3fec1a

Browse files
Dispatcher validates the data types of the given parameters according to the message signature.
1 parent bf858b1 commit d3fec1a

3 files changed

Lines changed: 76 additions & 6 deletions

File tree

src/Magic/Dispatcher.php

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use ScaleUpStack\Metadata\FeatureAnalyzers\VirtualMethods;
1616
use ScaleUpStack\Metadata\Metadata\ClassMetadata;
1717
use ScaleUpStack\Metadata\Factory;
18+
use ScaleUpStack\Metadata\Metadata\DataTypeMetadata;
1819
use ScaleUpStack\Metadata\Metadata\VirtualMethodMetadata;
1920

2021
final class Dispatcher
@@ -96,7 +97,12 @@ private function doInvocation(
9697
throw new \Error("Calling a non-static method when not in object context.");
9798
}
9899

99-
$this->assertGivenParametersMatchMethodSignature($methodName, $arguments, $classMetadata);
100+
$this->assertGivenParametersMatchMethodSignature(
101+
$objectOrClassName,
102+
$methodName,
103+
$arguments,
104+
$classMetadata
105+
);
100106

101107
$return = $callHandler->execute($objectOrClassName, $methodName, $arguments, $classMetadata);
102108

@@ -158,16 +164,22 @@ private function determineCallHandler(
158164
return null;
159165
}
160166

167+
/**
168+
* @param object|string $objectContext
169+
*/
161170
private function assertGivenParametersMatchMethodSignature(
171+
$objectContext,
162172
string $methodName,
163-
array $parameters,
173+
array $givenParameters,
164174
ClassMetadata $classMetadata
165175
)
166176
{
177+
/** @var VirtualMethodMetadata $methodMetadata */
167178
$methodMetadata = $classMetadata->features[VirtualMethods::class][$methodName];
168-
$expectedParameterCount = count($methodMetadata->parameters);
169179

170-
$givenParametersCount = count($parameters);
180+
// validate parameter count according to method signature
181+
$expectedParameterCount = count($methodMetadata->parameters);
182+
$givenParametersCount = count($givenParameters);
171183

172184
if ($expectedParameterCount !== $givenParametersCount) {
173185
throw new \ArgumentCountError(
@@ -176,11 +188,31 @@ private function assertGivenParametersMatchMethodSignature(
176188
$expectedParameterCount > $givenParametersCount ? 'few' : 'many',
177189
$classMetadata->name,
178190
$methodName,
179-
count($parameters),
191+
count($givenParameters),
180192
$expectedParameterCount
181193
)
182194
);
183195
}
196+
197+
// validate parameters' data types according to method signature
198+
$key = 0;
199+
/** @var DataTypeMetadata $signatureParameter */
200+
foreach ($methodMetadata->parameters as $signatureParameterName => $signatureParameter) {
201+
$parameterValue = $givenParameters[$key];
202+
if (! $signatureParameter->validateVariable($parameterValue, $objectContext)) {
203+
throw new \TypeError(
204+
sprintf(
205+
'Argument %s (%s) passed to %s() must be of the type %s, %s given',
206+
$key + 1,
207+
$signatureParameterName,
208+
$methodName,
209+
$signatureParameter->declaration(),
210+
gettype($parameterValue)
211+
)
212+
);
213+
}
214+
$key++;
215+
}
184216
}
185217

186218
/**

tests/PhpUnit/Magic/DispatcherTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public function it_invokes_a_virtual_static_method_on_some_object_via_some_call_
8080
'myFactoryMethod',
8181
[
8282
17,
83+
'some string'
8384
],
8485
$supportedCallHandlers
8586
);
@@ -158,6 +159,41 @@ public function it_throws_an_exception_when_the_number_of_parameters_is_invalid(
158159
);
159160
}
160161

162+
/**
163+
* @test
164+
* @covers ::assertGivenParametersMatchMethodSignature()
165+
*/
166+
public function it_throws_an_exception_on_invalid_parameter_types()
167+
{
168+
// given an object, and a list of supported call handlers
169+
$object = new ClassForDispatcherTesting();
170+
$supportedCallHandlers = [
171+
[
172+
NamedConstructor::class,
173+
[
174+
'methodName' => 'myFactoryMethod',
175+
]
176+
]
177+
];
178+
179+
// when invoking an allowed method, but with wrong arguments
180+
// then an exception is thrown
181+
$this->expectException(\TypeError::class);
182+
$this->expectExceptionMessage(
183+
'Argument 2 (otherProperty) passed to myFactoryMethod() must be of the type string, integer given'
184+
);
185+
186+
$result = Dispatcher::invoke(
187+
$object,
188+
'myFactoryMethod',
189+
[
190+
17,
191+
42, // must be string
192+
],
193+
$supportedCallHandlers
194+
);
195+
}
196+
161197
/**
162198
* @test
163199
* @covers ::doInvocation()

tests/Resources/Magic/ClassForDispatcherTesting.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
namespace ScaleUpStack\EasyObject\Tests\Resources\Magic;
1414

1515
/**
16-
* @method static self myFactoryMethod(int $someProperty)
16+
* @method static self myFactoryMethod(int $someProperty, string $otherProperty)
1717
* @method int getSomeProperty()
1818
*/
1919
final class ClassForDispatcherTesting
2020
{
2121
private $someProperty = 42;
22+
23+
private $otherProperty;
2224
}

0 commit comments

Comments
 (0)