Passed
Push — master ( e7bef7...3228c5 )
by Vladimir
03:06
created

SchemaGenerator   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 15
eloc 77
dl 0
loc 148
c 0
b 0
f 0
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A resolveField() 0 3 1
A buildSchema() 0 4 1
A loadType() 0 6 1
A getFieldTypeAndName() 0 14 3
A createFieldArgs() 0 20 1
A createType() 0 23 3
A buildQueryType() 0 6 1
A createTypeFields() 0 31 3
1
<?php
2
namespace GraphQL\Benchmarks\Utils;
3
4
use GraphQL\Type\Definition\EnumType;
5
use GraphQL\Type\Definition\InputObjectType;
6
use GraphQL\Type\Definition\ObjectType;
7
use GraphQL\Type\Definition\Type;
8
use GraphQL\Type\Schema;
9
10
class SchemaGenerator
11
{
12
    private $config = [
13
        'totalTypes' => 100,
14
        'nestingLevel' => 10,
15
        'fieldsPerType' => 10,
16
        'listFieldsPerType' => 2
17
    ];
18
19
    private $typeIndex = 0;
20
21
    private $objectTypes = [];
22
23
    /**
24
     * BenchmarkSchemaBuilder constructor.
25
     * @param array $config
26
     */
27
    public function __construct(array $config)
28
    {
29
        $this->config = array_merge($this->config, $config);
30
    }
31
32
    public function buildSchema()
33
    {
34
        return new Schema([
35
            'query' => $this->buildQueryType()
36
        ]);
37
    }
38
39
    public function buildQueryType()
40
    {
41
        $this->typeIndex = 0;
42
        $this->objectTypes = [];
43
44
        return $this->createType(0);
45
    }
46
47
    public function loadType($name)
48
    {
49
        $tokens = explode('_', $name);
50
        $nestingLevel = (int) $tokens[1];
51
52
        return $this->createType($nestingLevel, $name);
53
    }
54
55
    protected function createType($nestingLevel, $typeName = null)
56
    {
57
        if ($this->typeIndex > $this->config['totalTypes']) {
58
            throw new \Exception(
59
                "Cannot create new type: there are already {$this->typeIndex} ".
60
                "which exceeds allowed number of {$this->config['totalTypes']} types total"
61
            );
62
        }
63
64
        $this->typeIndex++;
65
        if (!$typeName) {
66
            $typeName = 'Level_' . $nestingLevel . '_Type' . $this->typeIndex;
67
        }
68
69
        $type = new ObjectType([
70
            'name' => $typeName,
71
            'fields' => function() use ($typeName, $nestingLevel) {
72
                return $this->createTypeFields($typeName, $nestingLevel + 1);
73
            }
74
        ]);
75
76
        $this->objectTypes[$typeName] = $type;
77
        return $type;
78
    }
79
80
    protected function getFieldTypeAndName($nestingLevel, $fieldIndex)
81
    {
82
        if ($nestingLevel >= $this->config['nestingLevel']) {
83
            $fieldType = Type::string();
84
            $fieldName = 'leafField' . $fieldIndex;
85
        } else if ($this->typeIndex >= $this->config['totalTypes']) {
86
            $fieldType = $this->objectTypes[array_rand($this->objectTypes)];
87
            $fieldName = 'randomTypeField' . $fieldIndex;
88
        } else {
89
            $fieldType = $this->createType($nestingLevel);
90
            $fieldName = 'field' . $fieldIndex;
91
        }
92
93
        return [$fieldType, $fieldName];
94
    }
95
96
    protected function createTypeFields($typeName, $nestingLevel)
97
    {
98
        $fields = [];
99
        for ($index = 0; $index < $this->config['fieldsPerType']; $index++) {
100
            list($type, $name) = $this->getFieldTypeAndName($nestingLevel, $index);
101
            $fields[] = [
102
                'name' => $name,
103
                'type' => $type,
104
                'resolve' => [$this, 'resolveField']
105
            ];
106
        }
107
        for ($index = 0; $index < $this->config['listFieldsPerType']; $index++) {
108
            list($type, $name) = $this->getFieldTypeAndName($nestingLevel, $index);
109
            $name = 'listOf' . ucfirst($name);
110
111
            $fields[] = [
112
                'name' => $name,
113
                'type' => Type::listOf($type),
114
                'args' => $this->createFieldArgs($name, $typeName),
115
                'resolve' => function() {
116
                    return [
117
                        'string1',
118
                        'string2',
119
                        'string3',
120
                        'string4',
121
                        'string5',
122
                    ];
123
                }
124
            ];
125
        }
126
        return $fields;
127
    }
128
129
    protected function createFieldArgs($fieldName, $typeName)
130
    {
131
        return [
132
            'argString' => [
133
                'type' => Type::string()
134
            ],
135
            'argEnum' => [
136
                'type' => new EnumType([
137
                    'name' => $typeName . $fieldName . 'Enum',
138
                    'values' => [
139
                        "ONE", "TWO", "THREE"
140
                    ]
141
                ])
142
            ],
143
            'argInputObject' => [
144
                'type' => new InputObjectType([
145
                    'name' => $typeName . $fieldName . 'Input',
146
                    'fields' => [
147
                        'field1' => Type::string(),
148
                        'field2' => Type::int()
149
                    ]
150
                ])
151
            ]
152
        ];
153
    }
154
155
    public function resolveField($objectValue, $args, $context, $resolveInfo)
156
    {
157
        return $resolveInfo->fieldName . '-value';
158
    }
159
}
160