Passed
Push — master ( affe64...6c9189 )
by Jason
02:51
created

LocatorController::setLocations()   B

Complexity

Conditions 9
Paths 72

Size

Total Lines 58
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 9
eloc 31
nc 72
nop 1
dl 0
loc 58
rs 8.0555
c 3
b 0
f 0

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
namespace Dynamic\Locator;
4
5
use Dynamic\SilverStripeGeocoder\DistanceDataExtension;
6
use Dynamic\SilverStripeGeocoder\GoogleGeocoder;
7
use muskie9\DataToArrayList\ORM\DataToArrayListHelper;
8
use SilverStripe\Control\Controller;
9
use SilverStripe\Control\HTTPRequest;
10
use SilverStripe\Core\Config\Config;
11
use SilverStripe\ORM\ArrayList;
12
use SilverStripe\ORM\DataList;
13
use SilverStripe\View\ArrayData;
14
use SilverStripe\View\Requirements;
15
16
/**
17
 * Class LocatorController
18
 */
19
class LocatorController extends \PageController
20
{
21
    /**
22
     * @var array
23
     */
24
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
25
        'xml',
26
        'json',
27
    ];
28
29
    /**
30
     * @var array
31
     */
32
    private static $base_filter = [];
0 ignored issues
show
introduced by
The private property $base_filter is not used, and could be removed.
Loading history...
33
34
    /**
35
     * @var array
36
     */
37
    private static $base_exclude = [
0 ignored issues
show
introduced by
The private property $base_exclude is not used, and could be removed.
Loading history...
38
        'Lat' => 0,
39
        'Lng' => 0,
40
    ];
41
42
    /**
43
     * @var array
44
     */
45
    private static $base_filter_any = [];
0 ignored issues
show
introduced by
The private property $base_filter_any is not used, and could be removed.
Loading history...
46
47
    /**
48
     * @var bool
49
     */
50
    private static $bootstrapify = true;
0 ignored issues
show
introduced by
The private property $bootstrapify is not used, and could be removed.
Loading history...
51
52
    /**
53
     * ID of map container
54
     *
55
     * @var string
56
     */
57
    private static $map_container = 'map';
0 ignored issues
show
introduced by
The private property $map_container is not used, and could be removed.
Loading history...
58
59
    /**
60
     * class of location list container
61
     *
62
     * @var string
63
     */
64
    private static $list_container = 'loc-list';
0 ignored issues
show
introduced by
The private property $list_container is not used, and could be removed.
Loading history...
65
66
    /**
67
     * GET variable which, if isset, will trigger storeLocator init and return XML
68
     *
69
     * @var string
70
     */
71
    private static $query_trigger = 'action_doFilterLocations';
0 ignored issues
show
introduced by
The private property $query_trigger is not used, and could be removed.
Loading history...
72
73
    /**
74
     * @var DataList|ArrayList
75
     */
76
    protected $locations;
77
78
    /**
79
     * Set Requirements based on input from CMS
80
     */
81
    public function init()
