GoogleMapField   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 262
Duplicated Lines 8.4 %

Coupling/Cohesion

Components 3
Dependencies 8

Importance

Changes 0
Metric Value
wmc 33
lcom 3
cbo 8
dl 22
loc 262
rs 9.3999
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 2
A getApi() 0 3 1
A setApi() 0 3 1
A setOptions() 0 22 3
A getTranslations() 0 11 1
A getOptions() 0 5 1
A array_keys_to_objects() 5 9 3
A setMarkers() 0 3 1
B getMarkers() 0 17 7
A deleteMarkers() 0 8 4
B updateMarkers() 0 26 5
A zoomChanged() 9 9 2
A coordinatesChanged() 8 8 2

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
/**
4
 * @author    Donatas Navidonskis <[email protected]>
5
 * @since     2017
6
 * @class     GoogleMapField
7
 *
8
 */
9
class GoogleMapField extends \FormField {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
10
11
    /**
12
     * @var array
13
     * @config
14
     */
15
    private static $allowed_actions = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $allowed_actions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
16
        'updateMarkers',
17
        'deleteMarkers',
18
        'zoomChanged',
19
        'coordinatesChanged',
20
    ];
21
22
    /**
23
     * Google maps api key
24
     *
25
     * @var string
26
     * @config
27
     */
28
    private static $api = '';
0 ignored issues
show
Unused Code introduced by
The property $api is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
29
30
    /**
31
     * @var SS_List
32
     * @config
33
     */
34
    protected $markers = null;
35
36
    /**
37
     * @var array
38
     * @config
39
     */
40
    private static $options = [
0 ignored issues
show
Unused Code introduced by
The property $options is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
41
        'map' => [
42
            'center' => [
43
                'lat' => 55.1309504,
44
                'lng' => 24.5499231,
45
            ],
46
        ],
47
    ];
48
49
    /**
50
     * @var MapBlock
51
     */
52
    protected $block;
53
54
    /**
55
     * GoogleMapField constructor.
56
     *
57
     * @param string        $name
58
     * @param MapBlock      $block
59
     * @param \SS_List|null $markers
60
     * @param array         $options
61
     */
62
    public function __construct($name, MapBlock $block, \SS_List $markers = null, $options = []) {
63
        if (array_key_exists('api', $options)) {
64
            $this->setApi($options['api']);
65
            unset($options['api']);
66
        }
67
68
        $this->block = $block;
69
        $this->setMarkers($markers);
0 ignored issues
show
Bug introduced by
It seems like $markers defined by parameter $markers on line 62 can be null; however, GoogleMapField::setMarkers() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
70
        $this->setOptions($options);
71
72
        parent::__construct($name);
73
    }
74
75
    /**
76
     * @return string
77
     */
78
    public function getApi() {
79
        return static::config()->api;
80
    }
81
82
    /**
83
     * @param string $api
84
     *
85
     * @return void
86
     */
87
    public function setApi($api) {
88
        static::config()->api = $api;
89
    }
90
91
    /**
92
     * @param array $options
93
     *
94
     * @return void
95
     */
96
    public function setOptions($options = []) {
97
        if (array_key_exists('map', $options) && is_array($options['map'])) {
98
            $settings = static::config()->options;
99
            $settings['map'] = array_merge($settings['map'], $options['map']);
100
101
            static::config()->options = $settings;
102
            unset($options['map']);
103
        }
104
105
        static::config()->options = array_merge(
106
            static::config()->options,
107
            [
108
                'translations' => $this->getTranslations(),
109
                'sprite'       => \Controller::join_links(
110
                    \Director::absoluteBaseURL(),
111
                    CONTENT_BLOCKS_DIR,
112
                    '/assets/images/sprite.png'
113
                ),
114
            ],
115
            $options
116
        );
117
    }
118
119
    /**
120
     * @return array
121
     */
122
    public function getTranslations() {
123
        return [
124
            'close'       => _t('GoogleMapField.CLOSE', 'Close'),
125
            'address'     => _t('GoogleMapField.TYPE_AN_ADDRESS', 'Type an address'),
126
            'editMarker'  => _t('GoogleMapField.EDIT_MARKER', 'Edit marker'),
127
            'displayInfo' => _t('GoogleMapField.DISPLAY_INFO', 'Display content info window?'),
128
            'content'     => _t('GoogleMapField.CONTENT', 'Content'),
129
            'delete'      => _t('GoogleMapField.DELETE', 'Delete'),
130
            'save'        => _t('GoogleMapField.SAVE', 'Save'),
131
        ];
132
    }
133
134
    /**
135
     * @return string
136
     */
