ModuleFileConverter::addJsonToModuleFile()   D
last analyzed

Complexity

Conditions 23
Paths 64

Size

Total Lines 84
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 48
CRAP Score 23.0044

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 84
ccs 48
cts 49
cp 0.9796
rs 4.8107
cc 23
eloc 52
nc 64
nop 2
crap 23.0044

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
/*
4
 * This file is part of the puli/manager package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\Manager\Module;
13
14
use Puli\Discovery\Api\Type\BindingParameter;
15
use Puli\Discovery\Api\Type\BindingType;
16
use Puli\Discovery\Binding\ClassBinding;
17
use Puli\Discovery\Binding\ResourceBinding;
18
use Puli\Manager\Api\Discovery\BindingDescriptor;
19
use Puli\Manager\Api\Discovery\BindingTypeDescriptor;
20
use Puli\Manager\Api\Module\ModuleFile;
21
use Puli\Manager\Api\Repository\PathMapping;
22
use Puli\Manager\Assert\Assert;
23
use Rhumsaa\Uuid\Uuid;
24
use stdClass;
25
use Webmozart\Json\Conversion\JsonConverter;
26
use Webmozart\Json\Versioning\JsonVersioner;
27
28
/**
29
 * Converts module files to JSON and back.
30
 *
31
 * @since  1.0
32
 *
33
 * @author Bernhard Schussek <[email protected]>
34
 */
