Rewrote argument resolver in the dependency manager to account for torrent tracker edge case.

This commit is contained in:
flash 2025-03-21 18:19:04 +00:00
parent 1ee6dc8115
commit 8df1d32304
Signed by: flash
GPG key ID: 2C9C2C574D47FE3E
4 changed files with 46 additions and 33 deletions

View file

@ -1 +1 @@
0.2503.210003
0.2503.211818

View file

@ -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;
}
/**

View file

@ -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);

View file

@ -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 {