137
    public function getOptions() {
138
        return \Convert::raw2att(\Convert::array2json(
139
            static::array_keys_to_objects(static::config()->options)
0 ignored issues
show
Bug introduced by
Since array_keys_to_objects() is declared private, calling it with static will lead to errors in possible sub-classes. You can either use self, or increase the visibility of array_keys_to_objects() to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
}

public static function getSomeVariable()
{
    return static::getTemperature();
}

}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass {
      private static function getTemperature() {
        return "-182 °C";
    }
}

print YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class YourClass
{
    private static function getTemperature() {
        return "3422 °C";
    }

    public static function getSomeVariable()
    {
        return self::getTemperature();
    }
}
Loading history...
140
        ));
141
    }
142
143
    /**
144
     * @param array $data
145
     *
146
     * @return array
147
     */
148
    private static function array_keys_to_objects(array $data = []) {
149 View Code Duplication
        foreach ($data as $key => $value) {
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...
150
            if (is_array($value)) {
151
                $data[$key] = json_decode(json_encode((object) $value), false);
152
            }
153
        }
154
155
        return $data;
156
    }
157
158
    /**
159
     * @param SS_List $markers
160
     *
161
     * @return void
162
     */
163
    public function setMarkers(SS_List $markers) {
164
        $this->markers = $markers;
165
    }
166
167
    /**
168
     * @return bool|string
169
     */
170
    public function getMarkers() {
171
        if (count($markers = $this->markers->toNestedArray())) {
172
            $markers = array_map(function ($marker) {
173
                return [
174
                    'instanceId'    => isset($marker['InstanceId']) ? $marker['InstanceId'] : '',
175
                    'address'       => isset($marker['Address']) ? $marker['Address'] : '',
176
                    'coordinates'   => isset($marker['Coordinates']) ? $marker['Coordinates'] : '',
177
                    'content'       => isset($marker['Content']) ? $marker['Content'] : '',
178
                    'displayWindow' => (bool) (isset($marker['DisplayWindow']) ? $marker['DisplayWindow'] : false),
179
                ];
180
            }, $markers);
181
182
            return \Convert::raw2att(\Convert::array2json($markers));
183
        }
184
185
        return false;
186
    }
187
188
    /**
189
     * Action to delete markers. Should be triggered InstanceId of marker.
190
     *
191
     * @param \SS_HTTPRequest $request
192
     *
193
     * @return void
194
     */
195
    public function deleteMarkers(\SS_HTTPRequest $request) {
196
        $data = $request->getVars();
197
198
        if (isset($data['InstanceId']) && (($marker = $this->block->Markers()->filter('InstanceId', $data['InstanceId'])) && $marker->exists())) {
0 ignored issues
show
Bug introduced by
The method Markers() does not exist on MapBlock. Did you maybe mean getMarkersAsJson()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
199
            $marker = $marker->first();
200
            $marker->delete();
201
        }
202
    }
203
204
    /**
205
     * Action to update markers. Should be triggered InstanceId and other fields which has @see Marker has.
206
     *
207
     * @param \SS_HTTPRequest $request
208
     *
209
     * @return void
210
     */
211
    public function updateMarkers(\SS_HTTPRequest $request) {
212
        $data = $request->getVars();
213
214
        if (array_key_exists('InstanceId', $data)) {
215
            $marker = $this->block->Markers()->filter('InstanceId', $data['InstanceId']);
0 ignored issues
show
Bug introduced by
The method Markers() does not exist on MapBlock. Did you maybe mean getMarkersAsJson()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
216
217
            if ($marker->exists()) {
218
                $marker = $marker->first();
219
220
                foreach ($data as $field => $value) {
221
                    if ($marker->hasField($field)) {
222
                        $marker->setField($field, $value);
223
                    }
224
                }
225
226
                $marker->write();
227
            } else {
228
                $marker = Marker::create(array_merge($data, [
229
                    'BlockID' => $this->block->ID,
230
                ]));
231
                $marker->write();
232
233
                $this->block->Markers()->add($marker);
0 ignored issues
show
Bug introduced by
The method Markers() does not exist on MapBlock. Did you maybe mean getMarkersAsJson()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
234
            }
235
        }
236
    }
237
238
    /**
239
     * Action to update zoom in/out changes.
240
     *
241
     * @param \SS_HTTPRequest $request
242
     *
243
     * @return void
244
     */
245 View Code Duplication
    public function zoomChanged(\SS_HTTPRequest $request) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
246
        $data = $request->getVars();
247
248
        if (array_key_exists('zoom', $data)) {
249
            $zoomLevel = (int) $data['zoom'];
250
            $this->block->ZoomLevel = $zoomLevel;
251
            $this->block->write();
252
        }
253
    }
254
255
    /**
256
     * Action to update coordinates changes.
257
     *
258
     * @param \SS_HTTPRequest $request
259
     *
260
     * @return void
261
     */
262 View Code Duplication
    public function coordinatesChanged(\SS_HTTPRequest $request) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
263
        $data = $request->getVars();
264
265
        if (array_key_exists('coordinates', $data)) {
266
            $this->block->Coordinates = $data['coordinates'];
267
            $this->block->write();
268
        }
269
    }
270
}