Completed
Push — master ( 296743...12eab9 )
by Kirill
36:17
created

SchemaValidator   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 101
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 88.57%

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 3
dl 0
loc 101
ccs 31
cts 35
cp 0.8857
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A match() 0 4 1
A validate() 0 5 1
A checkQueryExistence() 0 9 2
A checkSchemaActionCompatibilities() 0 6 1
A checkSchemaField() 0 14 2
A checkSchemaFieldCompatibility() 0 24 3
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\SDL\Reflection\Validation\Definitions;
11
12
use Railt\SDL\Contracts\Definitions\Definition;
13
use Railt\SDL\Contracts\Definitions\ObjectDefinition;
14
use Railt\SDL\Contracts\Definitions\SchemaDefinition;
15
use Railt\SDL\Exceptions\TypeConflictException;
16
17
/**
18
 * Class SchemaValidator
19
 */
20
class SchemaValidator extends BaseDefinitionValidator
21
{
22
    /**
23
     * @param Definition $definition
24
     * @return bool
25
     */
26 6563
    public function match(Definition $definition): bool
27
    {
28 6563
        return $definition instanceof SchemaDefinition;
29
    }
30
31
    /**
32
     * @param Definition|SchemaDefinition $definition
33
     * @return void
34
     * @throws \Railt\SDL\Exceptions\TypeConflictException
35
     */
36 150
    public function validate(Definition $definition): void
37
    {
38 150
        $this->checkQueryExistence($definition);
0 ignored issues
show
Compatibility introduced by
$definition of type object<Railt\SDL\Contrac...Definitions\Definition> is not a sub-type of object<Railt\SDL\Contrac...tions\SchemaDefinition>. It seems like you assume a child interface of the interface Railt\SDL\Contracts\Definitions\Definition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
39 138
        $this->checkSchemaActionCompatibilities($definition);
0 ignored issues
show
Compatibility introduced by
$definition of type object<Railt\SDL\Contrac...Definitions\Definition> is not a sub-type of object<Railt\SDL\Contrac...tions\SchemaDefinition>. It seems like you assume a child interface of the interface Railt\SDL\Contracts\Definitions\Definition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
40 126
    }
41
42
    /**
43
     * @param SchemaDefinition $schema
44
     * @return void
45
     * @throws \Railt\SDL\Exceptions\TypeConflictException
46
     */
47 150
    private function checkQueryExistence(SchemaDefinition $schema): void
48
    {
49
        try {
50 150
            $schema->getQuery();
51 12
        } catch (\TypeError $typo) {
52 12
            $error = \sprintf('The %s must contain an Object type reference to the "query" field', $schema);
53 12
            throw new TypeConflictException($error, $this->getCallStack(), $typo);
54
        }
55 138
    }
56
57
    /**
58
     * @param SchemaDefinition $schema
59
     * @return void
60
     * @throws \Railt\SDL\Exceptions\TypeConflictException
61
     */
62 138
    private function checkSchemaActionCompatibilities(SchemaDefinition $schema): void
63
    {
64 138
        $this->checkSchemaField($schema, 'query', 'getQuery');
65 138
        $this->checkSchemaField($schema, 'mutation', 'getMutation');
66 132
        $this->checkSchemaField($schema, 'subscription', 'getSubscription');
67 126
    }
68
69
    /**
70
     * @param SchemaDefinition $schema
71
     * @param string $field
72
     * @param string $action
73
     * @return void
74
     * @throws \Railt\SDL\Exceptions\TypeConflictException
75
     */
76 138
    private function checkSchemaField(SchemaDefinition $schema, string $field, string $action): void
77
    {
78
        try {
79 138
            $definition = $schema->$action();
80 138
            $this->checkSchemaFieldCompatibility($field, $definition);
81 12
        } catch (\TypeError $typo) {
82 12
            $error = \vsprintf('The %s contain incompatible type for field %s', [
83 12
                $schema,
84 12
                $field,
85
            ]);
86
87 12
            throw new TypeConflictException($error, $this->getCallStack(), $typo);
88
        }
89 138
    }
90
91
    /**
92
     * @param string $field
93
     * @param null|Definition $definition
94
     * @return void
95
     */
96 138
    private function checkSchemaFieldCompatibility(string $field, ?Definition $definition): void
97
    {
98
        /**
99
         * Action is not defined. All OK. The presence
100
         * of the "query" field is checked above.
101
         */
102 138
        if ($definition === null) {
103 84
            return;
104
        }
105
106
        /**
107
         * The schema action should be compatible with Object type only.
108
         */
109 138
        if ($definition instanceof ObjectDefinition) {
110 138
            return;
111
        }
112
113
        $error = \vsprintf('Schema field %s contain incompatible type %s', [
114
            $field,
115
            $definition,
116
        ]);
117
118
        throw new TypeConflictException($error, $this->getCallStack());
119
    }
120
}
121