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); + } + } +}