Completed
Pull Request — master (#88)
by Jason
02:33
created

Locator_Controller   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 216
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 43.9%

Importance

Changes 27
Bugs 1 Features 3
Metric Value
wmc 27
c 27
b 1
f 3
lcom 1
cbo 11
dl 0
loc 216
ccs 18
cts 41
cp 0.439
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
D init() 0 75 10
A index() 0 8 1
C Items() 0 27 7
A xml() 0 8 1
B LocationSearch() 0 40 6
A doSearch() 0 15 2
1
<?php
2
3
class Locator extends Page
4
{
5
    private static $db = array(
1 ignored issue
show
Unused Code introduced by
The property $db 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...
6
        'AutoGeocode' => 'Boolean',
7
        'ModalWindow' => 'Boolean',
8
        'Unit' => 'Enum("m,km","m")',
9
    );
10
11
    private static $many_many = array(
1 ignored issue
show
Unused Code introduced by
The property $many_many 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...
12
        'Categories' => 'LocationCategory',
13
    );
14
15
    private static $defaults = array(
1 ignored issue
show
Unused Code introduced by
The property $defaults is not used and could be removed.

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

Loading history...
16
        'AutoGeocode' => true,
17
    );
18
19 1
    private static $singular_name = 'Locator';
1 ignored issue
show
Unused Code introduced by
The property $singular_name 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...
20
    private static $plural_name = 'Locators';
1 ignored issue
show
Unused Code introduced by
The property $plural_name 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...
21 1
    private static $description = 'Find locations on a map';
1 ignored issue
show
Unused Code introduced by
The property $description 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...
22
23
    public function getCMSFields()
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...
24 1
    {
25 1
        $fields = parent::getCMSFields();
26 1
27
        // Settings
28
        $fields->addFieldsToTab('Root.Settings', array(
29 1
            HeaderField::create('DisplayOptions', 'Display Options', 3),
30 1
            OptionsetField::create('Unit', 'Unit of measure', array('m' => 'Miles', 'km' => 'Kilometers')),
31
            CheckboxField::create('AutoGeocode', 'Auto Geocode - Automatically filter map results based on user location')
32
                ->setDescription('Note: if any locations are set as featured, the auto geocode is automatically disabled.'),
33 1
            CheckboxField::create('ModalWindow', 'Modal Window - Show Map results in a modal window'),
34 1
        ));
35 1
36 1
        // Filter categories
37 1
        $config = GridFieldConfig_RelationEditor::create();
38 1
        if (class_exists('GridFieldAddExistingSearchButton')) {
39 1
            $config->removeComponentsByType('GridFieldAddExistingAutocompleter');
40
            $config->addComponent(new GridFieldAddExistingSearchButton());
41 1
        }
42
        $categories = $this->Categories();
43 1
        $categoriesField = GridField::create('Categories', 'Categories', $categories, $config)
44
            ->setDescription('only show locations from the selected category');
45
46 3
            // Filter
47
            $fields->addFieldsToTab('Root.Filter', array(
48 3
                HeaderField::create('CategoryOptionsHeader', 'Location Filtering', 3),
49
                $categoriesField,
50 3
            ));
51 3
52 3
        $this->extend('updateCMSFields', $fields);
53 3
54
        return $fields;
55
    }
56 1
57
    public static function getLocations($filter = array(), $exclude = array(), $filterAny = array())
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...
58 1
    {
59
        $filter['ShowInLocator'] = true;
60
        $exclude['Lat'] = 0;
61 1
62
        $Locations = Location::get()->exclude($exclude)->filter($filter)->filterAny($filterAny);
63 1
64
        return $Locations;
65
    }
66
67
    public function getAreLocations()
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...
68
    {
69
        return self::getLocations();
70
    }
71
72
    public function getAllCategories()
73
    {
74
        return LocationCategory::get();
75
    }
76
77
    public static function getPageCategories($id = null)
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...
78
    {
79
        if ($id) {
80
            if ($locator = self::get()->byID($id)) {
81
                return $locator->Categories();
82
            }
83
84
            return false;
85
        }
86
87
        return false;
88
    }
89
90
    public static function locations(
91
        $filter = array(),
92
        $filterAny = array(),
93
        $exclude = array(),
94
        $filterByCallback = null
95
    ) {
96
97
        $locationsList = ArrayList::create();
98
99
        $locations = Location::get()->filter($filter);
100
101
        if (!empty($filterAny)) {
102
            $locations = $locations->filterAny($filterAny);
103
        }
104
        if (!empty($exclude)) {
105
            $locations = $locations->exclude($exclude);
106
        }
107
108
        if ($filterByCallback !== null && is_callable($filterByCallback)) {
109
            $locations = $locations->filterByCallback($filterByCallback);
110
        }
111
112
        if ($locations->exists()) {
113
            $locationsList->merge($locations);
114
        }
115
116
117
        return $locationsList;
118
    }
119
}
120
121
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...
122
{
123
    // allowed actions
124
    private static $allowed_actions = array(
1 ignored issue
show
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...
125
        'xml',
126
        'LocationSearch',
127
    );
128
129
    // Set Requirements based on input from CMS
130
    public function init()
131
    {
132
        parent::init();
133
134
        $themeDir = SSViewer::get_theme_folder();
135
136
        Requirements::javascript('framework/thirdparty/jquery/jquery.js');
137
        if (Locator::getLocations()) {
138
            Requirements::javascript('http://maps.google.com/maps/api/js?sensor=false');
139
            Requirements::javascript('locator/thirdparty/handlebars/handlebars-v1.3.0.js');
140
            Requirements::javascript('locator/thirdparty/jquery-store-locator/js/jquery.storelocator.js');
141
        }
142
143
        Requirements::css('locator/css/map.css');
144
145
        $featured = (Locator::getLocations(array('Featured' => 1))->count() > 0) ?
146
            'featuredLocations: true' :
147
            'featuredLocations: false';
148
149
        // map config based on user input in Settings tab
150
        // AutoGeocode or Full Map
151
        $load = ($this->data()->AutoGeocode) ?
152
            'autoGeocode: true, fullMapStart: false,' :
153
            'autoGeocode: false, fullMapStart: true, storeLimit: 1000, maxDistance: true,';
154
155
        $base = Director::baseFolder();
156
        $themePath = $base.'/'.$themeDir;
157
158
        $listTemplatePath = (file_exists($themePath.'/templates/location-list-description.html')) ?
159
            $themeDir.'/templates/location-list-description.html' :
160
            'locator/templates/location-list-description.html';
161
        $infowindowTemplatePath = (file_exists($themePath.'/templates/infowindow-description.html')) ?
162
            $themeDir.'/templates/infowindow-description.html' :
163
            'locator/templates/infowindow-description.html';
164
165
        // in page or modal
166
        $modal = ($this->data()->ModalWindow) ? 'modalWindow: true' : 'modalWindow: false';
167
168 1
        $kilometer = ($this->data()->Unit == 'km') ? 'lengthUnit: "km"' : 'lengthUnit: "m"';
169
170 1
        $vars = $this->request->getVars();
171 1
        unset($vars['url']);
172 1
173 1
        $url = '';
174
        if (count($vars)) {
175 1
            $url .= '?' . http_build_query($vars);
176 1
        }
177 1
        $link = $this->Link().'xml.xml'.$url;
178 1
179
        // init map
180 1
        if (Locator::getLocations()) {
181
            Requirements::customScript("
182 1
                $(function($) {
183
                    $('#map-container').storeLocator({
184 1
                        ".$load."
185
                        dataLocation: '".$link."',
186
                        listTemplatePath: '".$listTemplatePath."',
187
                        infowindowTemplatePath: '".$infowindowTemplatePath."',
188
                        originMarker: true,
189
                        ".$modal.',
190
                        '.$featured.",
191
                        slideMap: false,
192 1
                        zoomLevel: 0,
193
                        distanceAlert: 120,
194 1
                        noForm: true,
195 1
                        formID: 'Form_LocationSearch',
196 1
                        inputID: 'Form_LocationSearch_address',
197
                        categoryID: 'Form_LocationSearch_category',
198 1
                        distanceAlert: -1,
199
                        ".$kilometer.'
200
                    });
201 1
                });
202
            ');
203
        }
204
    }
205
206
    /**
207
     * @param SS_HTTPRequest $request
208
     * @return ViewableData_Customised
209
     */
210
    public function index(SS_HTTPRequest $request)
211
    {
212
        $locations = $this->Items($request);
213
214
        return $this->customise(array(
215
            'Locations' => $locations
216
        ));
217
    }
218
219
220
221
    /**
222
     * @param array $searchCriteria
223
     * @return mixed
224
     */
225
    public function Items($searchCriteria = array())
226
    {
227
        $request = ($this->request) ? $this->request : $this->parentController->getRequest();
228
        if(empty($searchCriteria)) $searchCriteria = $request->requestVars();
0 ignored issues
show
Unused Code introduced by
$searchCriteria 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...
229
230
        $filter = array();
231
        $filterAny = array();
232
        $exclude = array();
233
234
        $address = ($request->getVar('Address')) ? $request->getVar('Address') : false;
235
        if ($address) {
236
            $filterAny['Address:PartialMatch'] = $address;
237
            $filterAny['Suburb:PartialMatch'] = $address;
238
            $filterAny['State:PartialMatch'] = $address;
239
            $filterAny['Postcode:PartialMatch'] = $address;
240
            $filterAny['Country:PartialMatch'] = $address;
241
        }
242
243
        $category = ($request->getVar('CategoryID')) ? $request->getVar('CategoryID') : false;
244
        if ($category) {
245
            $filter['CategoryID'] = $category;
246
        }
247
248
        $locations = Locator::locations($filter, $filterAny, $exclude);
249
250
        return $locations;
251
    }
252
253
    /**
254
     * Find all locations for map.
255
     *
256
     * Will return a XML feed of all locations marked "show in locator".
257
     *
258
     * @return XML file
259
     *
260
     * @todo rename/refactor to allow for json/xml
261
     * @todo allow $filter to run off of getVars key/val pair
262
     */
263
    public function xml(SS_HTTPRequest $request)
264
    {
265
        $locations = $this->Items($request);
266
267
        return $this->customise(array(
268
            'Locations' => $locations,
269
        ))->renderWith('LocationXML');
270
    }
271
272
    /**
273
     * LocationSearch form.
274
     *
275
     * Search form for locations, updates map and results list via AJAX
276
     *
277
     * @return Form
278
     */
279
    public function LocationSearch()
280
    {
281
        $fields = FieldList::create(
282
            $address = TextField::create('Address', '')
283
                ->setAttribute('placeholder', 'address or zip code')
284
        );
285
286
        $locatorCategories = Locator::getPageCategories($this->ID);
287
288
        if (LocationCategory::get()->Count() > 0 && $locatorCategories && $locatorCategories->Count() != 1) {
289
290
            $ct = $locatorCategories->Count();
291
292
            if ($ct > 0) {
293
                $categories = $locatorCategories;
294
            } else {
295
                $categories = LocationCategory::get();
296
            }
297
298
            if ($categories->count() > 0) {
299
                $fields->push(
300
                    DropdownField::create(
301
                        'CategoryID',
302
                        '',
303
                        $categories->map()
304
                    )->setEmptyString('Select Category'));
305
            }
306
        }
307
308
        $actions = FieldList::create(
309
            FormAction::create('doSearch', 'Search')
310
        );
311
312
        return Form::create($this, 'LocationSearch', $fields, $actions)
313
            ->setFormMethod('GET')
314
            ->setFormAction($this->Link())
315
            ->disableSecurityToken()
316
            ->loadDataFrom($this->request->getVars())
317
        ;
318
    }
319
320
    // Results filtered by query
321
    function doSearch($data, $form, $request)
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...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
322
    {
323
        if (isset($data['location'])) {
324
            $location = $data['location'];
325
            $data['Address'] = $location;
326
            $data['Suburb'] = $location;
327
            $data['State'] = $location;
328
            $data['Postcode'] = $location;
329
            $data['Country'] = $location;
330
        }
331
        return $this->render(array(
332
            'Items' => $this->Items($data),
333
            'AdvSearchForm' => $form
334
        ));
335
    }
336
}
337