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

Locator_Controller::Items()   C

Complexity

Conditions 7
Paths 64

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 33
ccs 0
cts 0
cp 0
rs 6.7272
cc 7
eloc 20
nc 64
nop 1
crap 56
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
        $locationsList = ArrayList::create();
97
98
        $locations = Location::get()->filter($filter);
99
100
        if (!empty($filterAny)) {
101
            $locations = $locations->filterAny($filterAny);
102
        }
103
        if (!empty($exclude)) {
104
            $locations = $locations->exclude($exclude);
105
        }
106
107
        if ($filterByCallback !== null && is_callable($filterByCallback)) {
108
            $locations = $locations->filterByCallback($filterByCallback);
109
        }
110
111
        if ($locations->exists()) {
112
            $locationsList->merge($locations);
113
        }
114
115
        return $locationsList;
116
    }
117
}
118
119
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...
120
{
121
    // allowed actions
122
    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...
123
        'xml',
124
    );
125
126
    // Set Requirements based on input from CMS
127
    public function init()
128
    {
129
        parent::init();
130
131
        $themeDir = SSViewer::get_theme_folder();
132
133
        // google maps api key
134
        $key = Config::inst()->get('GoogleGeocoding', 'google_api_key');
135
136
        Requirements::javascript('framework/thirdparty/jquery/jquery.js');
137
        if (Locator::getLocations()) {
138
            Requirements::javascript('http://maps.google.com/maps/api/js?key='.$key);
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
        // pass GET variables to xml action
171 1
        $vars = $this->request->getVars();
172 1
        unset($vars['url']);
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_CategoryID',
198 1
                        distanceAlert: -1,
199
                        ".$kilometer.'
200
                    });
201 1
                });
202
            ');
203
        }
204
    }
205
206
    /**
207
     * @param SS_HTTPRequest $request
208
     *
209
     * @return ViewableData_Customised
210
     */
211
    public function index(SS_HTTPRequest $request)
212
    {
213
        $locations = $this->Items($request);
214
215
        return $this->customise(array(
216
            'Locations' => $locations,
217
        ));
218
    }
219
220
    /**
221
     * Return a XML feed of all locations marked "show in locator"
222
     *
223
     * @param SS_HTTPRequest $request
224
     * @return HTMLText
225
     */
226
    public function xml(SS_HTTPRequest $request)
227
    {
228
        $locations = $this->Items($request);
229
230
        return $this->customise(array(
231
            'Locations' => $locations,
232
        ))->renderWith('LocationXML');
233
    }
234
235
    /**
236
     * @param array $searchCriteria
237
     *
238
     * @return mixed
239
     */
240
    public function Items($searchCriteria = array())
241
    {
242
        $request = ($this->request) ? $this->request : $this->parentController->getRequest();
243
        if (empty($searchCriteria)) {
244
            $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...
245
        }
246
247
        $filter = array();
248
        $filterAny = array();
249
        $exclude = array();
250
251
        // only show locations marked as ShowInLocator
252
        $filter['ShowInLocator'] = 1;
253
254
        // search across all address related fields
255
        $address = ($request->getVar('Address')) ? $request->getVar('Address') : false;
256
        if ($address) {
257
            $filterAny['Address:PartialMatch'] = $address;
258
            $filterAny['Suburb:PartialMatch'] = $address;
259
            $filterAny['State:PartialMatch'] = $address;
260
            $filterAny['Postcode:PartialMatch'] = $address;
261
            $filterAny['Country:PartialMatch'] = $address;
262
        }
263
264
        $category = ($request->getVar('CategoryID')) ? $request->getVar('CategoryID') : false;
265
        if ($category) {
266
            $filter['CategoryID'] = $category;
267
        }
268
269
        $locations = Locator::locations($filter, $filterAny, $exclude);
270
271
        return $locations;
272
    }
273
274
    /**
275
     * LocationSearch form.
276
     *
277
     * Search form for locations, updates map and results list via AJAX
278
     *
279
     * @return Form
280
     */
281
    public function LocationSearch()
282
    {
283
        $fields = FieldList::create(
284
            $address = TextField::create('Address', '')
285
                ->setAttribute('placeholder', 'address or zip code')
286
        );
287
288
        $filterCategories = Locator::getPageCategories($this->ID);
289
        $allCategories = LocationCategory::get();
290
291
        if ($allCategories->Count() > 0) {
292
            $categories = ArrayList::create();
293
            if ($filterCategories->Count() > 0) {
294
                if ($filterCategories->Count() != 1) {
295
                    $categories = $filterCategories;
296
                }
297
            } else {
298
                $categories = $allCategories;
299
            }
300
301
            if ($categories->count() > 0) {
302
                $fields->push(
303
                    DropdownField::create(
304
                        'CategoryID',
305
                        '',
306
                        $categories->map()
307
                    )->setEmptyString('All Categories'));
308
            }
309
        }
310
311
        $actions = FieldList::create(
312
            FormAction::create('index', 'Search')
313
        );
314
315
        if (class_exists('BootstrapForm')) {
316
            $form = BootstrapForm::create($this, 'LocationSearch', $fields, $actions);
317
        } else {
318
            $form = Form::create($this, 'LocationSearch', $fields, $actions);
319
        }
320
321
        return $form
322
            ->setFormMethod('GET')
323
            ->setFormAction($this->Link())
324
            ->disableSecurityToken()
325
            ->loadDataFrom($this->request->getVars())
326
        ;
327
    }
328
}
329