Lines 100.00% 27 / 27
Methods 100.00% 1 / 1
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 resolve 100.00% 27 / 27 100.00% 1 / 1 7
29final class ReferenceResolver
30{
31    /**
32     * Resolve a reference to its table name.
33     *
34     * @param  ForeignKeyReference  $reference
35     * @return string
36     * @throws \InvalidArgumentException
37     */
38    public static function resolve(string $reference): string
39    {
40        if (!str_contains($reference, '\\')) {
41            // A backslash-free input is a table name — unless it names an
42            // existing class. PHP's `::class` constant has NO leading
43            // backslash, so a global-namespace class-string would land here
44            // and masquerade as a table (the FK would compile against a
45            // nonexistent table and fail downstream with a confusing SQL
46            // error). Reject it here, where the message can say why.
47            if (class_exists($reference) && !is_a($reference, \BlueprintAU\Radiant\Model::class, true)) {
48                throw new \InvalidArgumentException(
49                    "A foreign key references [{$reference}], which is a class but not a "
50                    . 'Radiant model; a foreign key must reference a table name or a '
51                    . 'model class-string.'
52                );
53            }
54
55            return $reference;
56        }
57
58        if (!class_exists($reference)) {
59            throw new \InvalidArgumentException(
60                "A foreign key references [{$reference}], which is neither a table name "
61                . 'nor an existing model class-string.'
62            );
63        }
64
65        if (!is_a($reference, \BlueprintAU\Radiant\Model::class, true)) {
66            throw new \InvalidArgumentException(
67                "A foreign key references [{$reference}], which is a class but not a "
68                . 'Radiant model; a foreign key must reference a table name or a '
69                . 'model class-string.'
70            );
71        }
72
73        $table = MetadataFactory::for($reference)->tableName;
74
75        if ($table === null) {
76            throw new \InvalidArgumentException(
77                "A foreign key references model [{$reference}], which owns no table "
78                . '(no columns); a foreign key must reference a table-owning model or a '
79                . 'plain table name.'
80            );
81        }
82
83        return $table;
84    }
85}