Passed
Push — master ( 384538...4f7dc7 )
by Anton
02:27
created

src/Relation/Traits/MorphTrait.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * Cycle ORM Schema Builder.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
declare(strict_types=1);
9
10
namespace Cycle\Schema\Relation\Traits;
11
12
use Cycle\Schema\Definition\Entity;
13
use Cycle\Schema\Definition\Field;
14
use Cycle\Schema\Exception\RelationException;
15
use Cycle\Schema\Registry;
16
use Cycle\Schema\Table\Column;
17
18
trait MorphTrait
19
{
20
    /**
21
     * @param Registry $registry
22
     * @param string   $interface
23
     * @return \Generator
24
     */
25
    protected function findTargets(Registry $registry, string $interface): \Generator
26
    {
27
        foreach ($registry as $entity) {
28
            $class = $entity->getClass();
29
            if ($class === null || !in_array($interface, class_implements($class))) {
30
                continue;
31
            }
32
33
            yield $entity;
34
        }
35
    }
36
37
    /**
38
     * @param Registry $registry
39
     * @param string   $interface
40
     * @return array Tuple [name, Field]
41
     *
42
     * @throws RelationException
43
     */
44
    protected function findOuterKey(Registry $registry, string $interface): array
45
    {
46
        /** @var Field|null $field */
47
        $key = null;
48
        $field = null;
49
50
        foreach ($this->findTargets($registry, $interface) as $entity) {
51
            $primaryKey = $this->getPrimary($entity);
0 ignored issues
show
It seems like getPrimary() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
            /** @scrutinizer ignore-call */ 
52
            $primaryKey = $this->getPrimary($entity);
Loading history...
52
            $primaryField = $entity->getFields()->get($primaryKey);
53
54
            if (is_null($field)) {
55
                $key = $primaryKey;
56
                $field = $primaryField;
57
            } else {
58
                if ($key != $primaryKey) {
59
                    throw new RelationException("Inconsistent primary key reference (name)");
60
                }
61
62
                if ($field->getType() != $primaryField->getType()) {
63
                    throw new RelationException("Inconsistent primary key reference (type)");
64
                }
65
            }
66
        }
67
68
        if (is_null($field)) {
69
            throw new RelationException("Unable to find morphed parent");
70
        }
71
72
        return [$key, $field];
73
    }
74
75
    /**
76
     * @param Entity $target
77
     * @param string $name
78
     * @param int    $lenght
79
     * @param bool   $nullable
80
     */
81
    protected function ensureMorphField(Entity $target, string $name, int $lenght, bool $nullable = false)
82
    {
83
        if ($target->getFields()->has($name)) {
84
            // field already exists and defined by the user
85
            return;
86
        }
87
88
        $field = new Field();
89
        $field->setColumn($name);
90
        $field->setType(sprintf("string(%s)", $lenght));
91
92
        if ($nullable) {
93
            $field->getOptions()->set(Column::OPT_NULLABLE, true);
94
        }
95
96
        $target->getFields()->set($name, $field);
97
    }
98
}