Passed
Pull Request — 2.x (#66)
by Maxim
15:09
created

MorphTrait::ensureMorphField()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
nc 3
nop 4
dl 0
loc 17
ccs 11
cts 11
cp 1
crap 3
rs 9.9666
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Cycle\Schema\Relation\Traits;
6
7
use Cycle\Schema\Definition\Entity;
8
use Cycle\Schema\Definition\Field;
9
use Cycle\Schema\Definition\Map\FieldMap;
10
use Cycle\Schema\Exception\RelationException;
11
use Cycle\Schema\Registry;
12
use Cycle\Schema\Table\Column;
13
use Generator;
14
15
trait MorphTrait
16
{
17
    /**
18
     * @psalm-param non-empty-string $interface
19
     *
20
     * @psalm-assert class-string $interface
21
     *
22
     * @return Entity[]|Generator
23 112
     *
24
     * @psalm-return Generator<int, Entity>
25 112
     */
26 112
    protected function findTargets(Registry $registry, string $interface): Generator
27 112
    {
28 112
        foreach ($registry as $entity) {
29
            $class = $entity->getClass();
30
            if ($class === null || !in_array($interface, class_implements($class))) {
31 112
                continue;
32
            }
33 96
34
            yield $entity;
35
        }
36
    }
37
38
    /**
39
     * @param non-empty-string $interface
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...
40 112
     *
41
     * @throws RelationException
42 112
     *
43 112
     * @return array Tuple [name, Field]
44 112
     */
45
    protected function findOuterKey(Registry $registry, string $interface): array
46 112
    {
47 112
        $keys = null;
48 112
        $fields = null;
49
        $prevEntity = null;
50 112
51 112
        foreach ($this->findTargets($registry, $interface) as $entity) {
52 112
            $primaryFields = $entity->getPrimaryFields();
53 112
            $primaryKeys = $this->getPrimaryColumns($entity);
0 ignored issues
show
Bug introduced by
It seems like getPrimaryColumns() 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

53
            /** @scrutinizer ignore-call */ 
54
            $primaryKeys = $this->getPrimaryColumns($entity);
Loading history...
54 112
55 16
            if (null === $keys) {
56 16
                $keys = $primaryKeys;
57 16
                $fields = $primaryFields;
58 16
                $prevEntity = $entity;
59 16
            } elseif ($keys !== $primaryKeys && $prevEntity !== null) {
60 16
                throw new RelationException(sprintf(
61
                    'Inconsistent primary key reference (%s). PKs: (%s). Required PKs [%s]: (%s).',
62
                    $entity->getRole() ?? 'unknown',
63
                    implode(',', $primaryKeys),
64
                    $prevEntity->getRole() ?? 'unknown',
0 ignored issues
show
Bug introduced by
The method getRole() does not exist on null. ( Ignorable by Annotation )

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

64
                    $prevEntity->/** @scrutinizer ignore-call */ 
65
                                 getRole() ?? 'unknown',

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
65 96
                    implode(',', $keys)
0 ignored issues
show
Bug introduced by
$keys of type void is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

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

65
                    implode(',', /** @scrutinizer ignore-type */ $keys)
Loading history...
66
                ));
67
            }
68
        }
69 96
70
        if (null === $fields) {
71
            throw new RelationException('Unable to find morphed parent.');
72 192
        }
73
74 192
        return [$keys, $fields];
75
    }
76
77
    /**
78
     * @param non-empty-string $column
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...
79 192
     */
80 192
    protected function ensureMorphField(Entity $target, string $column, int $length, bool $nullable = false): void
81 192
    {
82 192
        if ($target->getFields()->has($column)) {
83
            // field already exists and defined by the user
84 192
            return;
85 144
        }
86
87
        $field = new Field();
88 192
        $field->setEntityClass($target->getClass());
89 192
        $field->setColumn($column);
90
        $field->setType(sprintf('string(%s)', $length));
91 48
92
        if ($nullable) {
93 48
            $field->getOptions()->set(Column::OPT_NULLABLE, true);
94
        }
95 48
96 48
        $target->getFields()->set($column, $field);
97 48
    }
98 24
99 48
    protected function mergeIndex(Registry $registry, Entity $source, FieldMap ...$mergeMaps): void
100
    {
101
        $table = $registry->getTableSchema($source);
102
103 48
        if ($this->options->get(self::INDEX_CREATE)) {
0 ignored issues
show
Bug introduced by
The constant Cycle\Schema\Relation\Tr...orphTrait::INDEX_CREATE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
104 48
            /** @psalm-suppress NamedArgumentNotAllowed */
105
            $index = array_merge(...array_map(
106
                static function (FieldMap $map): array {
107 48
                    return $map->getColumnNames();
108
                },
109
                $mergeMaps
110
            ));
111
112
            if (count($index) > 0) {
113
                $table->index($index);
114
            }
115
        }
116
    }
117
}
118