Completed
Push — master ( 9449ab...150499 )
by Nicolaas
02:14
created

GoogleMapDataResponse::updatemexml()   C

Complexity

Conditions 18
Paths 11

Size

Total Lines 56
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 56
c 0
b 0
f 0
rs 6.5661
cc 18
eloc 45
nc 11
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
/**
4
 * The way the map works is that you open a page, which loads the initial page
5
 * with the map points being loaded as a separate XML doc.
6
 *
7
 * This controller returns the Google Map data XML sheet
8
 * You can show one point by adding ?i=123
9
 * Where 123 is the ID of a GoogleMapLocationsObject
10
 *
11
 * Here are other return options for the Map .... *
12
 *
13
 * 'index' / 'showemptymap' => map without anything on it, fallback
14
 *
15
 * 'showpagepointsmapxml' => show points from the current page
16
 *
17
 * 'showchildpointsmapxml' => show points from the child pages (all child pages)
18
 *
19
 * 'showdirectchildren' => show points from the child pages (direct ones only)
20
 *
21
 * 'showsearchpoint' =>
22
 *
23
 * 'showcustompagesmapxml' => these are sitetree elements loaded by session
24
 *
25
 * 'showcustomdosmapxml' =>
26
 *
27
 * 'showdataobjects' =>
28
 *
29
 * 'updatemexml' =>
30
 *
31
 * 'showaroundmexml' =>
32
 *
33
 * 'showpointbyid' => can also be more than one ID
34
 *
35
 */
36
37
class GoogleMapDataResponse extends Controller
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...
38
{
39
    private static $session_var_prefix = "addCustomGoogleMap";
0 ignored issues
show
Unused Code introduced by
The property $session_var_prefix 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...
40
41
    /**
42
     * Default URL handlers - (Action)/(ID)/(OtherID)
43
     */
44
    private static $url_handlers = array(
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 $url_handlers 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...
45
        '/$Action//$OwnerID/$Title/$Longitude/$Latitude/$FilterCode/$SecondFilterCode' => 'handleAction',
46
    );
47
48
49
50
51
52
    #################
53
    # SESSION MANAGEMENT
54
    #################
55
56
    protected static function session_var_name($filterCode = "")
57
    {
58
        return Config::inst()->get("GoogleMapDataResponse", "session_var_prefix")."_".$filterCode;
59
    }
60
61
    /**
62
     * @param Array $addCustomGoogleMapArrayNEW
63
     * @param string $filterCode
64
     *
65
     */
66
    public static function add_custom_google_map_session_data($addCustomGoogleMapArrayNEW, $filterCode = "")
67
    {
68
        $addCustomGoogleMapArrayOLD = Session::get(self::session_var_name($filterCode));
69
        $addCustomGoogleMapArrayNEW = array_merge($addCustomGoogleMapArrayOLD, $addCustomGoogleMapArrayNEW);
70
        Session::set(Session::get(self::session_var_name($filterCode), serialize($addCustomGoogleMapArrayNEW)));
0 ignored issues
show
Unused Code introduced by
The call to Session::get() has too many arguments starting with serialize($addCustomGoogleMapArrayNEW).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
Bug introduced by
The call to set() misses a required argument $val.

This check looks for function calls that miss required arguments.

Loading history...
71
    }
72
73
    /**
74
     *
75
     *
76
     * @param Array $addCustomGoogleMapArray
77
     * @param string $filterCode
78
     *
79
     */
80
    public static function set_custom_google_map_session_data($addCustomGoogleMapArray, $filterCode = "")
81
    {
82
        if (!is_array($addCustomGoogleMapArray)) {
83
            user_error("addCustomGoogleMapArray should be an array!");
84
        }
85
        Session::set(self::session_var_name($filterCode), serialize($addCustomGoogleMapArray));
86
    }
87
88
    /**
89
     * @param string $filterCode
90
     *
91
     * @return Array
92
     */
93
    public static function get_custom_google_map_session_data($filterCode = "")
94
    {
95
        $data = Session::get(self::session_var_name($filterCode));
96
        if (is_array($data)) {
97
            $addCustomGoogleMapArray = $data;
98
        } else {
99
            try {
100
                $addCustomGoogleMapArray = unserialize($data);
101
            } catch (Exception $e) {
102
                $addCustomGoogleMapArray = array();
103
            }
104
        }
105
        return $addCustomGoogleMapArray;
106
    }
107
108
    /**
109
     *
110
     * @param string $filterCode
111
     */
112
    public static function clear_custom_google_map_session_data($filterCode = "")
113
    {
114
        Session::clear(self::session_var_name($filterCode));
115
    }
116
117
118
119
120
121
122
123
    #################
124
    # BASICS
125
    #################
126
    /**
127
     * @inherited
128
     */
129
    private static $allowed_actions = array(
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...
130
        'showemptymap' => true,
131
        'showpagepointsmapxml' => true,
132
        'showchildpointsmapxml' => true,
133
        'showdirectchildren' => true,
134
        'showsearchpoint' => true,
135
        'showcustompagesmapxml' => true,
136
        'showcustomdosmapxml' => true,
137
        'showdataobjects' => true,
138
        'updatemexml' => 'ADMIN',
139
        'showaroundmexml' => true,
140
        'showpointbyid' => true
141
    );
142
143
    /**
144
     * @var Array
145
     */
146
    private static $actions_without_owner = array(
147
        'showemptymap'
148
    );
149
150
    /**
151
     * The Page that is displaying the
152
     * @var SiteTree
153
     */
154
    protected $owner = null;
155
156
    /**
157
     * @var Float
158
     */
159
    protected $lng = 0;
160
161
    /**
162
     * @var Float
163
     */
164
    protected $lat = 0;
165
166
    /**
167
     * @var String
168
     */
169
    protected $title = "";
170
171
    /**
172
     * @var String
173
     */
174
    protected $filterCode = "";
175
176
    /**
177
     * @var String
178
     */
179
    protected $secondFilterCode = "";
180
181
    /**
182
     * @var GoogleMap
183
     */
184
    protected $map = null;
185
186
187
188
189
190
191
192
193
194
195
196
    #################
197
    # SET AND GET VARIABLES
198
    #################
199
200
    public function init()
0 ignored issues
show
Coding Style introduced by
init uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
201
    {
202
        parent::init();
203
        $id = 0;
204
        if ($this->request->param("OwnerID")) {
205
            $id = intval($this->request->param("OwnerID"));
206
        } elseif (isset($_GET["i"])) {
207
            $i = intval($_GET["i"]);
208
            $point = GoogleMapLocationsObject::get()->byID($i);
209
            if (!$point) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
210
                //New POINT
211
            } else {
212
                $id = $point->ParentID;
213
            }
214
        }
215
        if ($id) {
216
            $this->owner = SiteTree::get()->byID($id);
0 ignored issues
show
Documentation Bug introduced by
It seems like \SiteTree::get()->byID($id) can also be of type object<DataObject>. However, the property $owner is declared as type object<SiteTree>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
217
        }
218
        //HACK
219
        elseif (!$this->owner) {
220
            $this->owner = DataObject::get_one(
221
                'SiteTree',
222
                array("Title" => Convert::raw2sql($this->request->param("Title")))
223
            );
224
        }
225
        if ($this->owner || in_array($this->request->param("Action"), self::$actions_without_owner)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
226
            //all ok
227
        } elseif (in_array($this->request->param("Action"), self::$actions_without_owner)) {
228
            //ok too
229
            $this->owner = DataObject::get_one('SiteTree');
230
        } else {
231
            user_error("no owner has been identified for GoogleMapDataResponse", E_USER_NOTICE);
232
        }
233
        //END HACK
234
        $this->title = urldecode($this->request->param("Title"));
235
        $this->lng = floatval($this->request->param("Longitude"));
236
        $this->lat = floatval($this->request->param("Latitude"));
237
        $this->filterCode = urldecode($this->request->param("FilterCode"));
238
        $this->secondFilterCode = urldecode($this->request->param("SecondFilterCode"));
239
        if (!$this->title && $this->owner) {
240
            $this->title = $this->owner->Title;
241
        }
242
    }
243
244
    /**
245
     * @param object $owner
246
     */
247
    public function setOwner($owner)
248
    {
249
        $this->owner = $owner;
250
    }
251
252
    /**
253
     * @param String $title
254
     */
255
    public function setTitle($title)
256
    {
257
        $this->title = $title;
258
    }
259
260
    /**
261
     * @param float $lng
262
     */
263
    public function setLng($lng)
264
    {
265
        $this->lng = $lng;
266
    }
267
268
    /**
269
     * @param Float $lat
270
     */
271
    public function setLat($lat)
272
    {
273
        $this->lat = $lat;
274
    }
275
276
    /**
277
     * @param string $filterCode
278
     */
279
    public function setFilterCode($filterCode)
