Skip to content

Commit

Permalink
PHP Location filtering
Browse files Browse the repository at this point in the history
use SilverStripe to filter locations, rather than JS script

fixes dynamic#72
  • Loading branch information
jsirish committed Apr 9, 2016
1 parent 00088f7 commit 60b409d
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 78 deletions.
6 changes: 1 addition & 5 deletions code/Location.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -170,9 +171,4 @@ public function providePermissions()
'Location_CREATE' => 'Create a Location',
);
}

public function onBeforeWrite()
{
parent::onBeforeWrite();
}
}
201 changes: 153 additions & 48 deletions code/Locator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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) {
Expand All @@ -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();
Expand All @@ -103,16 +144,18 @@ 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');
}

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';

Expand All @@ -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({
Expand All @@ -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.'
Expand All @@ -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;
}

/**
Expand All @@ -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())
;
}
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
5 changes: 3 additions & 2 deletions templates/Layout/Locator.ss
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<div class="content-container unit size3of4 lastUnit">
<h1>$Title</h1>
<% if $Content %><div class="typography">$Content</div><% end_if %>
<% if $AreLocations %>
<% if $Locations %>
<p>$Locations.Count locations</p>
<div id="form-container">
$LocationSearch
</div>
Expand All @@ -16,7 +17,7 @@
</div>
<% else %>
<div id="no-locals">
<h3>Sorry, there are no locations at this time. Please check back later.</h3>
<p>No locations match your search criteria. Please refine your search and try again.</p>
</div>
<% end_if %>
</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/LocationXML.ss
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<markers>
<% loop Locations %><marker name="$Title.XML" lat="$Lat.XML" lng="$Lng.XML" category="$Category.Name.XML" address="$Address.XML" address2="" city="$Suburb.XML" state="$State.XML" postal="$Postcode.XML" phone="$Phone.XML" web="$Website.XML" email="$Email.XML" featured="$Featured.NiceAsBoolean.XML" /><% end_loop %>
<% loop $Locations %><marker name="$Title.XML" lat="$Lat.XML" lng="$Lng.XML" category="$Category.Name.XML" address="$Address.XML" address2="" city="$Suburb.XML" state="$State.XML" postal="$Postcode.XML" phone="$Phone.XML" web="$Website.XML" email="$Email.XML" featured="$Featured.NiceAsBoolean.XML" /><% end_loop %>
</markers>
10 changes: 4 additions & 6 deletions templates/location-list-description.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@
{{#if phone}}<div class="loc-phone">{{phone}}</div>{{/if}}
{{#if web}}<div class="loc-web"><a href="http://{{web}}" target="_blank">Website</a></div>{{/if}}
{{#if email}}<div class="loc-email"><a href="mailto:{{email}}">Email</a></div>{{/if}}
{{#if distance}}
<div class="loc-dist">
{{distance}} {{length}} |
<a href="http://maps.google.com/maps?saddr={{origin}}&amp;daddr={{address}} {{address2}} {{city}}, {{state}} {{postal}}" target="_blank">Directions</a>
</div>
{{/if}}
<div class="loc-dist">
{{#if distance}}{{distance}} {{length}} |{{/if}}
<a href="http://maps.google.com/maps?saddr={{origin}}&amp;daddr={{address}} {{address2}} {{city}}, {{state}} {{postal}}" target="_blank">Directions</a>
</div>
</div>
</div>
</li>
Expand Down
12 changes: 8 additions & 4 deletions tests/LocationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public function testFieldLabels()
'Category' => 'Category',
'ShowInLocator.NiceAsBoolean' => 'Show',
'Category.Name' => 'Category',
'Category.ID' => 'Category',
'Featured.NiceAsBoolean' => 'Featured',
'Coords' => 'Coords',
);
Expand Down Expand Up @@ -110,9 +111,12 @@ public function testCanCreate()

public function testProvidePermissions()
{
}

public function testOnBeforeWrite()
{
$object = Location::create();
$expected = array(
'Location_EDIT' => 'Edit a Location',
'Location_DELETE' => 'Delete a Location',
'Location_CREATE' => 'Create a Location',
);
$this->assertEquals($expected, $object->providePermissions());
}
}
Loading

0 comments on commit 60b409d

Please sign in to comment.