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

Locator::getAllCategories()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 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
    /**
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
        $url = '';
187
        if (count($vars)) {
188
            $url .= '?'.http_build_query($vars);
189
        }
190
        $link = $this->Link().'xml.xml'.$url;
191
192 1
        // init map
193
        if ($locations) {
194 1
            Requirements::customScript("
195 1
                $(function($) {
196 1
                    $('#map-container').storeLocator({
197
                        ".$load."
198 1
                        dataLocation: '".$link."',
199
                        listTemplatePath: '".$listTemplatePath."',
200
                        infowindowTemplatePath: '".$infowindowTemplatePath."',
201 1
                        originMarker: true,
202
                        ".$modal.',
203
                        '.$featured.",
204
                        slideMap: false,
205
                        zoomLevel: 0,
206
                        noForm: true,
207
                        formID: 'Form_LocationSearch',
208
                        inputID: 'Form_LocationSearch_Address',
209
                        categoryID: 'Form_LocationSearch_CategoryID',
210
                        distanceAlert: -1,
211
                        ".$kilometer.'
212
                    });
213
                });
214
            ');
215
        }
216
    }
217
218
    /**
219
     * @param SS_HTTPRequest $request
220
     *
221
     * @return ViewableData_Customised
222
     */
223
    public function index(SS_HTTPRequest $request)
224
    {
225
        $locations = $this->Items($request);
226
227
        return $this->customise(array(
228
            'Locations' => $locations,
229
        ));
230
    }
231
232
    /**
233
     * Return a XML feed of all locations marked "show in locator"
234
     *
235
     * @param SS_HTTPRequest $request
236
     * @return HTMLText
237
     */
238
    public function xml(SS_HTTPRequest $request)
239
    {
240
        $locations = $this->Items($request);
241
242
        return $this->customise(array(
243
            'Locations' => $locations,
244
        ))->renderWith('LocationXML');
245
    }
246
247
    /**
248
     * @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...
249
     *
250
     * @return ArrayList
251
     */
252
    public function Items(SS_HTTPRequest $request)
253
    {
254
        $request = ($request) ? $request : $this->request;
255
256
        $filter = array();
257
        $filterAny = array();
258
        $exclude = array();
259
260
        // only show locations marked as ShowInLocator
261
        $filter['ShowInLocator'] = 1;
262
263
        // search across all address related fields
264
        $address = ($request->getVar('Address')) ? $request->getVar('Address') : false;
265
        if ($address) {
266
            $filterAny['Address:PartialMatch'] = $address;
267
            $filterAny['Suburb:PartialMatch'] = $address;
268
            $filterAny['State:PartialMatch'] = $address;
269
            $filterAny['Postcode:PartialMatch'] = $address;
270
            $filterAny['Country:PartialMatch'] = $address;
271
        }
272
273
        $category = ($request->getVar('CategoryID')) ? $request->getVar('CategoryID') : false;
274
        if ($category) {
275
            $filter['CategoryID'] = $category;
276
        }
277
278
        $locations = Locator::locations($filter, $filterAny, $exclude);
279
280
        return $locations;
281
    }
282
283
    /**
284
     * LocationSearch form.
285
     *
286
     * Search form for locations, updates map and results list via AJAX
287
     *
288
     * @return Form
289
     */
290
    public function LocationSearch()
291
    {
292
        $fields = FieldList::create(
293
            $address = TextField::create('Address', '')
294
                ->setAttribute('placeholder', 'address or zip code')
295
        );
296
297
        $filterCategories = Locator::getPageCategories($this->ID);
298
        $allCategories = Locator::getAllCategories();
299
300
        if ($allCategories->Count() > 0) {
301
            $categories = ArrayList::create();
302
            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...
303
                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...
304
                    $categories = $filterCategories;
305
                }
306
            } else {
307
                $categories = $allCategories;
308
            }
309
310
            if ($categories->count() > 0) {
311
                $fields->push(
312
                    DropdownField::create(
313
                        'CategoryID',
314
                        '',
315
                        $categories->map()
316
                    )->setEmptyString('All Categories'));
317
            }
318
        }
319
320
        $actions = FieldList::create(
321
            FormAction::create('index', 'Search')
322
        );
323
324
        if (class_exists('BootstrapForm')) {
325
            $form = BootstrapForm::create($this, 'LocationSearch', $fields, $actions);
326
        } else {
327
            $form = Form::create($this, 'LocationSearch', $fields, $actions);
328
        }
329
330
        return $form
331
            ->setFormMethod('GET')
332
            ->setFormAction($this->Link())
333
            ->disableSecurityToken()
334
            ->loadDataFrom($this->request->getVars())
335
        ;
336
    }
337
}
338