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

Locator::locations()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 30
ccs 0
cts 16
cp 0
rs 8.439
cc 6
eloc 17
nc 16
nop 4
crap 42
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
    /**
24 1
     * @return FieldList
25 1
     */
26 1
    public function getCMSFields()
27
    {
28
        $fields = parent::getCMSFields();
29 1
30 1
        // Settings
31
        $fields->addFieldsToTab('Root.Settings', array(
32
            HeaderField::create('DisplayOptions', 'Display Options', 3),
33 1
            OptionsetField::create('Unit', 'Unit of measure', array('m' => 'Miles', 'km' => 'Kilometers')),
34 1
            CheckboxField::create('AutoGeocode', 'Auto Geocode - Automatically filter map results based on user location')
35 1
                ->setDescription('Note: if any locations are set as featured, the auto geocode is automatically disabled.'),
36 1
            CheckboxField::create('ModalWindow', 'Modal Window - Show Map results in a modal window'),
37 1
        ));
38 1
39 1
        // Filter categories
40
        $config = GridFieldConfig_RelationEditor::create();
41 1
        if (class_exists('GridFieldAddExistingSearchButton')) {
42
            $config->removeComponentsByType('GridFieldAddExistingAutocompleter');
43 1
            $config->addComponent(new GridFieldAddExistingSearchButton());
44
        }
45
        $categories = $this->Categories();
46 3
        $categoriesField = GridField::create('Categories', 'Categories', $categories, $config)
47
            ->setDescription('only show locations from the selected category');
48 3
49
            // Filter
50 3
            $fields->addFieldsToTab('Root.Filter', array(
51 3
                HeaderField::create('CategoryOptionsHeader', 'Location Filtering', 3),
52 3
                $categoriesField,
53 3
            ));
54
55
        $this->extend('updateCMSFields', $fields);
56 1
57
        return $fields;
58 1
    }
59
60
    /**
61 1
     * @param array $filter
62
     * @param array $filterAny
63 1
     * @param array $exclude
64
     * @param null $filterByCallback
65
     * @return ArrayList
66
     */
67
    public static function locations(
68
        $filter = array(),
69
        $filterAny = array(),
70
        $exclude = array(),
71
        $filterByCallback = null
72
    ) {
73
        $locationsList = ArrayList::create();
74
75
        // filter by ShowInLocator
76
        $filter['ShowInLocator'] = 1;
77
78
        $locations = Location::get()->filter($filter);
79
80
        if (!empty($filterAny)) {
81
            $locations = $locations->filterAny($filterAny);
82
        }
83
        if (!empty($exclude)) {
84
            $locations = $locations->exclude($exclude);
85
        }
86
87
        if ($filterByCallback !== null && is_callable($filterByCallback)) {
88
            $locations = $locations->filterByCallback($filterByCallback);
89
        }
90
91
        if ($locations->exists()) {
92
            $locationsList->merge($locations);
93
        }
94
95
        return $locationsList;
96
    }
97
98
    /**
99
     * @return DataList
100
     */
101
    public static function getAllCategories()
102
    {
103
        return LocationCategory::get();
104
    }
105
106
    /**
107
     * @param null $id
108
     * @return bool
109
     */
110
    public static function getPageCategories($id = null)
111
    {
112
        if ($id) {
113
            if ($locator = self::get()->byID($id)) {
114
                return $locator->Categories();
115
            }
116
117
            return false;
118
        }
119
120
        return false;
121
    }
122
123
124
}
125
126
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...
127
{
128
    /**
129
     * @var array
130
     */
131
    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...
132
        'xml',
133
    );
134
135
    /**
136
     * Set Requirements based on input from CMS
137
     */
138
    public function init()
139
    {
140
        parent::init();
141
142
        $themeDir = SSViewer::get_theme_folder();
143
144
        // google maps api key
145
        $key = Config::inst()->get('GoogleGeocoding', 'google_api_key');
146
147
        $locations = $this->Items($this->request);
148
149
        Requirements::javascript('framework/thirdparty/jquery/jquery.js');
150
        if ($locations) {
151
            Requirements::javascript('http://maps.google.com/maps/api/js?key='.$key);
152
            Requirements::javascript('locator/thirdparty/handlebars/handlebars-v1.3.0.js');
153
            Requirements::javascript('locator/thirdparty/jquery-store-locator/js/jquery.storelocator.js');
154
        }
155
156
        Requirements::css('locator/css/map.css');
157
158
        $featured = ($locations->filter(array('Featured' => 1))->count() > 0) ?
159
            'featuredLocations: true' :
160
            'featuredLocations: false';
161
162
        // map config based on user input in Settings tab
163
        // AutoGeocode or Full Map
164
        $load = ($this->data()->AutoGeocode) ?
165
            'autoGeocode: true, fullMapStart: false,' :
166
            'autoGeocode: false, fullMapStart: true, storeLimit: 1000, maxDistance: true,';
167
168 1
        $base = Director::baseFolder();
169
        $themePath = $base.'/'.$themeDir;
170 1
171 1
        $listTemplatePath = (file_exists($themePath.'/templates/location-list-description.html')) ?
172 1
            $themeDir.'/templates/location-list-description.html' :
173 1
            'locator/templates/location-list-description.html';
174
        $infowindowTemplatePath = (file_exists($themePath.'/templates/infowindow-description.html')) ?
175 1
            $themeDir.'/templates/infowindow-description.html' :
176 1
            'locator/templates/infowindow-description.html';
177 1
178 1
        // in page or modal
179
        $modal = ($this->data()->ModalWindow) ? 'modalWindow: true' : 'modalWindow: false';
180 1
181
        $kilometer = ($this->data()->Unit == 'km') ? 'lengthUnit: "km"' : 'lengthUnit: "m"';
182 1
183
        // pass GET variables to xml action
184 1
        $vars = $this->request->getVars();
185
        unset($vars['url']);
186
        unset($vars['action_index']);
187
        $url = '';
188
        if (count($vars)) {
189
            $url .= '?'.http_build_query($vars);
190
        }
191
        $link = $this->Link().'xml.xml'.$url;
192 1
193
        // init map
194 1
        if ($locations) {
195 1
            Requirements::customScript("
196 1
                $(function($) {
197
                    $('#map-container').storeLocator({
198 1
                        ".$load."
199
                        dataLocation: '".$link."',
200
                        listTemplatePath: '".$listTemplatePath."',
201 1
                        infowindowTemplatePath: '".$infowindowTemplatePath."',
202
                        originMarker: true,
203
                        ".$modal.',
204
                        '.$featured.",
205
                        slideMap: false,
206
                        zoomLevel: 0,
207
                        noForm: true,
208
                        formID: 'Form_LocationSearch',
209
                        inputID: 'Form_LocationSearch_Address',
210
                        categoryID: 'Form_LocationSearch_category',
211
                        distanceAlert: -1,
212
                        ".$kilometer.'
213
                    });
214
                });
215
            ');
216
        }
217
    }
218
219
    /**
220
     * @param SS_HTTPRequest $request
221
     *
222
     * @return ViewableData_Customised
223
     */
224
    public function index(SS_HTTPRequest $request)
225
    {
226
        $locations = $this->Items($request);
227
228
        return $this->customise(array(
229
            'Locations' => $locations,
230
        ));
231
    }
232
233
    /**
234
     * Return a XML feed of all locations marked "show in locator"
235
     *
236
     * @param SS_HTTPRequest $request
237
     * @return HTMLText
238
     */
239
    public function xml(SS_HTTPRequest $request)
240
    {
241
        $locations = $this->Items($request);
242
243
        return $this->customise(array(
244
            'Locations' => $locations,
245
        ))->renderWith('LocationXML');
246
    }
247
248
    /**
249
     * @param array $searchCriteria
0 ignored issues
show
Bug introduced by
There is no parameter named $searchCriteria. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
250
     *
251
     * @return ArrayList
252
     */
253
    public function Items(SS_HTTPRequest $request)
254
    {
255
        $request = ($request) ? $request : $this->request;
256
257
        $filter = array();
258
        $filterAny = array();
259
        $exclude = array();
260
261
        // only show locations marked as ShowInLocator
262
        $filter['ShowInLocator'] = 1;
263
264
        // search across all address related fields
265
        $address = ($request->getVar('Address')) ? $request->getVar('Address') : false;
266
        if ($address && $this->data()->AutoGeocode == 0) {
267
            $filterAny['Suburb:PartialMatch'] = $address;
268
            $filterAny['State:PartialMatch'] = $address;
269
            $filterAny['Postcode:PartialMatch'] = $address;
270
            $filterAny['Country:PartialMatch'] = $address;
271
        } else {
272
            unset($filter['Address']);
273
        }
274
275
        $category = ($request->getVar('CategoryID')) ? $request->getVar('CategoryID') : false;
276
        if ($category) {
277
            $filter['CategoryID:ExactMatch'] = $category;
278
        }
279
280
        $locations = Locator::locations($filter, $filterAny, $exclude);
281
282
        return $locations;
283
    }
284
285
    /**
286
     * LocationSearch form.
287
     *
288
     * Search form for locations, updates map and results list via AJAX
289
     *
290
     * @return Form
291
     */
292
    public function LocationSearch()
293
    {
294
        $fields = FieldList::create(
295
            $address = TextField::create('Address', '')
296
                ->setAttribute('placeholder', 'address or zip code')
297
        );
298
299
        $filterCategories = Locator::getPageCategories($this->ID);
300
        $allCategories = Locator::getAllCategories();
301
302
        if ($allCategories->Count() > 0) {
303
            $categories = ArrayList::create();
304
            if ($filterCategories->Count() > 0) {
0 ignored issues
show
Bug introduced by
The method Count cannot be called on $filterCategories (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
305
                if ($filterCategories->Count() != 1) {
0 ignored issues
show
Bug introduced by
The method Count cannot be called on $filterCategories (of type boolean).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
306
                    $categories = $filterCategories;
307
                }
308
            } else {
309
                $categories = $allCategories;
310
            }
311
312
            if ($categories->count() > 0) {
313
                $fields->push(
314
                    DropdownField::create(
315
                        'CategoryID',
316
                        '',
317
                        $categories->map()
318
                    )->setEmptyString('All Categories'));
319
            }
320
        }
321
322
        $actions = FieldList::create(
323
            FormAction::create('index', 'Search')
324
        );
325
326
        if (class_exists('BootstrapForm')) {
327
            $form = BootstrapForm::create($this, 'LocationSearch', $fields, $actions);
328
        } else {
329
            $form = Form::create($this, 'LocationSearch', $fields, $actions);
330
        }
331
332
        return $form
333
            ->setFormMethod('GET')
334
            ->setFormAction($this->Link())
335
            ->disableSecurityToken()
336
            ->loadDataFrom($this->request->getVars())
337
        ;
338
    }
339
}
340