Rewrote argument resolver in the dependency manager to account for torrent tracker edge case.
This commit is contained in:
parent
1ee6dc8115
commit
8df1d32304
4 changed files with 46 additions and 33 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
0.2503.210003
|
||||
0.2503.211818
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
// Dependencies.php
|
||||
// Created: 2025-01-18
|
||||
// Updated: 2025-03-15
|
||||
// Updated: 2025-03-21
|
||||
|
||||
namespace Index;
|
||||
|
||||
|
@ -36,52 +36,54 @@ class Dependencies {
|
|||
* @return array<string|int, mixed>
|
||||
*/
|
||||
private function resolveArgs(ReflectionFunctionAbstract $constructor, array $args): array {
|
||||
$realArgs = [];
|
||||
$namedArgs = [];
|
||||
$seqArgs = [];
|
||||
foreach($args as $name => $value) {
|
||||
if(is_int($name) || ctype_digit($name))
|
||||
$seqArgs[] = $value;
|
||||
else
|
||||
$namedArgs[$name] = $value;
|
||||
}
|
||||
|
||||
$args = [];
|
||||
|
||||
$params = $constructor->getParameters();
|
||||
foreach($params as $paramInfo) {
|
||||
$paramName = $paramInfo->getName();
|
||||
if(array_key_exists($paramName, $args)) {
|
||||
$realArgs[] = $args[$paramName];
|
||||
unset($args[$paramName]);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// named values always take precedence, including explicit type erroring
|
||||
if(array_key_exists($paramName, $namedArgs)) {
|
||||
$value = $namedArgs[$paramName];
|
||||
} else {
|
||||
$value = null;
|
||||
$typeInfo = $paramInfo->getType();
|
||||
$allowsNull = $typeInfo === null || $typeInfo->allowsNull();
|
||||
$value = $paramInfo->isDefaultValueAvailable() ? $paramInfo->getDefaultValue() : null;
|
||||
|
||||
// maybe support intersection and union someday
|
||||
if($typeInfo instanceof ReflectionNamedType && !$typeInfo->isBuiltin()) {
|
||||
$className = $typeInfo->getName();
|
||||
if(!class_exists($className) && !interface_exists($className))
|
||||
throw new RuntimeException(sprintf('class in type does not exist: %s', $className));
|
||||
|
||||
$value = $this->resolve($className);
|
||||
if($value === null && !$allowsNull)
|
||||
throw new RuntimeException(sprintf('was not able to resolve %s', $className));
|
||||
if(class_exists($className) || interface_exists($className))
|
||||
$value = $this->resolve($className);
|
||||
}
|
||||
|
||||
if($value === null && !$allowsNull)
|
||||
throw new RuntimeException('required parameter has unsupported type definition');
|
||||
if($value === null) {
|
||||
if(count($seqArgs) > 0) {
|
||||
$value = $seqArgs[array_key_first($seqArgs)];
|
||||
if($typeInfo instanceof ReflectionNamedType && (!$typeInfo->isBuiltin() || $typeInfo->getName() === gettype($value)))
|
||||
array_shift($seqArgs);
|
||||
else
|
||||
$value = null;
|
||||
}
|
||||
|
||||
$realArgs[] = $value;
|
||||
continue;
|
||||
} catch(RuntimeException $ex) {
|
||||
if(count($args) > 0) {
|
||||
$realArgs[] = array_shift($args);
|
||||
continue;
|
||||
if($value === null && !$allowsNull && $paramInfo->isDefaultValueAvailable())
|
||||
$value = $paramInfo->getDefaultValue();
|
||||
}
|
||||
|
||||
if(!$paramInfo->isOptional())
|
||||
throw $ex;
|
||||
|
||||
$realArgs[] = null;
|
||||
}
|
||||
|
||||
$args[$paramName] = $value;
|
||||
}
|
||||
|
||||
return $realArgs;
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
// DependenciesTest.php
|
||||
// Created: 2025-01-21
|
||||
// Updated: 2025-03-07
|
||||
// Updated: 2025-03-21
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
@ -60,8 +60,7 @@ namespace {
|
|||
}
|
||||
|
||||
public function testRequiredDependency(): void {
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage(sprintf('was not able to resolve %s', DependenciesTest\DependencyTestInterface::class));
|
||||
$this->expectException(TypeError::class);
|
||||
|
||||
$deps = new Dependencies;
|
||||
$deps->register(DependenciesTest\RequiredParamTestClass::class);
|
||||
|
|
|
@ -112,6 +112,14 @@ final class RouterTest extends TestCase {
|
|||
return sprintf('still the profile of %s', $beans);
|
||||
}
|
||||
|
||||
#[ExactRoute('GET', '/announce')]
|
||||
#[ExactRoute('GET', '/announce.php')]
|
||||
#[PatternRoute('GET', '/announce/([A-Za-z0-9]+)')]
|
||||
#[PatternRoute('GET', '/announce.php/([A-Za-z0-9]+)')]
|
||||
public function getMultipleTestWithDefault(string $key = 'empty'): string {
|
||||
return $key;
|
||||
}
|
||||
|
||||
public function hasNoAttr(): string {
|
||||
return 'not a route';
|
||||
}
|
||||
|
@ -126,6 +134,10 @@ final class RouterTest extends TestCase {
|
|||
$this->assertSame('meow', (string)$router->handle(HttpRequest::createRequestWithoutBody('POST', '/meow'))->getBody());
|
||||
$this->assertSame('profile of Cool134', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/profile/Cool134'))->getBody());
|
||||
$this->assertSame('still the profile of Cool134', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/profile-but-raw/Cool134'))->getBody());
|
||||
$this->assertSame('empty', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/announce'))->getBody());
|
||||
$this->assertSame('empty', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/announce.php'))->getBody());
|
||||
$this->assertSame('Z643QANLgGNkF4D4h4qvFpyeXjx4TcDE', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/announce/Z643QANLgGNkF4D4h4qvFpyeXjx4TcDE'))->getBody());
|
||||
$this->assertSame('1aKq8VaGyHohNUUR7RzU1W57Z3hQ6m0YMazAkr2IoiSPsvQJ6QoQutywwiOBlNka', (string)$router->handle(HttpRequest::createRequestWithoutBody('GET', '/announce.php/1aKq8VaGyHohNUUR7RzU1W57Z3hQ6m0YMazAkr2IoiSPsvQJ6QoQutywwiOBlNka'))->getBody());
|
||||
}
|
||||
|
||||
public function testEEPROMSituation(): void {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue