Completed
Push — 2.0 ( 4f7a94...ecedba )
by Jason
11s
created

Locator_Controller::init()   C

Complexity

Conditions 8
Paths 34

Size

Total Lines 80
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 63.848

Importance

Changes 0
Metric Value
dl 0
loc 80
ccs 2
cts 45
cp 0.0444
rs 6.0132
c 0
b 0
f 0
cc 8
eloc 41
nc 34
nop 0
crap 63.848

How to fix   Long Method   

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
 * Class Locator
5
 *
6
 * @property bool $AutoGeocode
7
 * @property bool $ModalWindow
8
 * @property string $Unit
9
 * @method Categories|ManyManyList $Categories
10
 */
11
class Locator extends Page
12
{
13
14
    /**
15
     * @var array
16
     */
17
    private static $db = array(
18
        'Unit' => 'Enum("m,km","m")',
19
    );
20
21
    /**
22
     * @var array
23
     */
24
    private static $many_many = array(
25
        'Categories' => 'LocationCategory',
26
    );
27
28
    /**
29
     * @var string
30
     */
31
    private static $singular_name = 'Locator';
32
    /**
33
     * @var string
34
     */
35
    private static $plural_name = 'Locators';
36
    /**
37
     * @var string
38
     */
39
    private static $description = 'Find locations on a map';
40
41
    /**
42
     * @var string
43
     */
44
    private static $location_class = 'Location';
0 ignored issues
show
Unused Code introduced by
The property $location_class 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
46
    /**
47
     * @return FieldList
48
     */
49 1
    public function getCMSFields()
50
    {
51 1
        $fields = parent::getCMSFields();
52
53
        // Settings
54 1
        $fields->addFieldsToTab('Root.Settings', array(
55 1
            HeaderField::create('DisplayOptions', 'Display Options', 3),
56 1
            OptionsetField::create('Unit', 'Unit of measure', array('m' => 'Miles', 'km' => 'Kilometers')),
57 1
        ));
58
59
        // Filter categories
60 1
        $config = GridFieldConfig_RelationEditor::create();
61 1
        if (class_exists('GridFieldAddExistingSearchButton')) {
62 1
            $config->removeComponentsByType('GridFieldAddExistingAutocompleter');
63 1
            $config->addComponent(new GridFieldAddExistingSearchButton());
64 1
        }
65 1
        $categories = $this->Categories();
66 1
        $categoriesField = GridField::create('Categories', 'Categories', $categories, $config)
67 1
            ->setDescription('only show locations from the selected category');
68
69
        // Filter
70 1
        $fields->addFieldsToTab('Root.Filter', array(
71 1
            HeaderField::create('CategoryOptionsHeader', 'Location Filtering', 3),
72 1
            $categoriesField,
73 1
        ));
74
75 1
        $this->extend('updateCMSFields', $fields);
76
77 1
        return $fields;
78
    }
79
80
    /**
81
     * @param array $filter
82
     * @param array $filterAny
83
     * @param array $exclude
84
     * @param null|callable $callback
85
     * @return DataList|ArrayList
86
     */
87 1
    public static function get_locations(
88
        $filter = [],
89
        $filterAny = [],
90
        $exclude = [],
91
        $callback = null
92
    )
93
    {
94 1
        $locationClass = Config::inst()->get('Locator', 'location_class');
95 1
        $locations = $locationClass::get()->filter($filter)->exclude($exclude);
96
97 1
        if (!empty($filterAny)) {
98
            $locations = $locations->filterAny($filterAny);
99
        }
100 1
        if (!empty($exclude)) {
101 1
            $locations = $locations->exclude($exclude);
102 1
        }
103
104 1
        if ($callback !== null && is_callable($callback)) {
105
            $locations->filterByCallback($callback);
106
        }
107
108 1
        return $locations;
109
    }
110
111
    /**
112
     * @return DataList
113
     */
114 1
    public static function get_all_categories()
115
    {
116 1
        return LocationCategory::get();
117
    }
118
119
    /**
120
     * @return bool
121
     */
122 1
    public function getPageCategories()
123
    {
124 1
        return self::locator_categories_by_locator($this->ID);
125
    }
126
127
    /**
128
     * @param int $id
129
     * @return bool|
130
     */
131 5
    public static function locator_categories_by_locator($id = 0)
132
    {
133 5
        if ($id == 0) {
134
            return false;
135
        }
136
137 5
        return Locator::get()->byID($id)->Categories();
138
    }
139
140
141
}
142
143
/**
144
 * Class Locator_Controller
145
 */
