AdvancedModelTransformer::transformJSON()   C
last analyzed

Complexity

Conditions 12
Paths 22

Size

Total Lines 64
Code Lines 29

Duplication

Lines 12
Ratio 18.75 %

Code Coverage

Tests 4
CRAP Score 104.2646

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 12
loc 64
ccs 4
cts 29
cp 0.1379
rs 6.0561
cc 12
eloc 29
nc 22
nop 2
crap 104.2646

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
namespace BZIon\Form\Transformer;
4
5
use Symfony\Component\Form\DataTransformerInterface;
6
use Symfony\Component\Form\Exception\TransformationFailedException;
7
8
abstract class AdvancedModelTransformer implements DataTransformerInterface
9
{
10
    /**
11
     * @var string[]
12
     */
13
    protected $types;
14
15
    /**
16
     * @param string[] $types The types of the models
17
     */
18 1
    public function __construct(array $types)
19
    {
20 1
        if (empty($types)) {
21
            throw new \Exception("No type has been specified");
22
        }
23
24 1
        $this->types = $types;
25 1
    }
26
27
    /**
28
     * Transforms an object (model) to the form representation
29
     *
30
     * @param  \Model|\Model[]|null $models
31
     * @return array
32
     */
33 1
    public function transform($models)
34
    {
35 1
        if ($models === null) {
36 1
            $models = array();
37 1
        } elseif (!is_array($models)) {
38
            $models = array($models);
39
        }
40
41 1
        $data = $json = array();
42 1
        foreach ($models as $model) {
43 1
            $data[$model->getType()][] = $model->getName();
44 1
            $json[] = array(
45 1
                'id'   => $model->getID(),
46 1
                'name' => $model->getName(),
47 1
                'type' => ucfirst($model->getType())
48
            );
49
        }
50
51 1
        foreach ($data as $type => &$value) {
52 1
            $value = implode(', ', $value);
53
        }
54
55 1
        $data['ids'] = json_encode(array(
56 1
            'data' => $json
57
        ));
58
59 1
        return $data;
60
    }
61
62
    /**
63
     * Get an invalid model of an acceptable type
64
     *
65
     * @param  string|null $type The type of the model, or null to select one of
66
     *                           the specified types
67
     * @return \Model
68
     */
69
    protected function invalidModel($type = null)
70
    {
71
        if ($type === null) {
72
            $type = reset($this->types); // Get the first value of $this->types
73
        }
74
75
        $type = ucfirst($type);
76
77
        return call_user_func(array($type, 'invalid'));
78
    }
79
80
    /**
81
     * Get a model from its name
82
     * @param  string     $name The name of the model
83
     * @param  string     $type The type of the model in lower case
84
     * @return \NamedModel|null  The model or null if no name was specified
85
     */
86 1
    protected function getModelFromName($name, $type)
87
    {
88 1
        if ($name === '') {
89
            return null;
90
        }
91
92 1
        if ($type === 'player') {
93 1
            return \Player::getFromUsername($name);
94
        } elseif ($type === 'team') {
95
            return \Team::getFromName($name);
96
        } else {
97
            throw new \InvalidArgumentException('Unsupported model type');
98
        }
99
    }
100
101
    /**
102
     * Transform JSON data provided by javascript to a list of Models
103
     *
104
     * @param  string $data The JSON provided to us by javascript, containing
105
     *                      a list of Model IDs and types
106
     * @param  array  $include An array of Models of each type that will be
107
     *                         included in the final result
108
     * @return bool|\Model[] A list of models, or false if the data was not
109
     *                         provided by javascript as JSON
110
     */
111 1
    protected function transformJSON(&$data, $include = array())
112
    {
113 1
        $json = json_decode($data['ids'], true);
114
115 1
        if (!isset($json['modified']) || $json['modified'] !== true) {
116
            // The JSON data was not modified; we can proceed to check input
117
            // from other sources
118 1
            return false;
119
        }
120
121
        // Array to store IDs for quick access so we can be sure that no
122
        // duplicates are saved
123
        $ids = array();
124
125
        $models = array();
126
127
        foreach ($include as $type => $includedModels) {
128
            foreach ($includedModels as $model) {
129
                $ids[$type][$model->getID()] = true; // Prevent duplication
130
                $models[] = $model;
131
            }
132
        }
133
134
        foreach ($json['data'] as $key => $object) {
135
            if ($key === 'modified') {
136
                // This is just an object that lets us know javascript provided
137
                // data, we should ignore it
138
                continue;
139
            }
140
141
            if (!isset($object['id']) || !isset($object['type'])) {
142
                throw new TransformationFailedException(
143
                    "Invalid model provided"
144
                );
145
            }
146
147
            $type = strtolower($object['type']);
148
149
            // Sanity check so that the user can't generate arbitrary classes
150
            if (!in_array($type, $this->types)) {
151
                throw new TransformationFailedException(
152
                    "Objects of type \"{$object['type']}\" are not supported"
153
                );
154
            }
155
156
            $class = ucfirst($object['type']);
157
            $model = $class::get($object['id']);
158
159 View Code Duplication
            if ($model->isDeleted()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
160
                // Show an error message if the model provided by javascript is
161
                // invalid - we don't let the validator handle this error, so
162
                // that the user doesn't see a vague warning
163
                throw new TransformationFailedException(
164
                    "Invalid model ID provided"
165
                );
166
            } elseif (!isset($ids[$type][$model->getID()])) {
167
                // The model passed the duplication check
168
                $models[] = $model;
169
                $ids[$type][$model->getID()] = true;
170
            }
171
        }
172
173
        return $models;
174
    }
175
}
176