diff --git a/assets/addresslocationfield.publish.css b/assets/addresslocationfield.publish.css
index c711dc1..531a8eb 100644
--- a/assets/addresslocationfield.publish.css
+++ b/assets/addresslocationfield.publish.css
@@ -1,83 +1,93 @@
-div.field-addresslocation {
- clear: both;
- padding-bottom: 1em;
- border-bottom: 1px solid #ddc;
-}
-div.field-addresslocation:after {
- content: ".";
- display: block;
- height: 0;
- clear: both;
- visibility: hidden;
-}
div.field-addresslocation p {
- border-bottom: 1px solid #ddc;
- padding-bottom: 0.3em;
- margin-bottom: 1em;
- margin-top: 1.5em;
+ color: #2f77eb;
+ margin: 0 0 1.5rem;
}
+
div.field-addresslocation label {
- float: left;
- margin-bottom: 0.5em;
- width: 47%;
- margin-right: 3%;
-}
-div.field-addresslocation label.street {
- width: 97%;
+ box-sizing: border-box;
+ margin: 0 0 3rem;
+ padding-right: 3rem;
+ width: 50%;
}
-div.field-addresslocation label.street,
-div.field-addresslocation label.region,
-div.field-addresslocation label.latitude,
-div.field-addresslocation label.country {
-}
-div.field-addresslocation label.country {
+
+@media (max-width: 767px) {
+ div.field-addresslocation label {
+ width: 100%;
+ }
}
-div.field-addresslocation label.city,
-div.field-addresslocation label.postal-code,
-div.field-addresslocation label.longitude {
+
+div.field-addresslocation label.street {
+ width: 100%;
}
+
div.field-addresslocation label.latitude input,
div.field-addresslocation label.longitude input {
color: #7F7F7F;
}
+
div.field-addresslocation label input {
clear: both;
}
-div.field-addresslocation label.locate {
+
+div.field-addresslocation div.locate {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content: flex-start;
+ margin: 0 0 2em;
width: 100%;
- margin-top: 1em;
}
-div.field-addresslocation label.locate a.mapswitch {
+
+div.field-addresslocation div.locate a.mapswitch {
float: right;
text-decoration: none;
}
-div.field-addresslocation label.locate input {
- float: left;
- width: 47%;
- clear: none;
- margin-right: 3%;
+
+div.field-addresslocation div.locate input {
+ color: #fff;
+ font-size: 1.1rem;
+ text-transform: uppercase;
+ line-height: 1.6rem;
+ margin: 0 1rem 0 0;
+ padding: 1rem 1.5rem;
+ border-radius: 5px;
+ border: none;
+ background: #2f77eb;
+ width: auto;
+ cursor: pointer;
}
-div.field-addresslocation div.main {
- width: 60%;
- float: left;
+div.field-addresslocation div.locate input:not(:disabled):hover {
+ background: #121212;
}
-div.field-addresslocation div.main.map {
- float: right;
- height: 220px;
- width: 40%;
+
+div.field-addresslocation div.locate input:disabled {
+ opacity: 0.5;
+ pointer-events: none;
}
-div.field-addresslocation div.sidebar {
- width: 100%;
- float:left;
+div.field-addresslocation div.main-wrapper {
+ border-radius: 5px;
+ -webkit-border-radius: 5px;
+ margin: 0 0 3rem;
+ padding: 1.5rem;
+ border: 1px solid #d3dce2;
+}
+
+div.field-addresslocation div.address {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ justify-content: flex-start;
+ flex-wrap: wrap;
+ width: calc(100% + 3rem);
}
-div.field-addresslocation div.sidebar.map {
+
+div.field-addresslocation div.map {
width: 100%;
- margin-top: 15px;
height: 200px;
- float: left;
}
+
div.field-addresslocation div.gm-style-cc {
display: none;
}
diff --git a/assets/addresslocationfield.publish.js b/assets/addresslocationfield.publish.js
index 86244ba..2da6cd2 100755
--- a/assets/addresslocationfield.publish.js
+++ b/assets/addresslocationfield.publish.js
@@ -39,13 +39,13 @@
map.setCenter(latlng);
//map.setZoom(16);
SetMarker(latlng);
- helpers.toggleFieldState(field.find('label.locate input[name="locate"]'), true);
+ helpers.toggleFieldState(field.find('div.locate input[name="locate"]'), true);
}
else{
- helpers.toggleFieldState(field.find('label.locate input[name="clear"]'), true);
+ helpers.toggleFieldState(field.find('div.locate input[name="clear"]'), true);
}
- field.find('label.locate input[name="clear"]').click(function(ev){
+ field.find('div.locate input[name="clear"]').click(function(ev){
ev.preventDefault();
@@ -57,16 +57,15 @@
map.setCenter(new google.maps.LatLng(0,0));
map.setZoom(1);
- field.find('label.locate input[name="locate"]').removeAttr('disabled');
+ field.find('div.locate input[name="locate"]').removeAttr('disabled');
});
if(field.find('div.address').hasClass('sidebar')){
- var a = $('[-] Hide Map').appendTo('label.locate')
+ var a = $('[-] Hide Map').appendTo('div.locate')
- field.delegate('label.locate a.mapswitch', 'click', function(ev){
- console.log('clicked');
+ field.delegate('div.locate a.mapswitch', 'click', function(ev){
ev.preventDefault();
var map = field.find('div.map');
if(map.hasClass('open')){
@@ -81,7 +80,7 @@
}
- field.find('label.locate input[name="locate"]').click(function(ev){
+ field.find('div.locate input[name="locate"]').click(function(ev){
//Reassign field to stop mime warning/error
var field = $('div.field-addresslocation');
@@ -116,7 +115,7 @@
});
field.on('focus', 'input[type=text]', function(ev){
- var $btn = field.find('label.locate input[name="locate"]')
+ var $btn = field.find('div.locate input[name="locate"]')
if ($btn.attr('disabled')) {
helpers.toggleFieldState($btn);
}
@@ -125,7 +124,6 @@
}
function GeocodeAddress(address, success, fail){
geocoder.geocode({"address":address}, function(results, status){
- console.log(status, results);
if(status == google.maps.GeocoderStatus.OK){
success(results[0]);
}else{
diff --git a/extension.driver.php b/extension.driver.php
index fe11773..f31bc10 100755
--- a/extension.driver.php
+++ b/extension.driver.php
@@ -27,21 +27,30 @@ public function addCustomPreferenceFieldsets($context) {
public function uninstall()
{
- Symphony::Database()->query("DROP TABLE `tbl_fields_addresslocation`");
+ return Symphony::Database()
+ ->drop('tbl_fields_addresslocation')
+ ->ifExists()
+ ->execute()
+ ->success();
}
public function update($previousVersion = false){
- $addresslocation_entry_tables = Symphony::Database()->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_addresslocation`");
+ $addresslocation_entry_tables = Symphony::Database()
+ ->select(['field_id'])
+ ->from('tbl_fields_addresslocation')
+ ->execute()
+ ->column('field_id');
if(version_compare($previousVersion, '1.2.1', '<')){
if(is_array($addresslocation_entry_tables) && !empty($addresslocation_entry_tables))
{
foreach($addresslocation_entry_tables as $field)
{
- Symphony::Database()->query(sprintf(
- "ALTER TABLE `tbl_entries_data_%d` ADD `result_data` blob",
- $field
- ));
+ Symphony::Database()
+ ->alter("tbl_entries_data_$field")
+ ->add(['result_data' => 'blob'])
+ ->execute()
+ ->success();
}
}
}
@@ -51,23 +60,28 @@ public function update($previousVersion = false){
{
foreach($addresslocation_entry_tables as $field)
{
- Symphony::Database()->query(sprintf(
- "ALTER TABLE `tbl_entries_data_%d` ADD `neighborhood` varchar(255), ADD `neighborhood_handle` varchar(255)",
- $field
- ));
+ Symphony::Database()
+ ->alter("tbl_entries_data_$field")
+ ->add([
+ 'neighborhood' => 'varchar(255)',
+ 'neighborhood_handle' => 'varchar(255)',
+ ])
+ ->execute()
+ ->success();
}
}
}
-
+
if(version_compare($previousVersion, '1.2.3', '<')){
if(is_array($addresslocation_entry_tables) && !empty($addresslocation_entry_tables))
{
foreach($addresslocation_entry_tables as $field)
{
- Symphony::Database()->query(sprintf(
- "ALTER TABLE `tbl_entries_data_%d` MODIFY COLUMN `result_data` blob",
- $field
- ));
+ Symphony::Dabatase()
+ ->alter("tbl_entries_data_$field")
+ ->modify(['result_data' => 'blob'])
+ ->execute()
+ ->success();
}
}
}
@@ -77,24 +91,34 @@ public function update($previousVersion = false){
public function install()
{
- return Symphony::Database()->query("CREATE TABLE `tbl_fields_addresslocation` (
- `id` int(11) unsigned NOT NULL auto_increment,
- `field_id` int(11) unsigned NOT NULL,
- `street_label` varchar(80) NOT NULL,
- `city_label` varchar(80) NOT NULL,
- `region_label` varchar(80) NOT NULL,
- `postal_code_label` varchar(80) NOT NULL,
- `country_label` varchar(80) NOT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `field_id` (`field_id`)
- ) TYPE=MyISAM");
+ return Symphony::Database()
+ ->create('tbl_fields_addresslocation')
+ ->ifNotExists()
+ ->fields([
+ 'id' => [
+ 'type' => 'int(11)',
+ 'auto' => true,
+ ],
+ 'field_id' => 'int(11)',
+ 'street_label' => 'varchar(80)',
+ 'city_label' => 'varchar(80)',
+ 'region_label' => 'varchar(80)',
+ 'postal_code_label' => 'varchar(80)',
+ 'country_label' => 'varchar(80)',
+ ])
+ ->keys([
+ 'id' => 'primary',
+ 'field_id' => 'unique',
+ ])
+ ->execute()
+ ->success();
}
/*
Modified from:
http://www.kevinbradwick.co.uk/developer/php/free-to-script-to-calculate-the-radius-of-a-coordinate-using-latitude-and-longitude
*/
- public function geoRadius($lat, $lng, $rad, $kilometers=false)
+ public function geoRadius($lat, $lng, $rad, $kilometers = false)
{
$radius = ($kilometers) ? ($rad * 0.621371192) : $rad;
@@ -106,7 +130,7 @@ public function geoRadius($lat, $lng, $rad, $kilometers=false)
(float)$latMAX = $lat + $usrRLAT;
// Longitude calculation
- (float)$mpdLON = 69.1703234283616 * cos($lat * (pi/180));
+ (float)$mpdLON = 69.1703234283616 * cos($lat * (pi()/180));
(float)$dpmLON = 1 / $mpdLON; // degrees per mile longintude
$usrRLON = $dpmLON * $radius;
@@ -145,4 +169,4 @@ public function geoDistance($lat1, $lon1, $lat2, $lon2, $unit)
}
-?>
\ No newline at end of file
+?>
diff --git a/extension.meta.xml b/extension.meta.xml
index 05acd5b..2e308b4 100644
--- a/extension.meta.xml
+++ b/extension.meta.xml
@@ -1,6 +1,6 @@
- Address Location Field
+ Field: Address Location
Geocode an address, then refine the latlng returned for precision.
https://github.com/designermonkey/addresslocationfield
http://getsymphony.com/discuss/thread/70238/
@@ -14,6 +14,10 @@
+
+ - Update for Symphony 4.x
+ - Code refactoring for Database and EQFA
+
- Add preferences UI (#22)
@@ -37,4 +41,4 @@
-
\ No newline at end of file
+
diff --git a/fields/field.addresslocation.php b/fields/field.addresslocation.php
index f342406..b305e5f 100755
--- a/fields/field.addresslocation.php
+++ b/fields/field.addresslocation.php
@@ -1,32 +1,35 @@
entryQueryFieldAdapter = new EntryQueryAddressLocationAdapter($this);
+
$this->_name = 'Address Location';
- $this->_driver = Symphony::ExtensionManager()->create('addresslocationfield');
+ $this->driver = Symphony::ExtensionManager()->create('addresslocationfield');
}
- private function __geocodeAddress($address)
+ public function geocodeAddress($address)
{
$coordinates = null;
$cache_id = md5('addresslocationfield_' . $address);
$cache = new Cacheable(Symphony::Database());
- $cachedData = $cache->check($cache_id);
+ $cachedData = $cache->read($cache_id);
// no data has been cached
if(!$cachedData) {
@@ -77,7 +80,7 @@ public function canFilter()
return true;
}
- function displaySettingsPanel(XMLElement &$wrapper, $errors = NULL)
+ function displaySettingsPanel(XMLElement &$wrapper, $errors = null)
{
parent::displaySettingsPanel($wrapper, $errors);
@@ -90,7 +93,7 @@ function displaySettingsPanel(XMLElement &$wrapper, $errors = NULL)
}
- public function processRawFieldData($data, &$status, &$message=null, $simulate=false, $entry_id=null)
+ public function processRawFieldData($data, &$status, &$message = null, $simulate = false, $entry_id = null)
{
$status = self::__OK__;
@@ -103,7 +106,7 @@ public function processRawFieldData($data, &$status, &$message=null, $simulate=f
'postal_code' => General::sanitize($data['postal_code']),
'country' => General::sanitize($data['country']),
);
- $geocoded_result = $this->__geocodeAddress(implode(',', $result));
+ $geocoded_result = $this->geocodeAddress(implode(',', $result));
$neighborhood = '';
if( is_object($geocoded_result) ) {
@@ -146,20 +149,28 @@ function commit()
if($id === false) return false;
- $fields = array(
- 'field_id' => $id,
- 'street_label' => $this->get('street_label'),
- 'city_label' => $this->get('city_label'),
- 'region_label' => $this->get('region_label'),
- 'postal_code_label' => $this->get('postal_code_label'),
- 'country_label' => $this->get('country_label')
- );
-
- Symphony::Database()->query("DELETE FROM `tbl_fields_".$this->handle()."` WHERE `field_id` = '$id' LIMIT 1");
- Symphony::Database()->insert($fields, 'tbl_fields_' . $this->handle());
+ Symphony::Database()
+ ->delete('tbl_fields_' . $this->handle())
+ ->where(['field_id' => $id])
+ ->limit(1)
+ ->execute()
+ ->success();
+
+ Symphony::database()
+ ->insert('tbl_fields_' . $this->handle())
+ ->values([
+ 'field_id' => $id,
+ 'street_label' => $this->get('street_label'),
+ 'city_label' => $this->get('city_label'),
+ 'region_label' => $this->get('region_label'),
+ 'postal_code_label' => $this->get('postal_code_label'),
+ 'country_label' => $this->get('country_label'),
+ ])
+ ->execute()
+ ->success();
}
- function displayPublishPanel(XMLElement &$wrapper, $data = NULL, $flagWithError = NULL, $fieldnamePrefix = NULL, $fieldnamePostfix = NULL, $entry_id = NULL)
+ function displayPublishPanel(XMLElement &$wrapper, $data = null, $flagWithError = null, $fieldnamePrefix = null, $fieldnamePostfix = null, $entry_id = null)
{
$key = Symphony::Configuration()->get('api_key','addresslocationfield');
if(empty($key)) {
@@ -178,11 +189,12 @@ function displayPublishPanel(XMLElement &$wrapper, $data = NULL, $flagWithError
$label = new XMLElement('p', $this->get('label'));
$label->setAttribute('class', 'title');
$wrapper->appendChild($label);
+ $wrapinner = new XMLElement('div', null, array('class' => 'main-wrapper'));
// Address Fields
$address = new XMLElement('div');
$address->setAttribute('class', 'address '.$class);
- $wrapper->appendChild($address);
+ $wrapinner->appendChild($address);
$label = Widget::Label($this->get('street_label'));
$label->setAttribute('class', 'street');
@@ -219,56 +231,78 @@ function displayPublishPanel(XMLElement &$wrapper, $data = NULL, $flagWithError
$label->appendChild(Widget::Input('fields'.$fieldnamePrefix.'['.$this->get('element_name').'][longitude]'.$fieldnamePostfix, $coordinates[1], 'text', array('readonly' => 'readonly')));
$address->appendChild($label);
- $label = Widget::Label();
- $label->setAttribute('class', 'locate');
- $label->appendChild(Widget::Input('locate', 'Geocode Address', 'button', array('class' => 'button')));
- $label->appendChild(Widget::Input('clear', 'Clear Address', 'button', array('class' => 'button')));
- $address->appendChild($label);
+ $div = new XMLElement('div');
+ $div->setAttribute('class', 'locate');
+ $div->appendChild(Widget::Input('locate', 'Geocode Address', 'button', array('class' => 'button')));
+ $div->appendChild(Widget::Input('clear', 'Clear Address', 'button', array('class' => 'button')));
+ $address->appendChild($div);
$map = new XMLElement('div');
$map->setAttribute('class', 'map '.$class.' open');
- $wrapper->appendChild($map);
+ $wrapinner->appendChild($map);
+
+ $wrapper->appendChild($wrapinner);
}
public function createTable()
{
- return Symphony::Database()->query(
- "CREATE TABLE IF NOT EXISTS `tbl_entries_data_" . $this->get('id') . "` (
- `id` int(11) unsigned NOT NULL auto_increment,
- `entry_id` int(11) unsigned NOT NULL,
- `street` varchar(255),
- `street_handle` varchar(255),
- `city` varchar(255),
- `city_handle` varchar(255),
- `region` varchar(255),
- `region_handle` varchar(255),
- `postal_code` varchar(255),
- `postal_code_handle` varchar(255),
- `country` varchar(255),
- `country_handle` varchar(255),
- `latitude` double default NULL,
- `longitude` double default NULL,
- `neighborhood` varchar(255),
- `neighborhood_handle` varchar(255),
- `result_data` blob NOT NULL,
- PRIMARY KEY (`id`),
- KEY `entry_id` (`entry_id`),
- KEY `latitude` (`latitude`),
- KEY `longitude` (`longitude`),
- INDEX `street` (`street`),
- INDEX `street_handle` (`street_handle`),
- INDEX `city` (`city`),
- INDEX `city_handle` (`city_handle`),
- INDEX `region` (`region`),
- INDEX `region_handle` (`region_handle`),
- INDEX `postal_code` (`postal_code`),
- INDEX `postal_code_handle` (`postal_code_handle`),
- INDEX `country` (`country`),
- INDEX `country_handle` (`country_handle`),
- INDEX `neighborhood` (`neighborhood`),
- INDEX `neighborhood_handle` (`neighborhood_handle`)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"
- );
+ return Symphony::Database()
+ ->create('tbl_entries_data_' . $this->get('id'))
+ ->ifNotExists()
+ ->fields([
+ 'id' => [
+ 'type' => 'int(11)',
+ 'auto' => true,
+ ],
+ 'entry_id' => 'int(11)',
+ 'street' => 'varchar(255)',
+ 'street_handle' => 'varchar(255)',
+ 'city' => 'varchar(255)',
+ 'city_handle' => 'varchar(255)',
+ 'region' => 'varchar(255)',
+ 'region_handle' => 'varchar(255)',
+ 'postal_code' => 'varchar(255)',
+ 'postal_code_handle' => 'varchar(255)',
+ 'country' => 'varchar(255)',
+ 'country_handle' => 'varchar(255)',
+ 'latitude' => [
+ 'type' => 'double',
+ 'null' => true,
+ ],
+ 'longitude' => [
+ 'type' => 'double',
+ 'null' => true,
+ ],
+ 'neighborhood' => [
+ 'type' => 'varchar(255)',
+ 'null' => true,
+ ],
+ 'neighborhood_handle' => [
+ 'type' => 'varchar(255)',
+ 'null' => true,
+ ],
+ 'result_data' => 'blob',
+ ])
+ ->keys([
+ 'id' => 'primary',
+ 'entry_id' => 'key',
+ 'latitude' => 'key',
+ 'longitude' => 'key',
+ 'street' => 'index',
+ 'street_handle' => 'index',
+ 'city' => 'index',
+ 'city_handle' => 'index',
+ 'region' => 'index',
+ 'region_handle' => 'index',
+ 'postal_code' => 'index',
+ 'postal_code_handle' => 'index',
+ 'country' => 'index',
+ 'country_handle' => 'index',
+ 'neighborhood' => 'index',
+ 'neighborhood_handle' => 'index',
+ ])
+ ->execute()
+ ->success();
}
public function convertObjectToArray($data)
@@ -321,7 +355,7 @@ public function itemsToXML($parent, $items) {
}
}
- public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = false, $mode = NULL, $entry_id = NULL)
+ public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = false, $mode = null, $entry_id = null)
{
$field = new XMLElement($this->get('element_name'), null, array(
'latitude' => $data['latitude'],
@@ -331,7 +365,7 @@ public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = fa
foreach (array('street', 'city', 'region', 'postal_code', 'country', 'neighborhood') as $name)
{
- if ($encode === TRUE){
+ if ($encode === true){
$data[$name] = General::sanitize($data[$name]);
}
$element_name = $this->get("{$name}_label");
@@ -352,17 +386,17 @@ public function appendFormattedElement(XMLElement &$wrapper, $data, $encode = fa
// Add back Google Maps result data
- if (count($this->_filter_origin['latitude']) > 0) {
+ if (!empty($this->filter_origin['latitude'])) {
$distance = new XMLElement('distance');
- $distance->setAttribute('from', $this->_filter_origin['latitude'] . ',' . $this->_filter_origin['longitude']);
- $distance->setAttribute('distance', $this->_driver->geoDistance($this->_filter_origin['latitude'], $this->_filter_origin['longitude'], $data['latitude'], $data['longitude'], $this->_filter_origin['unit']));
- $distance->setAttribute('unit', ($this->_filter_origin['unit'] == 'k') ? 'km' : 'miles');
+ $distance->setAttribute('from', $this->filter_origin['latitude'] . ',' . $this->filter_origin['longitude']);
+ $distance->setAttribute('distance', $this->driver->geoDistance($this->filter_origin['latitude'], $this->filter_origin['longitude'], $data['latitude'], $data['longitude'], $this->filter_origin['unit']));
+ $distance->setAttribute('unit', ($this->filter_origin['unit'] == 'k') ? 'km' : 'miles');
$field->appendChild($distance);
}
}
- public function prepareTableValue($data, XMLElement $link = NULL, $entry_id = NULL)
+ public function prepareTableValue($data, XMLElement $link = null, $entry_id = null)
{
if (empty($data)) return;
@@ -377,7 +411,23 @@ public function prepareTableValue($data, XMLElement $link = NULL, $entry_id = NU
return trim($string,", ");
}
- function buildDSRetrievalSQL($data, &$joins, &$where, $andOperation=false)
+ public function fetchFilterableOperators()
+ {
+ return array(
+ array(
+ 'title' => 'in',
+ 'filter' => 'in ',
+ 'help' => __('in street|city|region|postal_code|country of %s')
+ ),
+ array(
+ 'title' => 'within',
+ 'filter' => 'within ',
+ 'help' => __('Within %skm|mile|miles of %s')
+ ),
+ );
+ }
+
+ function buildDSRetrievalSQL($data, &$joins, &$where, $andOperation = false)
{
$columns_to_labels = array();
@@ -431,7 +481,7 @@ function buildDSRetrievalSQL($data, &$joins, &$where, $andOperation=false)
}
// otherwise the origin needs geocoding
else {
- $geocoded_result = $this->__geocodeAddress($origin);
+ $geocoded_result = $this->geocodeAddress($origin);
$coordinates = $geocoded_result->geometry->location;
if ($geocoded_result) {
@@ -443,12 +493,12 @@ function buildDSRetrievalSQL($data, &$joins, &$where, $andOperation=false)
// if we don't have a decent set of coordinates, we can't query
if (is_null($lat) || is_null($lng)) return true;
- $this->_filter_origin['latitude'] = $lat;
- $this->_filter_origin['longitude'] = $lng;
- $this->_filter_origin['unit'] = $unit[0];
+ $this->filter_origin['latitude'] = $lat;
+ $this->filter_origin['longitude'] = $lng;
+ $this->filter_origin['unit'] = $unit[0];
// build the bounds within the query should look
- $radius = $this->_driver->geoRadius($lat, $lng, $radius, ($unit[0] == 'k'));
+ $radius = $this->driver->geoRadius($lat, $lng, $radius, ($unit[0] == 'k'));
$where .= sprintf(
" AND `t%d`.`latitude` BETWEEN %s AND %s AND `t%d`.`longitude` BETWEEN %s AND %s",
diff --git a/lib/class.entryqueryaddresslocationadapter.php b/lib/class.entryqueryaddresslocationadapter.php
new file mode 100644
index 0000000..c9efbb3
--- /dev/null
+++ b/lib/class.entryqueryaddresslocationadapter.php
@@ -0,0 +1,120 @@
+field->get('id'));
+ $filter = $this->field->cleanValue($filter);
+ $matches = [];
+ preg_match("/^in:? ?($columns) of (.+)$/", $filter, $matches);
+
+ $column = $columns_to_labels[$matches[1]];
+ $value = $matches[2];
+
+ $conditions = [];
+ $conditions[] = [$this->formatColumn($column, $field_id) => $value];
+ $conditions[] = [$this->formatColumn($column . '_handle', $field_id) => $value];
+
+ if (count($conditions) < 2) {
+ return $conditions;
+ }
+ return ['or' => $conditions];
+ }
+
+ public function isFilterWithin($filter)
+ {
+ return preg_match('/^within:? ?([0-9]+)\s?(km|mile|miles) of (.+)$/', $filter);
+ }
+
+ public function createFilterWithin($filter)
+ {
+ $field_id = General::intval($this->field->get('id'));
+ $filter = $this->field->cleanValue($filter);
+ $matches = [];
+ preg_match('/^within:? ?([0-9]+)\s?(km|mile|miles) of (.+)$/', $filter, $matches);
+
+ $radius = trim($matches[1]);
+ $unit = strtolower(trim($matches[2]));
+ $origin = trim($matches[3]);
+
+ $lat = null;
+ $lng = null;
+
+ // is a lat/long pair
+ if (preg_match('/^(-?[.0-9]+),?\s?(-?[.0-9]+)$/', $origin, $latlng)) {
+ $lat = $latlng[1];
+ $lng = $latlng[2];
+ }
+ // otherwise the origin needs geocoding
+ else {
+ $geocoded_result = $this->field->geocodeAddress($origin);
+ $coordinates = $geocoded_result->geometry->location;
+
+ if ($geocoded_result) {
+ $lat = $coordinates->lat;
+ $lng = $coordinates->lng;
+ }
+ }
+
+ // if we don't have a decent set of coordinates, we can't query
+ if (is_null($lat) || is_null($lng)) return true;
+
+ $this->field->filter_origin['latitude'] = $lat;
+ $this->field->filter_origin['longitude'] = $lng;
+ $this->field->filter_origin['unit'] = $unit[0];
+
+ // build the bounds within the query should look
+ $radius = $this->field->driver->geoRadius($lat, $lng, $radius, ($unit[0] == 'k'));
+
+ $conditions = [];
+ $conditions[] = [$this->formatColumn('latitude', $field_id) => ['between' => [$radius['latMIN'], $radius['latMAX']]]];
+ $conditions[] = [$this->formatColumn('longitude', $field_id) => ['between' => [$radius['lonMIN'], $radius['lonMAX']]]];
+
+ return ['and' => $conditions];
+ }
+
+ /**
+ * @see EntryQueryFieldAdapter::filterSingle()
+ *
+ * @param EntryQuery $query
+ * @param string $filter
+ * @return array
+ */
+ protected function filterSingle(EntryQuery $query, $filter)
+ {
+ General::ensureType([
+ 'filter' => ['var' => $filter, 'type' => 'string'],
+ ]);
+
+ $columns_to_labels = array();
+
+ foreach (array('street', 'city', 'region', 'postal_code', 'country') as $name)
+ {
+ $columns_to_labels[Lang::createHandle($this->field->get("{$name}_label"))] = $name;
+ }
+
+ $columns = implode('|', array_keys($columns_to_labels));
+ $this->_key++;
+
+ if ($this->isFilterIn($filter, $columns)) {
+ return $this->createFilterIn($filter, $columns, $columns_to_labels);
+ } elseif ($this->isFilterWithin($filter)) {
+ return $this->createFilterWithin($filter);
+ }
+ }
+}