LocatorController   A
last analyzed

Complexity

Total Complexity 32

Size/Duplication

Total Lines 342
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 32
eloc 144
c 0
b 0
f 0
dl 0
loc 342
rs 9.84

9 Methods

Rating   Name   Duplication   Size   Complexity  
B setLocations() 0 59 9
A getTrigger() 0 8 2
A LocationSearch() 0 12 1
A getAddressSearchCoords() 0 15 3
A index() 0 10 2
A getLocations() 0 7 2
A xml() 0 9 1
C init() 0 94 11
A json() 0 9 1
1
<?php
2
3
namespace Dynamic\Locator\Page;
4
5
use Dynamic\Locator\Form\LocatorForm;
6
use Dynamic\SilverStripeGeocoder\DistanceDataExtension;
7
use Dynamic\SilverStripeGeocoder\GoogleGeocoder;
8
use muskie9\DataToArrayList\ORM\DataToArrayListHelper;
9
use SilverStripe\Control\Controller;
10
use SilverStripe\Control\HTTPRequest;
11
use SilverStripe\Core\Config\Config;
12
use SilverStripe\ORM\ArrayList;
13
use SilverStripe\ORM\DataList;
14
use SilverStripe\View\ArrayData;
15
use SilverStripe\View\Requirements;
16
17
/**
18
 * Class LocatorController
19
 *
20
 * @mixin Locator
21
 */
