Passed
Pull Request — 2.x (#66)
by Maxim
13:26
created

MorphTrait::findOuterKey()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6.0052

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 20
nc 7
nop 2
dl 0
loc 30
ccs 18
cts 19
cp 0.9474
crap 6.0052
rs 8.9777
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
     * @psalm-assert class-string $interface
20
     *
21
     * @return Entity[]|Generator
22
     *
23 112
     * @psalm-return Generator<int, Entity>
24
     */
25 112
    protected function findTargets(Registry $registry, string $interface): Generator
26 112
    {
27 112
        foreach ($registry as $entity) {
28 112
            $class = $entity->getClass();
29
            if ($class === null || !in_array($interface, class_implements($class))) {
30
                continue;
31 112
            }
32
33 96
            yield $entity;
34
        }
35
    }
36
37
    /**
38
     * @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...
39
     *
40 112
     * @throws RelationException
41
     *
42 112
     * @return array Tuple [name, Field]
43 112
     */
44 112
    protected function findOuterKey(Registry $registry, string $interface): array
45
    {
46 112
        $keys = null;
47 112
        $fields = null;
48 112
        $prevEntity = null;
49
50 112
        foreach ($this->findTargets($registry, $interface) as $entity) {
51 112
            $primaryFields = $entity->getPrimaryFields();
52 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

52
            /** @scrutinizer ignore-call */ 
53
            $primaryKeys = $this->getPrimaryColumns($entity);
Loading history...
53 112
54 112
            if (null === $keys) {
55 16
                $keys = $primaryKeys;
56 16
                $fields = $primaryFields;
57 16
                $prevEntity = $entity;
58 16
            } elseif ($keys !== $primaryKeys && $prevEntity !== null) {
59 16
                throw new RelationException(sprintf(
60 16
                    'Inconsistent primary key reference (%s). PKs: (%s). Required PKs [%s]: (%s).',
61
                    $entity->getRole() ?? 'unknown',
62
                    implode(',', $primaryKeys),
63
                    $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

63
                    $prevEntity->/** @scrutinizer ignore-call */ 
64
                                 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...
64
                    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

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