From 96ebf041d3cc98deb11f00098ced0482c02dd649 Mon Sep 17 00:00:00 2001 From: Jason Irish Date: Fri, 8 Apr 2016 17:45:05 -0500 Subject: [PATCH] PHP Location filtering use SilverStripe to filter locations, rather than JS script fixes #72 --- code/Location.php | 23 ++++++ code/Locator.php | 158 ++++++++++++++++++++++++++++-------- templates/Layout/Locator.ss | 1 + tests/LocationTest.php | 1 + tests/LocatorTest.php | 2 +- 5 files changed, 152 insertions(+), 33 deletions(-) diff --git a/code/Location.php b/code/Location.php index 6d715be..26dbf60 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'; @@ -137,6 +138,28 @@ public function EmailAddress() return false; } + public function getCustomSearchContext() + { + $fields = $this->scaffoldSearchFields(array( + 'restrictFields' => array('Address', 'Category.ID'), + )); + + $filters = array( + 'Address' => new PartialMatchFilter('Address'), + 'Suburb' => new PartialMatchFilter('Suburb'), + 'State' => new PartialMatchFilter('State'), + 'Postcode' => new PartialMatchFilter('Postcode'), + 'Country' => new PartialMatchFilter('Postcode'), + 'CategoryID' => new ExactMatchFilter('CategoryID'), + ); + + return new SearchContext( + $this->class, + $fields, + $filters + ); + } + /** * @param Member $member * diff --git a/code/Locator.php b/code/Locator.php index 64812a4..63d8754 100644 --- a/code/Locator.php +++ b/code/Locator.php @@ -86,12 +86,42 @@ public static function getPageCategories($id = null) return false; } + + public static function locations( + $filter = array(), + $filterAny = array(), + $exclude = array(), + $filterByCallback = null + ) { + $locationsList = ArrayList::create(); + + $locations = Location::get()->filter($filter); + + 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; + } } class Locator_Controller extends Page_Controller { // allowed actions - private static $allowed_actions = array('xml'); + private static $allowed_actions = array( + 'xml', + ); // Set Requirements based on input from CMS public function init() @@ -137,7 +167,14 @@ 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']); + $url = ''; + if (count($vars)) { + $url .= '?'.http_build_query($vars); + } + $link = $this->Link().'xml.xml'.$url; // init map if (Locator::getLocations()) { @@ -154,9 +191,10 @@ public function init() slideMap: false, zoomLevel: 0, distanceAlert: 120, + noForm: true, formID: 'Form_LocationSearch', - inputID: 'Form_LocationSearch_address', - categoryID: 'Form_LocationSearch_category', + inputID: 'Form_LocationSearch_Address', + categoryID: 'Form_LocationSearch_CategoryID', distanceAlert: -1, ".$kilometer.' }); @@ -166,34 +204,71 @@ 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 mixed + */ + public function Items($searchCriteria = array()) + { + $request = ($this->request) ? $this->request : $this->parentController->getRequest(); + if (empty($searchCriteria)) { + $searchCriteria = $request->requestVars(); + } + $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) { + $filterAny['Address:PartialMatch'] = $address; + $filterAny['Suburb:PartialMatch'] = $address; + $filterAny['State:PartialMatch'] = $address; + $filterAny['Postcode:PartialMatch'] = $address; + $filterAny['Country:PartialMatch'] = $address; } - $Locations = Locator::getLocations($filter, $exclude, $filterAny); + $category = ($request->getVar('CategoryID')) ? $request->getVar('CategoryID') : false; + if ($category) { + $filter['CategoryID'] = $category; + } - return $this->customise(array( - 'Locations' => $Locations, - ))->renderWith('LocationXML'); + $locations = Locator::locations($filter, $filterAny, $exclude); + + return $locations; } /** @@ -206,29 +281,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 = LocationCategory::get(); + + 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/templates/Layout/Locator.ss b/templates/Layout/Locator.ss index f60d03b..2656c83 100644 --- a/templates/Layout/Locator.ss +++ b/templates/Layout/Locator.ss @@ -1,6 +1,7 @@

$Title

<% if $Content %>
$Content
<% end_if %> +

$Locations.Count locations

<% if $AreLocations %>
$LocationSearch diff --git a/tests/LocationTest.php b/tests/LocationTest.php index b0b1b31..41ab656 100644 --- a/tests/LocationTest.php +++ b/tests/LocationTest.php @@ -35,6 +35,7 @@ public function testFieldLabels() 'Category' => 'Category', 'ShowInLocator.NiceAsBoolean' => 'Show', 'Category.Name' => 'Category', + 'Category.ID' => 'Category', 'Featured.NiceAsBoolean' => 'Featured', 'Coords' => 'Coords', ); diff --git a/tests/LocatorTest.php b/tests/LocatorTest.php index 4858ae9..9d0d500 100644 --- a/tests/LocatorTest.php +++ b/tests/LocatorTest.php @@ -64,6 +64,6 @@ public function testLocationSearch() $form = $object->LocationSearch(); $fields = $form->Fields(); - $this->assertNotNull($fields->fieldByName('category')); + $this->assertNotNull($fields->fieldByName('CategoryID')); } }