22
class LocatorController extends \PageController
23
{
24
    /**
25
     * @var array
26
     */
27
    private static $allowed_actions = [
0 ignored issues
show
introduced by
The private property $allowed_actions is not used, and could be removed.
Loading history...
28
        'xml',
29
        'json',
30
    ];
31
32
    /**
33
     * @var array
34
     */
35
    private static $base_filter = [];
0 ignored issues
show
introduced by
The private property $base_filter is not used, and could be removed.
Loading history...
36
37
    /**
38
     * @var array
39
     */
40
    private static $base_exclude = [
0 ignored issues
show
introduced by
The private property $base_exclude is not used, and could be removed.
Loading history...
41
        'Lat' => 0,
42
        'Lng' => 0,
43
    ];
44
45
    /**
46
     * @var array
47
     */
48
    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...
49
50
    /**
51
     * @var bool
52
     */
53
    private static $bootstrapify = true;
0 ignored issues
show
introduced by
The private property $bootstrapify is not used, and could be removed.
Loading history...
54
55
    /**
56
     * ID of map container
57
     *
58
     * @var string
59
     */
60
    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...
61
62
    /**
63
     * class of location list container
64
     *
65
     * @var string
66
     */
67
    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...
68
69
    /**
70
     * GET variable which, if isset, will trigger storeLocator init and return XML
71
     *
72
     * @var string
73
     */
74
    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...
75
76
    /**
77
     * @var DataList|ArrayList
78
     */
79
    protected $locations;
80
81
    /**
82
     * Set Requirements based on input from CMS
83
     */
84
    public function init()
85
    {
86
        parent::init();
87
88
        // prevent init of map if no query
89
        $request = Controller::curr()->getRequest();
90
        if (!$this->getTrigger($request)) {
91
            return;
92
        }
93
94
        $locations = $this->getLocations();
95
96
        // prevent init of map if there are no locations
97
        if (!$locations) {
98
            return;
99
        }
100
101
        // google maps api key
102
        $key = Config::inst()->get(GoogleGeocoder::class, 'map_api_key');
103
        Requirements::javascript('https://maps.google.com/maps/api/js?key=' . $key);
104
105
        $mapSettings = [
106
            'fullMapStart' => true,
107
            'maxDistance' => true,
108
            'storeLimit' => -1,
109
            'originMarker' => true,
110
            'slideMap' => false,
111
            'distanceAlert' => -1,
112
            'featuredLocations' => false,
113
            'defaultLat' => 0,
114
            'defaultLng' => 0,
115
            'mapSettings' => [
116
                'zoom' => 12,
117
                'mapTypeId' => 'google.maps.MapTypeId.ROADMAP',
118
                'disableDoubleClickZoom' => true,
119
                'scrollwheel' => false,
120
                'navigationControl' => false,
121
                'draggable' => false,
122
            ],
123
        ];
124
125
        $mapSettings['listTemplatePath'] = $this->getListTemplate();
0 ignored issues
show
Bug introduced by
The method getListTemplate() does not exist on Dynamic\Locator\Page\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

125
        /** @scrutinizer ignore-call */ 
126
        $mapSettings['listTemplatePath'] = $this->getListTemplate();
Loading history...
126
        $mapSettings['infowindowTemplatePath'] = $this->getInfoWindowTemplate();
0 ignored issues
show
Bug introduced by
The method getInfoWindowTemplate() does not exist on Dynamic\Locator\Page\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

126
        /** @scrutinizer ignore-call */ 
127
        $mapSettings['infowindowTemplatePath'] = $this->getInfoWindowTemplate();
Loading history...
127
        $mapSettings['lengthUnit'] = $this->data()->Unit == 'km' ? 'km' : 'm';
128
        $mapSettings['mapID'] = Config::inst()->get(LocatorController::class, 'map_container');
129
        $mapSettings['locationList'] = Config::inst()->get(LocatorController::class, 'list_container');
130
131
        if ($locations->filter('Featured', true)->count() > 0) {
132
            $mapSettings['featuredLocations'] = true;
133
        }
134
135
        // map config based on user input in Settings tab
136
        $limit = Config::inst()->get(LocatorController::class, 'limit');
137
        if (0 < $limit) {
138
            $mapSettings['storeLimit'] = $limit;
139
        }
140
141
        if ($coords = $this->getAddressSearchCoords()) {
142
            $mapSettings['defaultLat'] = $coords->getField("Lat");
143
            $mapSettings['defaultLat'] = $coords->getField("Lng");
144
        }
145
146
        // pass GET variables to xml action
147
        $vars = $this->request->getVars();
148
        unset($vars['url']);
149
        $url = '';
150
        if (count($vars)) {
151
            $url .= '?' . http_build_query($vars);
152
        }
153
        $mapSettings['dataLocation'] = Controller::join_links($this->Link(), 'xml.xml', $url);
154
155
        if ($stylePath = $this->getMapStyleJSONPath()) {
0 ignored issues
show
Bug introduced by
The method getMapStyleJSONPath() does not exist on Dynamic\Locator\Page\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

155
        if ($stylePath = $this->/** @scrutinizer ignore-call */ getMapStyleJSONPath()) {
Loading history...
156
            if ($style = file_get_contents($stylePath)) {
157
                $mapSettings['mapSettings']['styles'] = json_decode($style);
158
            }
159
        }
160
161
        if ($imagePath = $this->getMarkerIcon()) {
0 ignored issues
show
Bug introduced by
The method getMarkerIcon() does not exist on Dynamic\Locator\Page\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

161
        if ($imagePath = $this->/** @scrutinizer ignore-call */ getMarkerIcon()) {
Loading history...
162
            $mapSettings['markerImg'] = $imagePath;
163
        }
164
165
        $this->extend('modifyMapSettings', $mapSettings);
166
167
        $encoded = json_encode($mapSettings, JSON_UNESCAPED_SLASHES);
168
        // mapTypeId is a javascript object
169
        $encoded = preg_replace('/("mapTypeId"\s*:\s*)"(.+?)"/i', '$1$2', $encoded);
170
171
        $this->extend('modifyMapSettingsEncoded', $encoded);
172
        // init map
173
        Requirements::customScript("
174
                $(function(){
175
                    $('#map-container').storeLocator({$encoded});
176
                });
177
            ", 'jquery-locator');
178
    }
179
180
    /**
181
     * @param HTTPRequest $request
182
     *
183
     * @return bool
184
     */
185
    public function getTrigger(HTTPRequest $request = null)
186
    {
187
        if ($request === null) {
188
            $request = $this->getRequest();
189
        }
190
        $trigger = $request->getVar(Config::inst()->get(LocatorController::class, 'query_trigger'));
191
192
        return isset($trigger);
193
    }
194
195
    /**
196
     * @return ArrayList|DataList
197
     */
198
    public function getLocations()
199
    {
200
        if (!$this->locations) {
201
            $this->setLocations($this->request);
202
        }
203
204
        return $this->locations;
205
    }
206
207
    /**
208
     * @param HTTPRequest|null $request
209
     *
210
     * @return $this
211
     */
212
    public function setLocations(HTTPRequest $request = null)
213
    {
214
215
        if ($request === null) {
216
            $request = $this->request;
217
        }
218
        $filter = $this->config()->get('base_filter');
219
220
        $categoryVar = $this->data()->config()->get('category_var');
221
        if ($request->getVar($categoryVar)) {
222
            $filter['Categories.ID'] = $request->getVar($categoryVar);
223
        } else {
224
            if ($this->getPageCategories()->exists()) {
0 ignored issues
show
Bug introduced by
The method getPageCategories() does not exist on Dynamic\Locator\Page\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

224
            if ($this->/** @scrutinizer ignore-call */ getPageCategories()->exists()) {
Loading history...
225
                foreach ($this->getPageCategories() as $category) {
226
                    $filter['Categories.ID'][] = $category->ID;
227
                }
228
            }
229
        }
230
231
        $this->extend('updateLocatorFilter', $filter, $request);
232
233
        $filterAny = $this->config()->get('base_filter_any');
234
        $this->extend('updateLocatorFilterAny', $filterAny, $request);
235
236
        $exclude = $this->config()->get('base_exclude');
237
        $this->extend('updateLocatorExclude', $exclude, $request);
238
239
        $class = $this->data()->ClassName;
240
        $locations = $class::get_locations($filter, $filterAny, $exclude);
241
        $locations = DataToArrayListHelper::to_array_list($locations);
242
243
        //allow for adjusting list post possible distance calculation
244
        $this->extend('updateLocationList', $locations);
245
246
        if ($locations->canSortBy('Distance')) {
247
            $locations = $locations->sort('Distance');
248
        }
249
250
        if ($this->getShowRadius()) {
0 ignored issues
show
Bug introduced by
The method getShowRadius() does not exist on Dynamic\Locator\Page\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

250
        if ($this->/** @scrutinizer ignore-call */ getShowRadius()) {
Loading history...
251
            $radiusVar = $this->data()->config()->get('radius_var');
252
253
            if ($radius = (int)$request->getVar($radiusVar)) {
254
                $locations = $locations->filterByCallback(function ($location) use (&$radius) {
255
                    return $location->Distance <= $radius;
256
                });
257
            }
258
        }
259
260
        //allow for returning list to be set as
261
        $this->extend('updateListType', $locations);
262
263
        $limit = $this->getLimit();
0 ignored issues
show
Bug introduced by
The method getLimit() does not exist on Dynamic\Locator\Page\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

263
        /** @scrutinizer ignore-call */ 
264
        $limit = $this->getLimit();
Loading history...
264
        if ($limit > 0) {
265
            $locations = $locations->limit($limit);
266
        }
267
268
        $this->locations = $locations;
269
270
        return $this;
271
    }
272
273
    /**
274
     * @return ArrayData|boolean
275
     */
276
    public function getAddressSearchCoords()
277
    {
278
        $addressVar = Config::inst()->get(DistanceDataExtension::class, 'address_var');
279
        if (!$this->request->getVar($addressVar)) {
280
            return false;
281
        }
282
        if (class_exists(GoogleGeocoder::class)) {
283
            $geocoder = new GoogleGeocoder($this->request->getVar($addressVar));
284
            $response = $geocoder->getResult();
285
            $lat = $response->getLatitude();
286
            $lng = $response->getLongitude();
287
288
            return new ArrayData([
289
                "Lat" => $lat,
290
                "Lng" => $lng,
291
            ]);
292
        }
293
    }
294
295
    /**
296
     * @param HTTPRequest $request
297
     *
298
     * @return \SilverStripe\View\ViewableData_Customised
299
     */
300
    public function index(HTTPRequest $request)
301
    {
302
        if ($this->getTrigger($request)) {
303
            $locations = $this->getLocations();
304
        } else {
305
            $locations = ArrayList::create();
306
        }
307
308
        return $this->customise([
309
            'Locations' => $locations,
310
        ]);
311
    }
312
313
    /**
314
     * Renders locations in xml format
315
     *
316
     * @return \SilverStripe\ORM\FieldType\DBHTMLText
317
     */
318
    public function xml()
319
    {
320
        $this->getResponse()->addHeader("Content-Type", "application/xml");
321
        $data = new ArrayData([
322
            "Locations" => $this->getLocations(),
323
            "AddressCoords" => $this->getAddressSearchCoords(),
324
        ]);
325
326
        return $data->renderWith('Dynamic/Locator/Data/XML');
327
    }
328
329
    /**
330
     * Renders locations in json format
331
     *
332
     * @return \SilverStripe\ORM\FieldType\DBHTMLText
333
     */
334
    public function json()
335
    {
336
        $this->getResponse()->addHeader("Content-Type", "application/json");
337
        $data = new ArrayData([
338
            "Locations" => $this->getLocations(),
339
            "AddressCoords" => $this->getAddressSearchCoords(),
340
        ]);
341
342
        return $data->renderWith('Dynamic/Locator/Data/JSON');
343
    }
344
345
    /**
346
     * LocationSearch form.
347
     *
348
     * Search form for locations, updates map and results list via AJAX
349
     *
350
     * @return \SilverStripe\Forms\Form
351
     */
352
    public function LocationSearch()
353
    {
354
355
        $form = LocatorForm::create($this, 'LocationSearch');
356
357
        $this->extend('updateLocationSearch', $form);
358
359
        return $form
360
            ->setFormMethod('GET')
361
            ->setFormAction($this->Link())
362
            ->disableSecurityToken()
363
            ->loadDataFrom($this->request->getVars());
364
    }
365
}
366