280
    {
281
        $this->filterCode = $filterCode;
282
    }
283
284
285
286
287
288
289
290
291
292
293
294
    #################
295
    # ACTIONS
296
    #################
297
298
    /**
299
     * @param SS_HTTPRequest
300
     *
301
     * @return String (XML)
302
     */
303
    public function index($request)
304
    {
305
        return $this->showemptymap($request);
306
    }
307
308
    /**
309
     * @param SS_HTTPRequest
310
     *
311
     * @return String (XML)
312
     */
313
    public function showemptymap($request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
314
    {
315
        return $this->makeXMLData(null, null, $this->title, $this->title." "._t("GoogleMap.MAP", "map"));
316
    }
317
318
    /**
319
     * @param SS_HTTPRequest
320
     *
321
     * @return String (XML)
322
     */
323 View Code Duplication
    public function showpagepointsmapxml($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...
324
    {
325
        $data = GoogleMapLocationsObject::get()->filter(array("ParentID" => $this->owner->ID));
326
        if ($data->count()) {
327
            return $this->makeXMLData(null, $data, $this->title, $this->title." "._t("GoogleMap.MAP", "map"));
328
        }
329
        return $this->showemptymap($request);
330
    }
331
332
    /**
333
     * @param SS_HTTPRequest
334
     *
335
     * @return String (XML)
336
     */
337 View Code Duplication
    public function showchildpointsmapxml($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...
338
    {
339
        if ($children = $this->owner->getChildrenOfType($this->owner, null)) {
340
            return $this->makeXMLData($children, null, $this->title, $this->title." "._t("GoogleMap.MAP", "map"));
341
        }
342
        return $this->showemptymap($request);
343
    }
344
345
    /**
346
     * @param SS_HTTPRequest
347
     *
348
     * @return String (XML)
349
     */
350
    public function showdirectchildren($request)
351
    {
352
        if ($children = Provider::get()) {
353
            return $this->makeXMLData($children, null, $this->title, $this->title." "._t("GoogleMap.MAP", "map"));
354
        }
355
        return $this->showemptymap($request);
356
    }
357
358
    /**
359
     * @param SS_HTTPRequest
360
     *
361
     * @return String (XML)
0 ignored issues
show
Documentation introduced by
Should the return type not be null|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
362
     */
363
    public function showsearchpoint($request)
364
    {
365
        if ($this->lat && $this->lng) {
366
            $point = GoogleMapLocationsObject::create();
367
            $point->ParentID = $this->owner->ID;
0 ignored issues
show
Documentation introduced by
The property ParentID does not exist on object<GoogleMapLocationsObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
368
            $point->Latitude = $this->lat;
0 ignored issues
show
Documentation introduced by
The property Latitude does not exist on object<GoogleMapLocationsObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
369
            $point->Longitude = $this->lng;
0 ignored issues
show
Documentation introduced by
The property Longitude does not exist on object<GoogleMapLocationsObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
370
            $point->CustomPopUpWindowTitle = $this->title;
0 ignored issues
show
Documentation introduced by
The property CustomPopUpWindowTitle does not exist on object<GoogleMapLocationsObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
371
            if ($this->address) {
0 ignored issues
show
Documentation introduced by
The property address does not exist on object<GoogleMapDataResponse>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
372
                die("get address to do");
0 ignored issues
show
Coding Style Compatibility introduced by
The method showsearchpoint() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
373
                $point->CustomPopUpWindowInfo = $this->address;
0 ignored issues
show
Unused Code introduced by
$point->CustomPopUpWindowInfo = $this->address; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
374
            }
375
            if ($point) {
376
                $data = new ArrayList();
377
                $data->push($point);
378
                return $this->makeXMLData(null, $data, $this->title, $this->title);
0 ignored issues
show
Documentation introduced by
$data is of type object<ArrayList>, but the function expects a object<DataList>|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
379
            }
380
        }
381
        return $this->showemptymap($request);
382
    }
383
384
    /**
385
     * @param SS_HTTPRequest
386
     *
387
     * @return String (XML)
388
     */
389
    public function showpointbyid($request)
390
    {
391
        $id = $request->param("FilterCode");
392
        $ids = explode(',', $id);
393
        foreach ($ids as $key => $id) {
394
            $ids[$key] = intval($id);
395
        }
396
        $className = Convert::raw2sql($request->param("SecondFilterCode"));
397
        $direct = false;
398
        if (! $className) {
399
            $direct = true;
400
        } elseif (! class_exists($className)) {
401
            $direct = true;
402
        }
403
        if ($direct) {
404
            $className = "GoogleMapLocationsObject";
405
        }
406
        $objects = $className::get()->filter(array("ID" => $ids));
407
        if ($direct) {
408
            return $this->makeXMLData(null, $objects, $this->title, $this->title);
409
        } else {
410
            return $this->makeXMLData($objects, null, $this->title, $this->title);
411
        }
412
    }
413
414
415
    /**
416
     * load data from session
417
     *
418
     * @param SS_HTTPRequest
419
     *
420
     * @return String (XML)
421
     */
422
    public function showcustompagesmapxml($request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
423
    {
424
        $addCustomGoogleMapArray = GoogleMapDataResponse::get_custom_google_map_session_data($this->filterCode);
425
        $pages = SiteTree::get()->filter(array("ID" => $addCustomGoogleMapArray));
426
        return $this->makeXMLData($pages, null, $this->title, $this->title);
427
    }
428
429
    /**
430
     * load a custom set of GoogleMapLocationsObjects
431
     *
432
     * @param SS_HTTPRequest
433
     *
434
     * @return String (XML)
435
     */
436
    public function showcustomdosmapxml($request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
437
    {
438
        $array = GoogleMapDataResponse::get_custom_google_map_session_data($this->filterCode);
439
        $googleMapLocationsObjects = GoogleMapLocationsObject::get()->filter(array("ID" => $array));
440
        return $this->makeXMLData(null, $googleMapLocationsObjects, $this->title, $this->title);
441
    }
442
443
    /**
444
     * Show what is around my points
445
     *
446
     * @param SS_HTTPRequest
447
     *
448
     * @return String (XML)
449
     */
450
    public function showaroundmexml($request)
451
    {
452
        $lng = 0;
453
        $lat = 0;
454
        $excludeIDList = array();
455
        $stage = '';
456
        if (Versioned::current_stage() == "Live") {
457
            $stage = "_Live";
458
        }
459
        if ($this->lng && $this->lat) {
460
            $lng = $this->lng;
461
            $lat = $this->lat;
462
        } elseif ($this->owner->ID) {
463
            //find the average!
464
            $objects = GoogleMapLocationsObject::get()->filter(array("ParentID" => $this->owner->ID));
465
            if ($count = $objects->count()) {
466
                foreach ($objects as $point) {
467
                    $lng += $point->Longitude;
468
                    $lat += $point->Latitude;
469
                }
470
                $lng = $lng / $count;
471
                $lat = $lat / $count;
472
            }
473
        }
474
        $classNameForParent = '';
475
        if ($otherClass = $this->filterCode) {
476
            $classNameForParent = $otherClass;
477
        }
478
        if ($this->title) {
479
            $title = $this->title;
480
        } else {
481
            $title = _t("GoogleMap.CLOSES_TO_ME", "Closest to me");
482
        }
483
        if ($lng && $lat) {
484
            $orderByRadius = GoogleMapLocationsObject::radius_definition($lng, $lat);
485
            $where = "(".$orderByRadius.") > 0 AND \"GoogleMapLocationsObject\".\"Latitude\" <> 0 AND \"GoogleMapLocationsObject\".\"Longitude\" <> 0";
486
            if ($classNameForParent && !is_object($classNameForParent)) {
487
                $where .= " AND \"SiteTree".$stage."\".\"ClassName\" = '".$classNameForParent."'";
488
            }
489
            if (count($excludeIDList)) {
490
                $where .= " AND \"GoogleMapLocationsObject\".\"ID\" NOT IN (".implode(",", $excludeIDList).") ";
491
            }
492
            $objects = GoogleMapLocationsObject::get()
493
                ->where($where)
494
                ->sort($orderByRadius)
495
                ->leftJoin("SiteTree".$stage."", "SiteTree".$stage.".ID = GoogleMapLocationsObject.ParentID")
496
                ->limit(Config::inst()->get("GoogleMap", "number_shown_in_around_me"));
497
            if ($objects->count()) {
498
                return $this->makeXMLData(
499
                    null,
500
                    $objects,
501
                    $title,
502
                    Config::inst()->get("GoogleMap", "number_shown_in_around_me") . " "._t("GoogleMap.CLOSEST_POINTS", "closest points")
503
                );
504
            }
505
        }
506
        return $this->showemptymap($request);
507
    }
508
509
    /**
510
     * URL must contain for GET variables
511
     * i - ID of owner
512
     * a - action
513
     * x - lng
514
     * y - lat
515
     *
516
     * actions are:
517
     *   - add
518
     *   - move
519
     *   - remove
520
     *
521
     * @param SS_HTTPRequest
522
     *
523
     * @return String (message)
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
524
     */
525
    public function updatemexml($request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
updatemexml uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
526
    {
527
        //we use request here, because the data comes from javascript!
528
        if ($this->owner->canEdit()) {
529
            if (isset($_REQUEST["x"]) && isset($_REQUEST["y"]) && isset($_REQUEST["i"]) && isset($_REQUEST["a"])) {
530
                $lng = floatval($_REQUEST["x"]);
531
                $lat = floatval($_REQUEST["y"]);
532
                $id = intval($_REQUEST["i"]);
533
                $action = $_REQUEST["a"];
534
                if ($lng && $lat) {
535
                    if (0 == $id && "add" == $action) {
536
                        $point = new GoogleMapLocationsObject;
537
                        $point->ParentID = $this->owner->ID;
0 ignored issues
show
Documentation introduced by
The property ParentID does not exist on object<GoogleMapLocationsObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
538
                        $point->Longitude = $lng;
0 ignored issues
show
Documentation introduced by
The property Longitude does not exist on object<GoogleMapLocationsObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
539
                        $point->Latitude = $lat;
0 ignored issues
show
Documentation introduced by
The property Latitude does not exist on object<GoogleMapLocationsObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
540
                        $point->write();
541
                        return $point->ID;
542
                    } elseif ($id > 0 && "move" == $action) {
543
                        $point = GoogleMapLocationsObject::get()->byID($id);
544
                        if ($point) {
545
                            if ($point->ParentID == $this->owner->ID) {
546
                                $point->Longitude = $lng;
547
                                $point->Latitude = $lat;
548
                                $point->Address = "";
549
                                $point->FullAddress = "";
550
                                $point->write();
551
                                return  _t("GoogleMap.LOCATION_UPDATED", "location updated");
552
                            } else {
553
                                return _t("GoogleMap.NO_PERMISSION_TO_UPDATE", "you dont have permission to update that location");
554
                            }
555
                        } else {
556
                            return _t("GoogleMap.COULD_NOT_FIND_LOCATION", "could not find location");
557
                        }
558
                    } elseif ($id && "remove" == $action) {
559
                        $point = GoogleMapLocationsObject::get()->byID($id);
560
                        if ($point) {
561
                            if ($point->ParentID == $this->owner->ID) {
562
                                $point->delete();
563
                                $point = null;
0 ignored issues
show
Unused Code introduced by
$point 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...
564
                                return _t("GoogleMap.LOCATION_DELETED", "location deleted");
565
                            } else {
566
                                return _t("GoogleMap.NO_DELETE_PERMISSION", "you dont have permission to delete that location");
567
                            }
568
                        } else {
569
                            return _t("GoogleMap.COULD_NOT_FIND_LOCATION", "could not find location.");
570
                        }
571
                    }
572
                } else {
573
                    return _t("GoogleMap.LOCATION_NOT_DEFINED", "point not defined.");
574
                }
575
            } else {
576
                return _t("GoogleMap.MISSING_VARIABLES", "not enough information was provided.");
577
            }
578
        }
579
        return  _t("GoogleMap.POINT_NOT_UPDATED", "You do not have permission to change the map.");
580
    }
581
582
583
584
585
586
587
588
    #################
589
    # TEMPLATE METHODS
590
    #################
591
    /**
592
     *
593
     * @return GoogleMap
594
     */
595
    public function GoogleMapController()
596
    {
597
        if (!$this->map) {
598
            user_error("No map has been created");
599
        }
600
        return $this->map;
601
    }
602
603
604
605
606
607
608
609
610
    #################
611
    # PRIVATE PARTY
612
    #################
613
614
    /**
615
     * @param DataList $pages
0 ignored issues
show
Documentation introduced by
Should the type for parameter $pages not be DataList|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
616
     * @param DataList $dataPoints
0 ignored issues
show
Documentation introduced by
Should the type for parameter $dataPoints not be DataList|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
617
     * @param string $title
618
     * @param string $selectionStatement
619
     *
620
     * @return String (XML)
621
     */
622
    protected function makeXMLData(
623
        $pages = null,
624
        $dataPoints = null,
625
        $title = '',
626
        $selectionStatement = ''
0 ignored issues
show
Unused Code introduced by
The parameter $selectionStatement is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
627
    ) {
628
        $this->response->addHeader("Content-Type", "text/xml; charset=\"utf-8\"");
629
        return self::xml_sheet(
630
            $pages,
631
            $dataPoints,
632
            $title,
633
            $selectionStatement = ''
634
        );
635
    }
636
637
638
639
    ################################
640
    # STATIC METHODS
641
    ################################
642
643
    public static function xml_sheet(
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
644
        $pages = null,
645
        $dataPoints = null,
646
        $title = '',
647
        $selectionStatement = ''
648
    ) {
649
        $map = Injector::inst()->get("GoogleMap");
650
        $map->setTitleOfMap($title);
651
        $map->setWhereStatementDescription($selectionStatement ? $selectionStatement : $title);
652
        if ($pages) {
653
            $map->setPageDataObjectSet($pages);
654
        } elseif ($dataPoints) {
655
            $map->setPoints($dataPoints);
656
        }
657
        $map->createDataPoints();
658
        return $map->renderWith("GoogleMapXml");
659
    }
660
661
662
663
    /**
664
     * var arrayOfLatitudeAndLongitude: Array (Latitude" => 123, "Longitude" => 123, "Marker" => "red1");
665
     * Marker is optional
666
     * @param Array arrayOfLatitudeAndLongitude
667
     * @param String title
668
     *
669
     * @return String (HTML - img tag)
670
     */
671
672
    public static function quick_static_map($arrayOfLatitudeAndLongitude, $title)
673
    {
674
        $staticMapURL = '';
0 ignored issues
show
Unused Code introduced by
$staticMapURL 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...
675
        $count = 0;
676
        //width
677
        $staticMapWidth = Config::inst()->get("GoogleMap", "google_map_width");
678
        if ($staticMapWidth > 512) {
679
            $staticMapWidth = 512;
680
        }
681
        //height
682
        $staticMapHeight = Config::inst()->get("GoogleMap", "google_map_height");
683
        if ($staticMapHeight > 512) {
684
            $staticMapHeight = 512;
685
        }
686
        $staticMapURL = "size=".$staticMapWidth."x".$staticMapHeight;
687
        if (count($arrayOfLatitudeAndLongitude)) {
688
            //http://maps.google.com/maps/api/staticmap?sensor=true&maptype=map&size=209x310&
689
            //markers=color:green%7Clabel:A%7C-45.0302,168.663
690
            //&markers=color:red%7Clabel:Q%7C-36.8667,174.767
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
691
            foreach ($arrayOfLatitudeAndLongitude as $row) {
692
                $staticMapURL .= '&amp;markers=color:'.$row["Colour"].'%7Clabel:'.$row["Label"].'%7C';
693
                $staticMapURL .= round($row["Latitude"], 6).",".round($row["Longitude"], 6);
694
                $count++;
695
            }
696
            if ($count == 1) {
697
                $staticMapURL .= '&amp;center='.$defaultCenter.'&amp;zoom='. Config::inst()->get("GoogleMap", "default_zoom");
0 ignored issues
show
Bug introduced by
The variable $defaultCenter does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
698
            }
699
        }
700
        return self::make_static_map_url_into_image($staticMapURL, $title);
701
    }
702
703
    /**
704
     * @param String $staticMapURL
705
     * @param String $title
706
     *
707
     * @return String (HTML - img tag)
708
     */
709
    protected static function make_static_map_url_into_image($staticMapURL, $title)
710
    {
711
        $fullStaticMapURL =
712
            'http://maps.google.com/maps/api/staticmap?'
713
                .Config::inst()->get("GoogleMap", "static_map_settings").'&amp;'
714
                .$staticMapURL.'&amp;'
715
                .'key='.Config::inst()->get("GoogleMap", "google_map_api_key");
716
        if (Config::inst()->get("GoogleMap", "save_static_map_locally")) {
717
            $fileName = str_replace(array('&', '|', ',', '=', ';'), array('', '', '', '', ''), $staticMapURL);
718
            $length = strlen($fileName);
719
            $fileName = "_sGMap".substr(hash("md5", $fileName), 0, 35)."_".$length.".gif";
720
            $fullStaticMapURL = StaticMapSaverForHTTPS::convert_to_local_file(str_replace('&amp;', '&', $fullStaticMapURL), $fileName);
721
        }
722
        return '<img class="staticGoogleMap" src="'.$fullStaticMapURL.'" alt="map: '.Convert::raw2att($title).'" />';
723
    }
724
}
725