Passed
Push — master ( 1dbc05...713241 )
by Bruno
03:36
created

BelongsToDirective::processModelFieldDirective()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
nc 1
nop 4
dl 0
loc 6
ccs 1
cts 1
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Modelarium\Laravel\Directives;
4
5
use Formularium\Datatype;
6
use Formularium\Factory\DatatypeFactory;
7
use GraphQL\Type\Definition\ObjectType;
8
use Illuminate\Support\Str;
9
use Modelarium\Datatypes\RelationshipFactory;
10
use Modelarium\Exception\DirectiveException;
11
use Modelarium\Laravel\Targets\Interfaces\MigrationDirectiveInterface;
12
use Modelarium\Laravel\Targets\ModelGenerator;
13
use Modelarium\Laravel\Targets\SeedGenerator;
14
use Modelarium\Laravel\Targets\Interfaces\ModelDirectiveInterface;
15
use Modelarium\Laravel\Targets\Interfaces\SeedDirectiveInterface;
16
use Modelarium\Laravel\Targets\MigrationCodeFragment;
17
use Modelarium\Laravel\Targets\MigrationGenerator;
18
use Modelarium\Parser;
19
20
class BelongsToDirective implements MigrationDirectiveInterface, ModelDirectiveInterface, SeedDirectiveInterface
21
{
22
    public static function processMigrationTypeDirective(
23
        MigrationGenerator $generator,
24
        \GraphQL\Language\AST\DirectiveNode $directive
25
    ): void {
26
        throw new DirectiveException("Directive not supported here");
27
    }
28
29
    public static function processMigrationFieldDirective(
30
        MigrationGenerator $generator,
31
        \GraphQL\Type\Definition\FieldDefinition $field,
32
        \GraphQL\Language\AST\DirectiveNode $directive,
33
        MigrationCodeFragment $code
34
    ): void {
35
        throw new DirectiveException("Directive not supported here");
36
    }
37
38 4
    public static function processMigrationRelationshipDirective(
39
        MigrationGenerator $generator,
40
        \GraphQL\Type\Definition\FieldDefinition $field,
41
        \GraphQL\Language\AST\DirectiveNode $directive,
42
        MigrationCodeFragment $codeFragment
43
    ): void {
44 4
        $lowerName = lcfirst($generator->getInflector()->singularize($field->name));
45 4
        $fieldName = $lowerName . '_id';
46
47 4
        list($type, $isRequired) = Parser::getUnwrappedType($field->getType());
48 4
        $typeName = $type->name;
49 4
        $tableName = MigrationGenerator::toTableName($typeName);
50
51 4
        $targetType = $generator->parser->getType($typeName);
52 4
        if (!$targetType) {
53
            throw new DirectiveException("Cannot get type {$typeName} as a relationship to {$generator->getBaseName()}");
54 4
        } elseif (!($targetType instanceof ObjectType)) {
55
            throw new DirectiveException("{$typeName} is not a type for a relationship to {$generator->getBaseName()}");
56
        }
57
58
        // we don't know what is the reverse relationship name at this point. so let's guess all possibilities
59 4
        $targetField = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $targetField is dead and can be removed.
Loading history...
60
        try {
61 4
            $targetField = $targetType->getField($tableName);
62 4
        } catch (\GraphQL\Error\InvariantViolation $e) {
63
            // pass
64
        }
65 4
        if (!$targetField) {
0 ignored issues
show
introduced by
$targetField is of type GraphQL\Type\Definition\FieldDefinition, thus it always evaluated to true.
Loading history...
66
            try {
67
                // many to many
68 4
                $targetField = $targetType->getField($generator->getTableName());
69 3
            } catch (\GraphQL\Error\InvariantViolation $e) {
70
                // pass
71
            }
72
        }
73 4
        if (!$targetField) {
0 ignored issues
show
introduced by
$targetField is of type GraphQL\Type\Definition\FieldDefinition, thus it always evaluated to true.
Loading history...
74
            try {
75
                // one to many
76 3
                $targetField = $targetType->getField($generator->getLowerFirstLetterNamePlural());
77 3
            } catch (\GraphQL\Error\InvariantViolation $e) {
78
                // pass
79
            }
80
        }
81 4
        if (!$targetField) {
0 ignored issues
show
introduced by
$targetField is of type GraphQL\Type\Definition\FieldDefinition, thus it always evaluated to true.
Loading history...
82
            // one to one
83 3
            $targetField = $targetType->getField($generator->getLowerFirstLetterName());
84
        }
85
86 4
        $targetDirectives = $targetField->astNode->directives;
87 4
        foreach ($targetDirectives as $targetDirective) {
88 4
            switch ($targetDirective->name->value) {
89 4
                case 'hasOne':
90 1
                case 'hasMany':
91 4
                    $codeFragment->appendBase('->unsignedBigInteger("' . $fieldName . '")');
92 4
                break;
93
            }
94
        }
95 4
    }
96
97
    public static function processModelTypeDirective(
98
        ModelGenerator $generator,
99
        \GraphQL\Language\AST\DirectiveNode $directive
100
    ): void {
101
        // nothing
102
    }
103
104 4
    public static function processModelFieldDirective(
105
        ModelGenerator $generator,
106
        \GraphQL\Type\Definition\FieldDefinition $field,
107
        \Formularium\Field $fieldFormularium,
108
        \GraphQL\Language\AST\DirectiveNode $directive
109
    ): void {
110
        // nothing
111 4
    }
112
113 4
    public static function processModelRelationshipDirective(
114
        ModelGenerator $generator,
115
        \GraphQL\Type\Definition\FieldDefinition $field,
116
        \GraphQL\Language\AST\DirectiveNode $directive,
117
        \Formularium\Datatype $datatype = null
118
    ): ?\Formularium\Datatype {
119 4
        $fieldName = $generator->getInflector()->singularize($field->name);
120
121 4
        $sourceTypeName = $generator->getBaseName();
122 4
        $targetTypeName = $fieldName;
123 4
        $relationship = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $relationship is dead and can be removed.
Loading history...
124 4
        $isInverse = false;
0 ignored issues
show
Unused Code introduced by
The assignment to $isInverse is dead and can be removed.
Loading history...
125
126 4
        $targetClass = Str::studly($fieldName);
127 4
        $generateRandom = true; // TODO
0 ignored issues
show
Unused Code introduced by
The assignment to $generateRandom is dead and can be removed.
Loading history...
128 4
        $relationship = RelationshipFactory::RELATIONSHIP_ONE_TO_MANY;
129 4
        $isInverse = true;
130 4
        $generator->class->addMethod($fieldName)
131 4
            ->setPublic()
132 4
            ->setReturnType('\\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo')
133 4
            ->setBody("return \$this->belongsTo($targetClass::class);");
134
135 4
        $datatypeName = $generator->getRelationshipDatatypeName(
136 4
            $relationship,
137
            $isInverse,
138
            $sourceTypeName,
139
            $targetTypeName
140
        );
141 4
        return DatatypeFactory::factory($datatypeName);
142
    }
143
144
    public static function processSeedTypeDirective(
145
        SeedGenerator $generator,
146
        \GraphQL\Language\AST\DirectiveNode $directive
147
    ): void {
148
        // empty
149
    }
150
151 4
    public static function processSeedFieldDirective(
152
        SeedGenerator $generator,
153
        \GraphQL\Type\Definition\FieldDefinition $field,
154
        \GraphQL\Language\AST\DirectiveNode $directive
155
    ): void {
156 4
        $type1 = $generator->getLowerFirstLetterName();
157 4
        $type2 = $generator->getInflector()->singularize($field->name);
158
159 4
        if (strcasecmp($type1, $type2) < 0) { // TODO: check this, might not work
160 4
            $relationship = $generator->getInflector()->pluralize($field->name);
161 4
            $generator->extraCode[] = self::makeManyToManySeed($type1, $type2, $relationship);
162
        }
163 4
    }
164
165 4
    protected static function makeManyToManySeed(string $sourceModel, string $targetModel, string $relationship): string
0 ignored issues
show
Unused Code introduced by
The parameter $sourceModel is not used and could be removed. ( Ignorable by Annotation )

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

165
    protected static function makeManyToManySeed(/** @scrutinizer ignore-unused */ string $sourceModel, string $targetModel, string $relationship): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
166
    {
167 4
        $className = Str::studly($targetModel);
168
        return <<<EOF
169
170
        try {
171 4
            \${$targetModel}Items = App\\Models\\$className::all();
172 4
            \$model->{$relationship}()->attach(
173 4
                \${$targetModel}Items->random(rand(1, 3))->pluck('id')->toArray()
174
            );
175
        }
176
        catch (\InvalidArgumentException \$e) {
177 4
            \$model->{$relationship}()->attach(
178 4
                \${$targetModel}Items->random(1)->pluck('id')->toArray()
179
            );
180
        }
181
EOF;
182
    }
183
}
184