82
    {
83
        parent::init();
84
        // google maps api key
85
        $key = Config::inst()->get(GoogleGeocoder::class, 'geocoder_api_key');
86
        Requirements::javascript('https://maps.google.com/maps/api/js?key=' . $key);
87
88
        // prevent init of map if no query
89
        $request = Controller::curr()->getRequest();
90
91
        if ($this->getTrigger($request)) {
92
            $locations = $this->getLocations();
93
94
            if ($locations) {
95
                $featuredInList = ($locations->filter('Featured', true)->count() > 0);
96
                $defaultCoords = $this->getAddressSearchCoords() ?
97
                    $this->getAddressSearchCoords() :
98
                    new ArrayData([
99
                        "Lat" => 0,
100
                        "Lng" => 0,
101
                    ]);
102
103
                $featured = $featuredInList
104
                    ? 'featuredLocations: true'
105
                    : 'featuredLocations: false';
106
107
                // map config based on user input in Settings tab
108
                $limit = Config::inst()->get(LocatorController::class, 'limit');
109
                if ($limit < 1) {
110
                    $limit = -1;
111
                }
112
                $load = 'fullMapStart: true, storeLimit: ' . $limit . ', maxDistance: true,';
113
114
                $listTemplatePath = $this->getListTemplate();
0 ignored issues
show
Bug introduced by
The method getListTemplate() does not exist on Dynamic\Locator\LocatorController. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

114
                /** @scrutinizer ignore-call */ 
115
                $listTemplatePath = $this->getListTemplate();
Loading history...
115
                $infowindowTemplatePath = $this->getInfoWindowTemplate();
0 ignored issues
show
Bug introduced by
The method getInfoWindowTemplate() does not exist on Dynamic\Locator\LocatorController. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

115
                /** @scrutinizer ignore-call */ 
116
                $infowindowTemplatePath = $this->getInfoWindowTemplate();
Loading history...
116
117
                $kilometer = ($this->data()->Unit == 'km') ? "lengthUnit: 'km'" : "lengthUnit: 'm'";
118
119
                // pass GET variables to xml action
120
                $vars = $this->request->getVars();
121
                unset($vars['url']);
122
                $url = '';
123
                if (count($vars)) {
124
                    $url .= '?' . http_build_query($vars);
125
                }
126
                $link = Controller::join_links($this->Link(), 'xml.xml', $url);
127
128
                // containers
129
                $map_id = Config::inst()->get(LocatorController::class, 'map_container');
130
                $list_class = Config::inst()->get(LocatorController::class, 'list_container');
131
132
                $mapStyle = '';
133
                if ($stylePath = $this->getMapStyleJSONPath()) {
0 ignored issues
show
Bug introduced by
The method getMapStyleJSONPath() does not exist on Dynamic\Locator\LocatorController. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

133
                if ($stylePath = $this->/** @scrutinizer ignore-call */ getMapStyleJSONPath()) {
Loading history...
134
                    if ($style = file_get_contents($stylePath)) {
135
                        $mapStyle = "styles: {$style},";
136
                    }
137
                };
138
139
                $markerImage = '';
140
                if ($imagePath = $this->getMarkerIcon()) {
0 ignored issues
show
Bug introduced by
The method getMarkerIcon() does not exist on Dynamic\Locator\LocatorController. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

140
                if ($imagePath = $this->/** @scrutinizer ignore-call */ getMarkerIcon()) {
Loading history...
141
                    $markerImage = "markerImg: '{$imagePath}',";
142
                }
143
144
                // init map
145
                Requirements::customScript("
146
                $(function(){
147
                    $('#map-container').storeLocator({
148
                        {$load}
149
                        dataLocation: '{$link}',
150
                        listTemplatePath: '{$listTemplatePath}',
151
                        infowindowTemplatePath: '{$infowindowTemplatePath}',
152
                        {$markerImage}
153
                        originMarker: true,
154
                        {$featured},
155
                        slideMap: false,
156
                        distanceAlert: -1,
157
                        {$kilometer},
158
                        defaultLat: {$defaultCoords->getField("Lat")},
159
                        defaultLng: {$defaultCoords->getField("Lng")},
160
                        mapID: '{$map_id}',
161
                        locationList: '{$list_class}',
162
                        mapSettings: {
163
                            {$mapStyle}
164
							zoom: 12,
165
							mapTypeId: google.maps.MapTypeId.ROADMAP,
166
							disableDoubleClickZoom: true,
167
							scrollwheel: false,
168
							navigationControl: false,
169
							draggable: false
170
						}
171
                    });
172
                });
173
            ", 'jquery-locator');
174
            }
175
        }
176
    }
177
178
    /**
179
     * @param HTTPRequest $request
180
     *
181
     * @return bool
182
     */
183
    public function getTrigger(HTTPRequest $request = null)
184
    {
185
        if ($request === null) {
186
            $request = $this->getRequest();
187
        }
188
        $trigger = $request->getVar(Config::inst()->get(LocatorController::class, 'query_trigger'));
189
190
        return isset($trigger);
191
    }
192
193
    /**
194
     * @return ArrayList|DataList
195
     */
196
    public function getLocations()
197
    {
198
        if (!$this->locations) {
199
            $this->setLocations($this->request);
200
        }
201
202
        return $this->locations;
203
    }
204
205
    /**
206
     * @param HTTPRequest|null $request
207
     *
208
     * @return $this
209
     */
210
    public function setLocations(HTTPRequest $request = null)
211
    {
212
213
        if ($request === null) {
214
            $request = $this->request;
215
        }
216
        $filter = $this->config()->get('base_filter');
217
218
        $categoryVar = Config::inst()->get(Locator::class, 'category_var');
219
        if ($request->getVar($categoryVar)) {
220
            $filter['Categories.ID'] = $request->getVar($categoryVar);
221
        } else {
222
            if ($this->getPageCategories()->exists()) {
0 ignored issues
show
Bug introduced by
The method getPageCategories() does not exist on Dynamic\Locator\LocatorController. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

222
            if ($this->/** @scrutinizer ignore-call */ getPageCategories()->exists()) {
Loading history...
223
                foreach ($this->getPageCategories() as $category) {
224
                    $filter['Categories.ID'][] = $category->ID;
225
                }
226
            }
227
        }
228
229
        $this->extend('updateLocatorFilter', $filter, $request);
230
231
        $filterAny = $this->config()->get('base_filter_any');
232
        $this->extend('updateLocatorFilterAny', $filterAny, $request);
233
234
        $exclude = $this->config()->get('base_exclude');
235
        $this->extend('updateLocatorExclude', $exclude, $request);
236
237
        $locations = Locator::get_locations($filter, $filterAny, $exclude);
238
        $locations = DataToArrayListHelper::to_array_list($locations);
0 ignored issues
show
Bug introduced by
It seems like $locations can also be of type SilverStripe\ORM\ArrayList; however, parameter $list of muskie9\DataToArrayList\...Helper::to_array_list() does only seem to accept SilverStripe\ORM\DataList, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

238
        $locations = DataToArrayListHelper::to_array_list(/** @scrutinizer ignore-type */ $locations);
Loading history...
239
240
        //allow for adjusting list post possible distance calculation
241
        $this->extend('updateLocationList', $locations);
242
243
        if ($locations->canSortBy('Distance')) {
244
            $locations = $locations->sort('Distance');
245
        }
246
247
        if ($this->getShowRadius()) {
0 ignored issues
show
Bug introduced by
The method getShowRadius() does not exist on Dynamic\Locator\LocatorController. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

247
        if ($this->/** @scrutinizer ignore-call */ getShowRadius()) {
Loading history...
248
            $radiusVar = Config::inst()->get(Locator::class, 'radius_var');
249
250
            if ($radius = (int)$request->getVar($radiusVar)) {
251
                $locations = $locations->filterByCallback(function ($location) use (&$radius) {
252
                    return $location->Distance <= $radius;
253
                });
254
            }
255
        }
256
257
        //allow for returning list to be set as
258
        $this->extend('updateListType', $locations);
259
260
        $limit = $this->getLimit();
0 ignored issues
show
Bug introduced by
The method getLimit() does not exist on Dynamic\Locator\LocatorController. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

260
        /** @scrutinizer ignore-call */ 
261
        $limit = $this->getLimit();
Loading history...
261
        if ($limit > 0) {
262
            $locations = $locations->limit($limit);
263
        }
264
265
        $this->locations = $locations;
266
267
        return $this;
268
    }
269
270
    /**
271
     * @return ArrayData|boolean
272
     */
273
    public function getAddressSearchCoords()
274
    {
275
        $addressVar = Config::inst()->get(DistanceDataExtension::class, 'address_var');
276
        if (!$this->request->getVar($addressVar)) {
277
            return false;
278
        }
279
        if (class_exists(GoogleGeocoder::class)) {
280
            $geocoder = new GoogleGeocoder($this->request->getVar($addressVar));
281
            $response = $geocoder->getResult();
282
            $lat = $response->getLatitude();
283
            $lng = $response->getLongitude();
284
285
            return new ArrayData([
286
                "Lat" => $lat,
287
                "Lng" => $lng,
288
            ]);
289
        }
290
    }
291
292
    /**
293
     * @param HTTPRequest $request
294
     *
295
     * @return \SilverStripe\View\ViewableData_Customised
296
     */
297
    public function index(HTTPRequest $request)
298
    {
299
        if ($this->getTrigger($request)) {
300
            $locations = $this->getLocations();
301
        } else {
302
            $locations = ArrayList::create();
303
        }
304
305
        return $this->customise(array(
306
            'Locations' => $locations,
307
        ));
308
    }
309
310
    /**
311
     * Renders locations in xml format
312
     *
313
     * @return \SilverStripe\ORM\FieldType\DBHTMLText
314
     */
315
    public function xml()
316
    {
317
        $this->getResponse()->addHeader("Content-Type", "application/xml");
318
        $data = new ArrayData(array(
319
            "Locations" => $this->getLocations(),
320
            "AddressCoords" => $this->getAddressSearchCoords(),
321
        ));
322
323
        return $data->renderWith('Dynamic/Locator/Data/XML');
324
    }
325
326
    /**
327
     * Renders locations in json format
328
     *
329
     * @return \SilverStripe\ORM\FieldType\DBHTMLText
330
     */
331
    public function json()
332
    {
333
        $this->getResponse()->addHeader("Content-Type", "application/json");
334
        $data = new ArrayData(array(
335
            "Locations" => $this->getLocations(),
336
            "AddressCoords" => $this->getAddressSearchCoords(),
337
        ));
338
339
        return $data->renderWith('Dynamic/Locator/Data/JSON');
340
    }
341
342
    /**
343
     * LocationSearch form.
344
     *
345
     * Search form for locations, updates map and results list via AJAX
346
     *
347
     * @return \SilverStripe\Forms\Form
348
     */
349
    public function LocationSearch()
350
    {
351
352
        $form = LocatorForm::create($this, 'LocationSearch');
353
        if (class_exists(BootstrapForm::class) && $this->config()->get('bootstrapify')) {
0 ignored issues
show
Bug introduced by
The type Dynamic\Locator\BootstrapForm was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
354
            $form->Fields()->bootstrapify();
355
            $form->Actions()->bootstrapify();
356
        }
357
358
        return $form
359
            ->setFormMethod('GET')
360
            ->setFormAction($this->Link())
361
            ->disableSecurityToken()
362
            ->loadDataFrom($this->request->getVars());
363
    }
364
}
365