146
class Locator_Controller extends Page_Controller
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
147
{
148
    /**
149
     * @var array
150
     */
151
    private static $allowed_actions = array(
152
        'xml',
153
    );
154
155
    /**
156
     * @var array
157
     */
158
    private static $base_filter = [];
0 ignored issues
show
Unused Code introduced by
The property $base_filter 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...
159
160
    /**
161
     * @var array
162
     */
163
    private static $base_exclude = [
0 ignored issues
show
Unused Code introduced by
The property $base_exclude 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...
164
        'Lat' => 0,
165
        'Lng' => 0,
166
    ];
167
168
    /**
169
     * @var array
170
     */
171
    private static $base_filter_any = [];
0 ignored issues
show
Unused Code introduced by
The property $base_filter_any 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...
172
173
    /**
174
     * @var string
175
     */
176
    private static $list_template_path = 'locator/templates/location-list-description.html';
0 ignored issues
show
Unused Code introduced by
The property $list_template_path 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...
177
178
    /**
179
     * @var string
180
     */
181
    private static $info_window_template_path = 'locator/templates/infowindow-description.html';
0 ignored issues
show
Unused Code introduced by
The property $info_window_template_path 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...
182
183
    /**
184
     * @var bool
185
     */
186
    private static $bootstrapify = true;
0 ignored issues
show
Unused Code introduced by
The property $bootstrapify 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...
187
188
    /**
189
     * @var int
190
     */
191
    private static $limit = 50;
0 ignored issues
show
Unused Code introduced by
The property $limit 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...
192
193
    /**
194
     * ID of map container
195
     *
196
     * @var string
197
     */
198
    private static $map_container = 'map';
0 ignored issues
show
Unused Code introduced by
The property $map_container 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...
199
200
    /**
201
     * class of location list container
202
     *
203
     * @var string
204
     */
205
    private static $list_container = 'loc-list';
0 ignored issues
show
Unused Code introduced by
The property $list_container 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...
206
207
    /**
208
     * GET variable which, if isset, will trigger storeLocator init and return XML
209
     *
210
     * @var string
211
     */
212
    private static $query_trigger = 'action_doFilterLocations';
0 ignored issues
show
Unused Code introduced by
The property $query_trigger 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...
213
214
    /**
215
     * @var DataList|ArrayList
216
     */
217
    protected $locations;
218
219
    /**
220
     * Set Requirements based on input from CMS
221
     */
222 1
    public function init()
223
    {
224
        parent::init();
225
226
        // prevent init of map if no query
227
        $request = Controller::curr()->getRequest();
228
        if ($this->getTrigger($request)) {
229
            // google maps api key
230
            $key = Config::inst()->get('GoogleGeocoding', 'google_api_key');
231
232
            $locations = $this->getLocations();
233
234
            if ($locations) {
235
236
                Requirements::css('locator/css/map.css');
237 1
                Requirements::javascript('framework/thirdparty/jquery/jquery.js');
238
                Requirements::javascript('https://maps.google.com/maps/api/js?key=' . $key);
239
                Requirements::javascript('locator/thirdparty/jquery-store-locator-plugin/assets/js/libs/handlebars.min.js');
240
                Requirements::javascript('locator/thirdparty/jquery-store-locator-plugin/assets/js/plugins/storeLocator/jquery.storelocator.js');
241
242
                $featuredInList = ($locations->filter('Featured', true)->count() > 0);
243
                $defaultCoords = $this->getAddressSearchCoords() ? $this->getAddressSearchCoords() : '';
244
245
                $featured = $featuredInList
246
                    ? 'featuredLocations: true'
247
                    : 'featuredLocations: false';
248
249
                // map config based on user input in Settings tab
250
                $limit = Config::inst()->get('Locator_Controller', 'limit');
251
                if ($limit < 1) $limit = -1;
252
                $load = 'fullMapStart: true, storeLimit: ' . $limit . ', maxDistance: true,';
253
254
                $listTemplatePath = Config::inst()->get('Locator_Controller', 'list_template_path');
255
                $infowindowTemplatePath = Config::inst()->get('Locator_Controller', 'info_window_template_path');
256
257
                $kilometer = ($this->data()->Unit == 'km') ? "lengthUnit: 'km'" : "lengthUnit: 'm'";
258
259
                // pass GET variables to xml action
260
                $vars = $this->request->getVars();
261
                unset($vars['url']);
262
                $url = '';
263
                if (count($vars)) {
264
                    $url .= '?' . http_build_query($vars);
265
                }
266
                $link = Controller::join_links($this->Link(), 'xml.xml', $url);
267
268
                // containers
269
                $map_id = Config::inst()->get('Locator_Controller', 'map_container');
270
                $list_class = Config::inst()->get('Locator_Controller', 'list_container');
271
272
                // init map
273
                Requirements::customScript("
274
                $(function(){
275
                    $('#map-container').storeLocator({
276
                        " . $load . "
277
                        dataLocation: '" . $link . "',
278
                        listTemplatePath: '" . $listTemplatePath . "',
279
                        infowindowTemplatePath: '" . $infowindowTemplatePath . "',
280
                        originMarker: true,
281
                        " . $featured . ",
282
                        slideMap: false,
283
                        distanceAlert: -1,
284
                        " . $kilometer . ",
285
                        " . $defaultCoords . "
286
                        mapID: '" . $map_id . "',
287
                        locationList: '" . $list_class . "',
288
                        mapSettings: {
289
							zoom: 12,
290
							mapTypeId: google.maps.MapTypeId.ROADMAP,
291
							disableDoubleClickZoom: true,
292
							scrollwheel: false,
293
							navigationControl: false,
294
							draggable: false
295
						}
296
                    });
297
                });
298
            ");
299
            }
300
        }
301
    }
302
303
    /**
304
     * @param SS_HTTPRequest $request
305
     *
306
     * @return ViewableData_Customised
307
     */
308 1 View Code Duplication
    public function index(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...
309
    {
310 1
        if ($this->getTrigger($request)) {
311
            $locations = $this->getLocations();
312
        } else {
313 1
            $locations = ArrayList::create();
314
        }
315
316 1
        return $this->customise(array(
317 1
            'Locations' => $locations,
318 1
        ));
319
    }
320
321
    /**
322
     * Return a XML feed of all locations marked "show in locator"
323
     *
324
     * @param SS_HTTPRequest $request
325
     * @return HTMLText
326
     */
327 1 View Code Duplication
    public function xml(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...
328
    {
329 1
        if ($this->getTrigger($request)) {
330
            $locations = $this->getLocations();
331
        } else {
332 1
            $locations = ArrayList::create();
333
        }
334
335 1
        return $this->customise(array(
336 1
            'Locations' => $locations,
337 1
        ))->renderWith('LocationXML');
338
    }
339
340
    /**
341
     * @return ArrayList|DataList
342
     */
343
    public function getLocations()
344
    {
345
        if (!$this->locations) {
346
            $this->setLocations($this->request);
347
        }
348
        return $this->locations;
349
    }
350
351
    /**
352
     * @param SS_HTTPRequest|null $request
353
     * @return $this
354
     */
355
    public function setLocations(SS_HTTPRequest $request = null)
356
    {
357
358
        if ($request === null) {
359
            $request = $this->request;
360
        }
361
        $filter = $this->config()->get('base_filter');
362
363
        if ($request->getVar('CategoryID')) {
364
            $filter['CategoryID'] = $request->getVar('CategoryID');
365
        } else {
366
            if ($this->getPageCategories()->exists()) {
367
                foreach ($this->getPageCategories() as $category) {
368
                    $filter['CategoryID'][] = $category->ID;
369
                }
370
            }
371
        }
372
373
        $this->extend('updateLocatorFilter', $filter, $request);
374
375
        $filterAny = $this->config()->get('base_filter_any');
376
        $this->extend('updateLocatorFilterAny', $filterAny, $request);
377
378
        $exclude = $this->config()->get('base_exclude');
379
        $this->extend('updateLocatorExclude', $exclude, $request);
380
381
        $locations = Locator::get_locations($filter, $filterAny, $exclude);
382
        $locations = DataToArrayListHelper::to_array_list($locations);
0 ignored issues
show
Bug introduced by
It seems like $locations defined by \DataToArrayListHelper::to_array_list($locations) on line 382 can also be of type object<ArrayList>; however, DataToArrayListHelper::to_array_list() does only seem to accept object<DataList>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
383
384
        //allow for adjusting list post possible distance calculation
385
        $this->extend('updateLocationList', $locations);
386
387
        if ($locations->canSortBy('distance')) {
388
            $locations = $locations->sort('distance');
389
        }
390
391
        if (Config::inst()->get('LocatorForm', 'show_radius')) {
392
            if ($radius = (int)$request->getVar('Radius')) {
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $radius, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
393
                $locations = $locations->filterByCallback(function ($location) use (&$radius) {
394
                    return $location->distance <= $radius;
395
                });
396
            }
397
        }
398
399
        //allow for returning list to be set as
400
        $this->extend('updateListType', $locations);
401
402
        $limit = Config::inst()->get('Locator_Controller', 'limit');
403
        if ($limit > 0) {
404
            $locations = $locations->limit($limit);
405
        }
406
407
        $this->locations = $locations;
408
        return $this;
409
410
    }
411
412
    /**
413
     * @param SS_HTTPRequest $request
414
     * @return bool
415
     */
416 2
    public function getTrigger(SS_HTTPRequest $request = null)
417
    {
418 2
        if ($request === null) {
419
            $request = $this->getRequest();
420
        }
421 2
        $trigger = $request->getVar(Config::inst()->get('Locator_Controller', 'query_trigger'));
422 2
        return isset($trigger);
423
    }
424
425
    /**
426
     * @return bool|string
427
     */
428
    public function getAddressSearchCoords()
429
    {
430
        if (!$this->request->getVar('Address')) {
431
            return false;
432
        }
433
        $coords = GoogleGeocoding::address_to_point(Controller::curr()->getRequest()->getVar('Address'));
434
435
        $lat = $coords['lat'];
436
        $lng = $coords['lng'];
437
438
        return "defaultLat: {$lat}, defaultLng: {$lng},";
439
    }
440
441
    /**
442
     * LocationSearch form.
443
     *
444
     * Search form for locations, updates map and results list via AJAX
445
     *
446
     * @return Form
447
     */
448 1
    public function LocationSearch()
449
    {
450
451 1
        $form = LocatorForm::create($this, 'LocationSearch');
452 1
        if (class_exists('BootstrapForm') && $this->config()->get('bootstrapify')) {
453
            $form->Fields()->bootstrapify();
454
            $form->Actions()->bootstrapify();
455
        }
456
457
        return $form
458 1
            ->setFormMethod('GET')
459 1
            ->setFormAction($this->Link())
460 1
            ->disableSecurityToken()
461 1
            ->loadDataFrom($this->request->getVars());
462
    }
463
464
}
465