recursivity check
parent
6537a2db81
commit
94f5bcb2a1
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kartierung\Analyze;
|
||||||
|
|
||||||
|
use Kartierung\Analyze\Exception\InvalidEntity;
|
||||||
|
use Kartierung\Attribute\ListOf;
|
||||||
|
use ReflectionClass;
|
||||||
|
use ReflectionException;
|
||||||
|
|
||||||
|
readonly class RecursionCheck
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param class-string<object> $fqcn
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private string $fqcn
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function check(): void
|
||||||
|
{
|
||||||
|
/** @var list<class-string<object>> $seenClasses */
|
||||||
|
$seenClasses = [$this->fqcn];
|
||||||
|
$toProcess = [...$this->declaredListTypes($this->fqcn)];
|
||||||
|
|
||||||
|
while (!empty($toProcess)) {
|
||||||
|
$current = array_pop($toProcess);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// is there a better workaround?
|
||||||
|
new ReflectionClass($current);
|
||||||
|
|
||||||
|
if (in_array($current, $seenClasses)) {
|
||||||
|
throw new InvalidEntity(
|
||||||
|
"Entity $this->fqcn declares a recursive mapping. This is not supported."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$seenClasses[] = $current;
|
||||||
|
} catch (ReflectionException) {
|
||||||
|
// $current does not reference a class, skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param class-string<object> $fqcn
|
||||||
|
* @return list<class-string<object>>
|
||||||
|
*/
|
||||||
|
private function declaredListTypes(string $fqcn): array
|
||||||
|
{
|
||||||
|
$params = (new ReflectionClass($fqcn))->getConstructor()?->getParameters();
|
||||||
|
|
||||||
|
if ($params === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach ($params as $param) {
|
||||||
|
$listAttr = $param->getAttributes(ListOf::class);
|
||||||
|
if (empty($listAttr)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var ListOf $inst */
|
||||||
|
$inst = $listAttr[0]->newInstance();
|
||||||
|
$result[] = $inst->entitiyFqcn;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Kartierung\Analyze;
|
||||||
|
|
||||||
|
use Kartierung\Attribute\Id;
|
||||||
|
use Kartierung\Attribute\ListOf;
|
||||||
|
|
||||||
|
class EntityWithInfiniteRecursion
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#[Id]
|
||||||
|
public int $id,
|
||||||
|
#[ListOf(self::class)]
|
||||||
|
public array $children
|
||||||
|
) {}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue