diff --git a/code/Location.php b/code/Location.php index 6d715be..a52395b 100644 --- a/code/Location.php +++ b/code/Location.php @@ -79,6 +79,7 @@ public function fieldLabels($includerelations = true) $labels['ShowInLocator'] = 'Show'; $labels['ShowInLocator.NiceAsBoolean'] = 'Show'; $labels['Category.Name'] = 'Category'; + $labels['Category.ID'] = 'Category'; $labels['Email'] = 'Email'; $labels['Featured.NiceAsBoolean'] = 'Featured'; $labels['Coords'] = 'Coords'; @@ -170,9 +171,4 @@ public function providePermissions() 'Location_CREATE' => 'Create a Location', ); } - - public function onBeforeWrite() - { - parent::onBeforeWrite(); - } } diff --git a/code/Locator.php b/code/Locator.php index 64812a4..a6ac3db 100644 --- a/code/Locator.php +++ b/code/Locator.php @@ -20,6 +20,9 @@ class Locator extends Page private static $plural_name = 'Locators'; private static $description = 'Find locations on a map'; + /** + * @return FieldList + */ public function getCMSFields() { $fields = parent::getCMSFields(); @@ -54,26 +57,56 @@ public function getCMSFields() return $fields; } - public static function getLocations($filter = array(), $exclude = array(), $filterAny = array()) - { - $filter['ShowInLocator'] = true; - $exclude['Lat'] = 0; + /** + * @param array $filter + * @param array $filterAny + * @param array $exclude + * @param null $filterByCallback + * @return ArrayList + */ + public static function locations( + $filter = array(), + $filterAny = array(), + $exclude = array(), + $filterByCallback = null + ) { + $locationsList = ArrayList::create(); - $Locations = Location::get()->exclude($exclude)->filter($filter)->filterAny($filterAny); + // filter by ShowInLocator + $filter['ShowInLocator'] = 1; - return $Locations; - } + $locations = Location::get()->filter($filter); - public function getAreLocations() - { - return self::getLocations(); + if (!empty($filterAny)) { + $locations = $locations->filterAny($filterAny); + } + if (!empty($exclude)) { + $locations = $locations->exclude($exclude); + } + + if ($filterByCallback !== null && is_callable($filterByCallback)) { + $locations = $locations->filterByCallback($filterByCallback); + } + + if ($locations->exists()) { + $locationsList->merge($locations); + } + + return $locationsList; } - public function getAllCategories() + /** + * @return DataList + */ + public static function getAllCategories() { return LocationCategory::get(); } + /** + * @param null $id + * @return bool + */ public static function getPageCategories($id = null) { if ($id) { @@ -86,14 +119,22 @@ public static function getPageCategories($id = null) return false; } + + } class Locator_Controller extends Page_Controller { - // allowed actions - private static $allowed_actions = array('xml'); + /** + * @var array + */ + private static $allowed_actions = array( + 'xml', + ); - // Set Requirements based on input from CMS + /** + * Set Requirements based on input from CMS + */ public function init() { parent::init(); @@ -103,8 +144,10 @@ public function init() // google maps api key $key = Config::inst()->get('GoogleGeocoding', 'google_api_key'); + $locations = $this->Items($this->request); + Requirements::javascript('framework/thirdparty/jquery/jquery.js'); - if (Locator::getLocations()) { + if ($locations) { Requirements::javascript('http://maps.google.com/maps/api/js?key='.$key); Requirements::javascript('locator/thirdparty/handlebars/handlebars-v1.3.0.js'); Requirements::javascript('locator/thirdparty/jquery-store-locator/js/jquery.storelocator.js'); @@ -112,7 +155,7 @@ public function init() Requirements::css('locator/css/map.css'); - $featured = (Locator::getLocations(array('Featured' => 1))->count() > 0) ? + $featured = ($locations->filter(array('Featured' => 1))->count() > 0) ? 'featuredLocations: true' : 'featuredLocations: false'; @@ -137,10 +180,18 @@ public function init() $kilometer = ($this->data()->Unit == 'km') ? 'lengthUnit: "km"' : 'lengthUnit: "m"'; - $link = $this->Link().'xml.xml'; + // pass GET variables to xml action + $vars = $this->request->getVars(); + unset($vars['url']); + unset($vars['action_index']); + $url = ''; + if (count($vars)) { + $url .= '?'.http_build_query($vars); + } + $link = $this->Link().'xml.xml'.$url; // init map - if (Locator::getLocations()) { + if ($locations) { Requirements::customScript(" $(function($) { $('#map-container').storeLocator({ @@ -153,9 +204,9 @@ public function init() '.$featured.", slideMap: false, zoomLevel: 0, - distanceAlert: 120, + noForm: true, formID: 'Form_LocationSearch', - inputID: 'Form_LocationSearch_address', + inputID: 'Form_LocationSearch_Address', categoryID: 'Form_LocationSearch_category', distanceAlert: -1, ".$kilometer.' @@ -166,34 +217,69 @@ public function init() } /** - * Find all locations for map. - * - * Will return a XML feed of all locations marked "show in locator". + * @param SS_HTTPRequest $request * - * @return XML file + * @return ViewableData_Customised + */ + public function index(SS_HTTPRequest $request) + { + $locations = $this->Items($request); + + return $this->customise(array( + 'Locations' => $locations, + )); + } + + /** + * Return a XML feed of all locations marked "show in locator" * - * @todo rename/refactor to allow for json/xml - * @todo allow $filter to run off of getVars key/val pair + * @param SS_HTTPRequest $request + * @return HTMLText */ public function xml(SS_HTTPRequest $request) { + $locations = $this->Items($request); + + return $this->customise(array( + 'Locations' => $locations, + ))->renderWith('LocationXML'); + } + + /** + * @param array $searchCriteria + * + * @return ArrayList + */ + public function Items(SS_HTTPRequest $request) + { + $request = ($request) ? $request : $this->request; + $filter = array(); - $exclude = array(); $filterAny = array(); + $exclude = array(); - //if a category filter selected - if ($this->Categories()->exists()) { - $categories = $this->Categories(); - foreach ($categories as $category) { - $filterAny['CategoryID'] = $category->ID; - } + // only show locations marked as ShowInLocator + $filter['ShowInLocator'] = 1; + + // search across all address related fields + $address = ($request->getVar('Address')) ? $request->getVar('Address') : false; + if ($address && $this->data()->AutoGeocode == 0) { + $filterAny['Suburb:PartialMatch'] = $address; + $filterAny['State:PartialMatch'] = $address; + $filterAny['Postcode:PartialMatch'] = $address; + $filterAny['Country:PartialMatch'] = $address; + } else { + unset($filter['Address']); + } + + $category = ($request->getVar('CategoryID')) ? $request->getVar('CategoryID') : false; + if ($category) { + $filter['CategoryID:ExactMatch'] = $category; } - $Locations = Locator::getLocations($filter, $exclude, $filterAny); + $locations = Locator::locations($filter, $filterAny, $exclude); - return $this->customise(array( - 'Locations' => $Locations, - ))->renderWith('LocationXML'); + return $locations; } /** @@ -206,29 +292,48 @@ public function xml(SS_HTTPRequest $request) public function LocationSearch() { $fields = FieldList::create( - $address = TextField::create('address', '') + $address = TextField::create('Address', '') + ->setAttribute('placeholder', 'address or zip code') ); - $address->setAttribute('placeholder', 'address or zip code'); - - $locatorCategories = Locator::getPageCategories($this->ID); - if (LocationCategory::get()->Count() > 0 && $locatorCategories && $locatorCategories->Count() != 1) { - $categories = LocationCategory::get(); + $filterCategories = Locator::getPageCategories($this->ID); + $allCategories = Locator::getAllCategories(); + + if ($allCategories->Count() > 0) { + $categories = ArrayList::create(); + if ($filterCategories->Count() > 0) { + if ($filterCategories->Count() != 1) { + $categories = $filterCategories; + } + } else { + $categories = $allCategories; + } if ($categories->count() > 0) { $fields->push( DropdownField::create( - 'category', + 'CategoryID', '', - $categories->map('Title', 'Title') - )->setEmptyString('Select Category')); + $categories->map() + )->setEmptyString('All Categories')); } } $actions = FieldList::create( - FormAction::create('', 'Search') + FormAction::create('index', 'Search') ); - return Form::create($this, 'LocationSearch', $fields, $actions); + if (class_exists('BootstrapForm')) { + $form = BootstrapForm::create($this, 'LocationSearch', $fields, $actions); + } else { + $form = Form::create($this, 'LocationSearch', $fields, $actions); + } + + return $form + ->setFormMethod('GET') + ->setFormAction($this->Link()) + ->disableSecurityToken() + ->loadDataFrom($this->request->getVars()) + ; } } diff --git a/composer.json b/composer.json index e667e57..220a23d 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "silverstripe-australia/addressable": "^1.1" }, "suggest": { - "unclecheese/betterbuttons": "Adds new form actions and buttons to GridField detail form for usability enhancements." + "unclecheese/betterbuttons": "Adds new form actions and buttons to GridField detail form for usability enhancements.", + "unclecheese/bootstrap-forms": "Allows the creation of forms compatible with the Twitter Bootstrap CSS framework in SilverStripe." }, "extra": { "installer-name": "locator" diff --git a/templates/Layout/Locator.ss b/templates/Layout/Locator.ss index f60d03b..03f9c8f 100644 --- a/templates/Layout/Locator.ss +++ b/templates/Layout/Locator.ss @@ -1,7 +1,8 @@
$Locations.Count locations
No locations match your search criteria. Please refine your search and try again.