35
class ModuleFileConverter implements JsonConverter
36
{
37
    /**
38
     * The version of the schema.
39
     */
40
    const VERSION = '2.0';
41
42
    /**
43
     * The URI of the schema of this converter.
44
     */
45
    const SCHEMA = 'http://puli.io/schema/%s/manager/module';
46
47
    /**
48
     * The default order of the keys in the written module file.
49
     *
50
     * @var string[]
51
     */
52
    private static $keyOrder = array(
53
        '$schema',
54
        'name',
55
        'resources',
56
        'bindings',
57
        'binding-types',
58
        'depend',
59
        'extra',
60
    );
61
62
    /**
63
     * @var JsonVersioner
64
     */
65
    protected $versioner;
66
67 3
    public static function compareBindingDescriptors(BindingDescriptor $a, BindingDescriptor $b)
68
    {
69
        // Make sure that bindings are always printed in the same order
70 3
        return strcmp($a->getUuid()->toString(), $b->getUuid()->toString());
71
    }
72
73
    /**
74
     * Creates a new converter.
75
     *
76
     * @param JsonVersioner $versioner The JSON versioner.
77
     */
78 58
    public function __construct(JsonVersioner $versioner)
79
    {
80 58
        $this->versioner = $versioner;
81 58
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 14
    public function toJson($moduleFile, array $options = array())
87
    {
88 14
        Assert::isInstanceOf($moduleFile, 'Puli\Manager\Api\Module\ModuleFile');
89
90 14
        $jsonData = new stdClass();
91 14
        $jsonData->{'$schema'} = sprintf(self::SCHEMA, self::VERSION);
92
93 14
        $this->addModuleFileToJson($moduleFile, $jsonData);
94
95
        // Sort according to key order
96 14
        $jsonArray = (array) $jsonData;
97 14
        $orderedKeys = array_intersect_key(array_flip(self::$keyOrder), $jsonArray);
98 14
        $jsonData = (object) array_replace($orderedKeys, $jsonArray);
99
100 14
        return $jsonData;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106 22
    public function fromJson($jsonData, array $options = array())
107
    {
108 22
        Assert::isInstanceOf($jsonData, 'stdClass');
109
110 22
        $moduleFile = new ModuleFile(null, isset($options['path']) ? $options['path'] : null);
111 22
        $moduleFile->setVersion($this->versioner->parseVersion($jsonData));
112
113 22
        $this->addJsonToModuleFile($jsonData, $moduleFile);
114
115 22
        return $moduleFile;
116
    }
117
118 20
    protected function addModuleFileToJson(ModuleFile $moduleFile, stdClass $jsonData)
119
    {
120 20
        $mappings = $moduleFile->getPathMappings();
121 20
        $bindingDescriptors = $moduleFile->getBindingDescriptors();
122 20
        $typeDescriptors = $moduleFile->getTypeDescriptors();
123 20
        $dependencies = $moduleFile->getDependencies();
124 20
        $extra = $moduleFile->getExtraKeys();
125
126 20
        if (null !== $moduleFile->getModuleName()) {
127 2
            $jsonData->name = $moduleFile->getModuleName();
128
        }
129
130 20
        if (count($mappings) > 0) {
131 4
            $jsonData->resources = new stdClass();
132
133 4
            foreach ($mappings as $mapping) {
134 4
                $puliPath = $mapping->getRepositoryPath();
135 4
                $localPaths = $mapping->getPathReferences();
136
137 4
                $jsonData->resources->$puliPath = count($localPaths) > 1 ? $localPaths : reset($localPaths);
138
            }
139
        }
140
141 20
        if (count($bindingDescriptors) > 0) {
142 6
            uasort($bindingDescriptors, array(__CLASS__, 'compareBindingDescriptors'));
143
144 6
            $jsonData->bindings = new stdClass();
145
146 6
            foreach ($bindingDescriptors as $bindingDescriptor) {
147 6
                $binding = $bindingDescriptor->getBinding();
148 6
                $bindingData = new stdClass();
149 6
                $bindingData->_class = get_class($binding);
150
151
                // This needs to be moved to external classes to allow adding
152
                // custom binding classes at some point
153 6
                if ($binding instanceof ResourceBinding) {
154 6
                    $bindingData->query = $binding->getQuery();
155
156 6
                    if ('glob' !== $binding->getLanguage()) {
157 6
                        $bindingData->language = $binding->getLanguage();
158
                    }
159
                } elseif ($binding instanceof ClassBinding) {
160 3
                    $bindingData->class = $binding->getClassName();
161
                }
162
163 6
                $bindingData->type = $bindingDescriptor->getTypeName();
164
165
                // Don't include the default values of the binding type
166 6
                if ($binding->hasParameterValues(false)) {
167 1
                    $parameterData = $binding->getParameterValues(false);
168 1
                    ksort($parameterData);
169 1
                    $bindingData->parameters = (object) $parameterData;
170
                }
171
172 6
                $jsonData->bindings->{$bindingDescriptor->getUuid()->toString()} = $bindingData;
173
            }
174
        }
175
176 20
        if (count($typeDescriptors) > 0) {
177 8
            $bindingTypesData = array();
178
179 8
            foreach ($typeDescriptors as $typeDescriptor) {
180 8
                $type = $typeDescriptor->getType();
181 8
                $typeData = new stdClass();
182
183 8
                if ($typeDescriptor->getDescription()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $typeDescriptor->getDescription() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
184 2
                    $typeData->description = $typeDescriptor->getDescription();
185
                }
186
187 8
                if ($type->hasParameters()) {
188 6
                    $parametersData = array();
189
190 6
                    foreach ($type->getParameters() as $parameter) {
191 6
                        $parameterData = new stdClass();
192
193 6
                        if ($typeDescriptor->hasParameterDescription($parameter->getName())) {
194 3
                            $parameterData->description = $typeDescriptor->getParameterDescription($parameter->getName());
195
                        }
196
197 6
                        if ($parameter->isRequired()) {
198 1
                            $parameterData->required = true;
199
                        }
200
201 6
                        if (null !== $parameter->getDefaultValue()) {
202 3
                            $parameterData->default = $parameter->getDefaultValue();
203
                        }
204
205 6
                        $parametersData[$parameter->getName()] = $parameterData;
206
                    }
207
208 6
                    ksort($parametersData);
209
210 6
                    $typeData->parameters = (object) $parametersData;
211
                }
212
213 8
                $bindingTypesData[$type->getName()] = $typeData;
214
            }
215
216 8
            ksort($bindingTypesData);
217
218 8
            $jsonData->{'binding-types'} = (object) $bindingTypesData;
219
        }
220
221 20
        if (count($dependencies) > 0) {
222 3
            $jsonData->depend = $dependencies;
223
        }
224
225 20
        if (count($extra) > 0) {
226 2
            $jsonData->extra = (object) $extra;
227
        }
228 20
    }
229
230 38
    protected function addJsonToModuleFile(stdClass $jsonData, ModuleFile $moduleFile)
231
    {
232 38
        if (isset($jsonData->name)) {
233 28
            $moduleFile->setModuleName($jsonData->name);
234
        }
235
236 38
        if (isset($jsonData->resources)) {
237 2
            foreach ($jsonData->resources as $path => $relativePaths) {
238 2
                $moduleFile->addPathMapping(new PathMapping($path, (array) $relativePaths));
239
            }
240
        }
241
242 38
        if (isset($jsonData->bindings)) {
243 6
            foreach ($jsonData->bindings as $uuid => $bindingData) {
244 6
                $binding = null;
0 ignored issues
show
Unused Code introduced by
$binding is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
245 6
                $class = isset($bindingData->_class)
246 4
                    ? $bindingData->_class
247 6
                    : 'Puli\Discovery\Binding\ResourceBinding';
248
249
                // Move this code to external classes to allow use of custom
250
                // bindings
251
                switch ($class) {
252 6
                    case 'Puli\Discovery\Binding\ClassBinding':
253 3
                        $binding = new ClassBinding(
254 3
                            $bindingData->class,
255 3
                            $bindingData->type,
256 3
                            isset($bindingData->parameters) ? (array) $bindingData->parameters : array(),
257 3
                            Uuid::fromString($uuid)
258
                        );
259 3
                        break;
260 5
                    case 'Puli\Discovery\Binding\ResourceBinding':
261 5
                        $binding = new ResourceBinding(
262 5
                            $bindingData->query,
263 5
                            $bindingData->type,
264 5
                            isset($bindingData->parameters) ? (array) $bindingData->parameters : array(),
265 5
                            isset($bindingData->language) ? $bindingData->language : 'glob',
266 5
                            Uuid::fromString($uuid)
267
                        );
268 5
                        break;
269
                    default:
270
                        continue 2;
271
                }
272
273 6
                $moduleFile->addBindingDescriptor(new BindingDescriptor($binding));
274
            }
275
        }
276
277 38
        if (isset($jsonData->{'binding-types'})) {
278 3
            foreach ((array) $jsonData->{'binding-types'} as $typeName => $data) {
279 3
                $parameters = array();
280 3
                $parameterDescriptions = array();
281
282 3
                if (isset($data->parameters)) {
283 3
                    foreach ((array) $data->parameters as $parameterName => $parameterData) {
284 3
                        $required = isset($parameterData->required) ? $parameterData->required : false;
285
286 3
                        $parameters[] = new BindingParameter(
287
                            $parameterName,
288 3
                            $required ? BindingParameter::REQUIRED : BindingParameter::OPTIONAL,
289 3
                            isset($parameterData->default) ? $parameterData->default : null
290
                        );
291
292 3
                        if (isset($parameterData->description)) {
293 3
                            $parameterDescriptions[$parameterName] = $parameterData->description;
294
                        }
295
                    }
296
                }
297
298 3
                $moduleFile->addTypeDescriptor(new BindingTypeDescriptor(
299 3
                    new BindingType($typeName, $parameters),
300 3
                    isset($data->description) ? $data->description : null,
301
                    $parameterDescriptions
302
                ));
303
            }
304
        }
305
306 38
        if (isset($jsonData->depend)) {
307 2
            $moduleFile->setDependencies($jsonData->depend);
308
        }
309
310 38
        if (isset($jsonData->extra)) {
311 2
            $moduleFile->setExtraKeys((array) $jsonData->extra);
312
        }
313 38
    }
314
}
315