Issues (84)

src/Generator/ResolveInterfaces.php (1 issue)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\Schema\Generator;
6
7
use Cycle\Schema\Definition\Entity;
8
use Cycle\Schema\Exception\RegistryException;
9
use Cycle\Schema\Exception\RelationException;
10
use Cycle\Schema\GeneratorInterface;
11
use Cycle\Schema\Registry;
12
13
final class ResolveInterfaces implements GeneratorInterface
14
{
15
    // option to indicate that static link resolution is required
16
    public const STATIC_LINK = 'staticLink';
17
18
    /**
19
     * @param Registry $registry
20
     *
21
     * @return Registry
22
     */
23 48
    public function run(Registry $registry): Registry
24
    {
25 48
        foreach ($registry as $entity) {
26 48
            $this->compute($registry, $entity);
27
        }
28
29 24
        return $registry;
30
    }
31
32
    /**
33
     * @param Registry $registry
34
     * @param Entity   $entity
35
     *
36
     * @throws RelationException
37
     */
38 48
    protected function compute(Registry $registry, Entity $entity): void
39
    {
40 48
        foreach ($entity->getRelations() as $relation) {
41 48
            if (!$relation->getOptions()->has(self::STATIC_LINK)) {
42 16
                continue;
43
            }
44
45 32
            $target = $relation->getTarget();
46 32
            if ($registry->hasEntity($target)) {
47
                // no need to resolve
48
                continue;
49
            }
50
51 32
            $relation->setTarget($this->resolve($registry, $target));
52 8
            $relation->getOptions()->remove(self::STATIC_LINK);
53
        }
54 24
    }
55
56
    /**
57
     * @param Registry $registry
58
     * @param string   $target
59
     *
60
     * @return non-empty-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment non-empty-string at position 0 could not be parsed: Unknown type name 'non-empty-string' at position 0 in non-empty-string.
Loading history...
61
     */
62 32
    protected function resolve(Registry $registry, string $target): string
63
    {
64 32
        if (!interface_exists($target)) {
65 8
            throw new RelationException("Unable to resolve static link to non interface target `{$target}`");
66
        }
67
68 24
        $found = null;
69 24
        foreach ($registry->getIterator() as $entity) {
70 24
            if ($entity->getClass() === null) {
71
                continue;
72
            }
73
74
            try {
75 24
                $candidate = new \ReflectionClass($entity->getClass());
76
            } catch (\ReflectionException $e) {
77
                throw new RegistryException($e->getMessage(), $e->getCode(), $e);
78
            }
79
80 24
            if ($candidate->isSubclassOf($target) || $candidate->implementsInterface($target)) {
81 16
                if ($found !== null) {
82 8
                    throw new RelationException("Ambiguous static link to `{$target}`");
83
                }
84
85 16
                $found = $entity->getClass();
86
            }
87
        }
88
89 16
        if ($found !== null) {
90 8
            return $found;
91
        }
92
93 8
        throw new RelationException("Unable to resolve static link to `{$target}`");
94
    }
95
}
96