Completed
Push — fm-matches ( f867e2...7fc64f )
by Vladimir
14:12
created

AdvancedModelTransformer   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 168
Duplicated Lines 7.14 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 43.75%

Importance

Changes 0
Metric Value
wmc 25
c 0
b 0
f 0
lcom 1
cbo 3
dl 12
loc 168
ccs 28
cts 64
cp 0.4375
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
B transform() 0 28 5
A invalidModel() 0 10 2
A getModelFromName() 0 14 4
C transformJSON() 12 64 12

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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[] $type     The types of the models
0 ignored issues
show
Bug introduced by
There is no parameter named $type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
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|null $model
0 ignored issues
show
Documentation introduced by
There is no parameter named $model. Did you maybe mean $models?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
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 $json The JSON provided to us by javascript, containing
0 ignored issues
show
Bug introduced by
There is no parameter named $json. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
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