Lines 100.00% 8 / 8
Functions and Methods 100.00% 4 / 4
Classes and Traits 100.00% 1 / 1
Name Lines Functions and Methods CRAP Classes and Traits
Morphs 100.00% 8 / 8 100.00% 4 / 4 5 100.00% 1 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 typeColumn 100.00% 1 / 1 100.00% 1 / 1 1
 keyColumn 100.00% 1 / 1 100.00% 1 / 1 1
 assertKeyTypeCapable 100.00% 5 / 5 100.00% 1 / 1 2
1<?php
2
3declare(strict_types=1);
4
5namespace BlueprintAU\Radiant\Attributes;
6
7use BlueprintAU\Radiant\Database\Schema\Enums\ColumnType;
8
9/**
10 * Declares a polymorphic (morph) column pair on the model's table.
11 *
12 * Emits two synthetic columns — `{name}_type` (the related model's
13 * class-string) and `{name}_id` (its primary-key value) — read and
14 * written through {@see \BlueprintAU\Radiant\Model::attribute()} /
15 * {@see \BlueprintAU\Radiant\Model::setAttribute()}. The key column's
16 * type defaults to bigint; declare `keyType:` when the morph targets use
17 * a different primary-key type. The alias convention is the related
18 * model's full class-string; renaming a class changes the stored alias —
19 * a data-migration concern documented in docs/relations.md.
20 */
21#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
22final class Morphs
23{
24    /**
25     * Create a morph-pair declaration.
26     *
27     * @param  string  $name
28     * @param  bool  $nullable
29     * @param  ColumnType  $keyType  The `{name}_id` column's type; every morph target's primary key must match it.
30     */
31    public function __construct(
32        public string $name,
33        public bool $nullable = false,
34        public ColumnType $keyType = ColumnType::BigInt,
35    ) {
36    }
37
38    /**
39     * The type-discriminator column name this declaration emits.
40     *
41     * @return string
42     */
43    public function typeColumn(): string
44    {
45        return $this->name . '_type';
46    }
47
48    /**
49     * The key column name this declaration emits.
50     *
51     * @return string
52     */
53    public function keyColumn(): string
54    {
55        return $this->name . '_id';
56    }
57
58    /**
59     * Assert the declared key type can hold a primary-key value.
60     *
61     * @return void
62     * @throws \InvalidArgumentException
63     */
64    public function assertKeyTypeCapable(): void
65    {
66        if (!$this->keyType->primaryKeyCapable()) {
67            throw new \InvalidArgumentException(
68                "#[Morphs(name: '{$this->name}')] declares keyType [{$this->keyType->value}], "
69                . 'which cannot hold a primary-key value; use an integer, string, char, or uuid type.'
70            );
71        }
72    }
73}