Completed
Pull Request — develop (#575)
by
unknown
102:40 queued 37:52
created

SchemaMapper::convert()   C

Complexity

Conditions 13
Paths 72

Size

Total Lines 67
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 67
rs 5.8281
c 0
b 0
f 0
cc 13
eloc 38
nc 72
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: taachja1
5
 * Date: 03.04.17
6
 * Time: 11:15
7
 */
8
9
namespace Graviton\GeneratorV2Bundle\Service;
10
11
12
use Graviton\GeneratorBundle\Definition\JsonDefinition;
13
use Graviton\GeneratorBundle\Definition\JsonDefinitionField;
14
use Graviton\GeneratorBundle\Definition\Schema\XDynamicKey;
15
16
class SchemaMapper
17
{
18
19
20
    public function convert(JsonDefinition $definition)
21
    {
22
        $schema = [
23
            "x-documentClass" => $definition->getId()
24
        ];
25
26
        if (!$definition->getDef()->getTarget()) {
27
           // return $schema;
28
        }
29
30
        $requiredFields = [];
31
        $searchableFields = [];
32
        $readOnlyFields = [];
33
34
35
        $schema = [
36
            "x-documentClass" => $definition->getId(),
37
            "title" => $definition->getTitle(),
38
            "description" => $definition->getDescription(),
39
            "x-recordOriginModifiable" => $definition->isRecordOriginModifiable(),
40
            "properties" => []
41
        ];
42
        if (method_exists($definition, 'isVersionedService')) {
43
            $schema["x-versioning"] = $definition->isVersionedService();
44
        }
45
46
        $exposeFieldNames = array_flip(['title', 'type', 'readOnly', 'description', 'recordOriginException']);
47
48
        if (!$definition->getDef()->getTarget()) {
49
            return $schema;
50
        }
51
52
        /** @var JsonDefinitionField $field */
53
        foreach ($definition->getFields() as $field) {
54
            $def = $field->getDefAsArray();
55
            $key = $field->getName();
56
            if (isset($def['required']) && $def['required']) {
57
                $requiredFields[] = $field->getName();
58
            }
59
            if (isset($def['searchable']) && $def['searchable']) {
60
                $searchableFields[] = $field->getName();
61
            }
62
            if (isset($def['readOnly']) && $def['readOnly']) {
63
                $readOnlyFields[] = $field->getName();
64
            }
65
66
            $data = array_intersect_key($def,$exposeFieldNames);
67
            $schema["properties"][$key] = $data;
68
69
            /** @var XDynamicKey $xkex */
70
            if (method_exists($field, 'getXDynamicKey') && $xkex = $field->getXDynamicKey()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Graviton\GeneratorBundle...initionElementInterface as the method getXDynamicKey() does only exist in the following implementations of said interface: Graviton\GeneratorBundle...ion\JsonDefinitionField, Graviton\GeneratorBundle...ition\JsonDefinitionRel.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
71
                $schema["properties"][$key]["x-dynamic-key"] = [
72
                    "document-id" => $xkex->getDocumentId(),
73
                    "repository-method" => $xkex->getRepositoryMethod(),
74
                    "ref-field" => $xkex->getRefField()
75
                ];
76
            }
77
        }
78
79
        $schema["required"] = $requiredFields;
80
        $schema["searchable"] = $searchableFields;
81
        $schema["readOnlyFields"] = $readOnlyFields;
82
83
        return $schema;
84
85
86
    }
87
88
89
    /*
90
     *
91
92
    {
93
94
  "x-documentClass": {{ (base ~ 'Document\\' ~ document) | json_encode() }},
95
96
{% if json is defined %}
97
  "description": {{ json.getDescription()|json_encode() }},
98
{% else %}
99
  "description": "@todo replace me",
100
{% endif %}
101
102
  "x-versioning": {{ isVersioning|json_encode() }},
103
104
{% if noIdField is not defined %}
105
  "x-id-in-post-allowed": false,
106
{% else %}
107
  "x-id-in-post-allowed": true,
108
{% endif %}
109
110
{% if json is defined %}
111
    "title": "{{ json.getTitle() }}",
112
{% endif %}
113
114
  "properties": {
115
{% set requiredFields = [] %}
116
{% set searchableFields = [] %}
117
{% set readOnlyFields = [] %}
118
119
{% if idField is defined %}
120
      {% if idField.required is defined and idField.required == true %}
121
      {% set requiredFields = requiredFields|merge(['id']) %}
122
      {% endif %}
123
{% endif %}
124
125
126
127
{% for field in fields %}
128
    "{{ field.fieldName }}": {
129
        "title": {{ field.title|json_encode() }},
130
131
{% if field.collection is defined and field.type == 'extref' %}
132
      "collection": {{ field.collection|json_encode() }},
133
{% endif %}
134
135
{% if field.readOnly is defined and field.readOnly == true %}
136
      "readOnly": {{ field.readOnly|json_encode() }},
137
{% endif %}
138
139
{% if field.recordOriginException is defined and field.recordOriginException == true %}
140
      "recordOriginException": {{ field.recordOriginException|json_encode() }},
141
{% endif %}
142
143
{% if field.xDynamicKey is defined and field.xDynamicKey != null %}
144
      "x-dynamic-key": {
145
          "document-id": "{{ field.xDynamicKey.documentId }}",
146
          "repository-method": "{{ field.xDynamicKey.repositoryMethod }}",
147
          "ref-field": "{{ field.xDynamicKey.refField }}"
148
      },
149
{% endif %}
150
151
{% if field.constraints is defined and field.constraints != null %}
152
      "x-constraints": {{ field.constraints|json_encode() }},
153
{% endif %}
154
155
{% if field.description is defined and field.description != '' %}
156
      "description": {{ field.description|json_encode() }}
157
{% else %}
158
      "description": "@todo replace me"
159
{% endif %}
160
161
{% if field.required is defined and field.required == true %}
162
    {% set requiredFields = requiredFields|merge([field.fieldName]) %}
163
{% endif %}
164
165
{% if field.searchable is defined and field.searchable > 0 %}
166
    {% set searchableFields = searchableFields|merge([field.fieldName]) %}
167
{% endif %}
168
169
{% if field.readOnly is defined and field.readOnly == true %}
170
    {% set readOnlyFields = readOnlyFields|merge([field.fieldName]) %}
171
{% endif %}
172
173
    },
174
{% endfor %}
175
176
177
178
    "id": {
179
      "title": "ID",
180
      "description": "Unique identifier"
181
{% if isrecordOriginFlagSet %}
182
    },
183
    "recordOrigin": {
184
      "title": "record origin",
185
      "description": "A small string like 'core' to determine the record origin. Documents from some sources must not be modified. The 'core' value is defined as readonly by default."
186
{% endif %}
187
    }
188
  },
189
190
{#
191
the whole recordOrigin thing is kinda messed up as you need 2 vars to correctly detect what should be done.
192
for schema, we condense it so recordOriginModifiable holds the whole truth in one..
193
 #}
194
{% if (recordOriginModifiable is defined and recordOriginModifiable == "false") and
195
  (isrecordOriginFlagSet is defined and isrecordOriginFlagSet == true) %}
196
  "recordOriginModifiable": false,
197
{% else %}
198
  "recordOriginModifiable": true,
199
{% endif %}
200
  "required": {{ requiredFields|json_encode() }},
201
  "searchable": {{ searchableFields|json_encode() }},
202
  "readOnlyFields": {{ readOnlyFields|json_encode() }}
203
}
204
205
206
     *
207
     *
208
     *
209
     *
210
     */
211
}