diff -rupN location/handlers/location_handler_argument_location_proximity.inc location_new/handlers/location_handler_argument_location_proximity.inc
--- location/handlers/location_handler_argument_location_proximity.inc 1970-01-01 10:00:00.000000000 +1000
+++ handlers/location_handler_argument_location_proximity.inc 2010-07-01 21:46:54.000000000 +1000
@@ -0,0 +1,183 @@
+ ($country == 'us' || $country == 'uk' ? 'mile' : 'km'));
+ $options['search_method'] = array('default' => 'mbr');
+ $options['type'] = array('default' => 'postal');
+ return $options;
+ }
+
+ /**
+ * Add a form elements to select options for this argument.
+ */
+ function options_form(&$form, &$form_state) {
+ parent::options_form($form, $form_state);
+ $form['type'] = array(
+ '#title' => t('Coordinate Type'),
+ '#type' => 'select',
+ '#options' => array(
+ 'postal' => t('Postal Code (Zipcode)'),
+ 'latlon' => t('Decimal Latitude and Longitude coordinates, comma delimited'),
+ ),
+ '#default_value' => $this->options['type'],
+ '#description' => t('Type of center point.') . '
' . t('Postal code argument format: country_postcode_distance or postcode_distance') . '
' . t('Lat/Lon argument format: lat,lon_distance'),
+ );
+
+ // Units used.
+ $form['search_units'] = array(
+ '#type' => 'select',
+ '#title' => t('Distance unit'),
+ '#options' => array(
+ 'km' => t('Kilometers'),
+ 'm' => t('Meters'),
+ 'mile' => t('Miles'),
+ 'dd' => t('Decimal degrees'),
+ ),
+ '#default_value' => $this->options['search_units'],
+ '#description' => t('Select the unit of distance. Decimal degrees should be comma delimited.'),
+ );
+
+ $form['search_method'] = array(
+ '#title' => t('Method'),
+ '#type' => 'select',
+ '#options' => array(
+ 'dist' => t('Circular Proximity'),
+ 'mbr' => t('Rectangular Proximity'),
+ ),
+ '#default_value' => $this->options['search_method'],
+ '#description' => t('Method of determining proximity. Please note that Circular Proximity does not work with Decimal degrees.'),
+ );
+ }
+
+ function calculate_coords() {
+ if (!empty($this->value['latitude']) && !empty($this->value['longitude'])) {
+ // If there are already coordinates, there's no work for us.
+ return TRUE;
+ }
+ // @@@ Switch to mock location object and rely on location more?
+
+ if ($this->options['type'] == 'postal') {
+ if (!isset($this->value['country'])) {
+ $this->value['country'] = variable_get('location_default_country', 'us');
+ }
+ // Zip code lookup.
+ if (!empty($this->value['postal_code']) && !empty($this->value['country'])) {
+ location_load_country($this->value['country']);
+ $coord = location_get_postalcode_data($this->value);
+ if ($coord) {
+ $this->value['latitude'] = $coord['lat'];
+ $this->value['longitude'] = $coord['lon'];
+ }
+ else {
+ $coord = location_latlon_rough($this->value);
+ if ($coord) {
+ $this->value['latitude'] = $coord['lat'];
+ $this->value['longitude'] = $coord['lon'];
+ }
+ else {
+ return FALSE;
+ }
+ }
+ }
+ else {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+
+ /**
+ * Set up the query for this argument.
+ *
+ * The argument sent may be found at $this->argument.
+ */
+ function query() {
+ // Get and process argument.
+ if ($this->options['type'] == 'postal') {
+ foreach ($this->view->argument as $argument) {
+ if ($argument->field == 'distance') {
+ $arg_parts = explode('_', $this->view->args[$argument->position]);
+ if (count($arg_parts) == 3) {
+ $this->value['country'] = drupal_strtolower($arg_parts[0]);
+ $this->value['postal_code'] = $arg_parts[1];
+ $this->value['search_distance'] = $arg_parts[2];
+ }
+ else {
+ $this->value['postal_code'] = $arg_parts[0];
+ $this->value['search_distance'] = $arg_parts[1];
+ }
+ break;
+ }
+ }
+ }
+ else if ($this->options['type'] == 'latlon') {
+ foreach ($this->view->argument as $argument) {
+ if ($argument->field == 'distance') {
+ list($coords, $this->value['search_distance']) = explode('_', $this->view->args[$argument->position]);
+ list($this->value['latitude'], $this->value['longitude']) = explode(',', $coords);
+ break;
+ }
+ }
+ }
+
+ // Coordinates available?
+ if (!$this->calculate_coords()) {
+ // Distance set?
+ if (!empty($this->value['search_distance'])) {
+ // Hmm, distance set but unable to resolve coordinates.
+ // Force nothing to match.
+ $this->query->add_where($this->options['group'], "1 = 0");
+ }
+ return;
+ }
+
+ $this->ensure_my_table();
+
+ $lat = $this->value['latitude'];
+ $lon = $this->value['longitude'];
+
+ // search_distance
+ if ($this->options['search_units'] == 'dd') {
+ list($lat_distance, $lon_distance) = explode(',', $this->value['search_distance']);
+ $latrange[0] = $lat - $lat_distance;
+ $latrange[1] = $lat + $lat_distance;
+ $lonrange[0] = $lon - $lon_distance;
+ $lonrange[1] = $lon + $lon_distance;
+ }
+ else {
+ $distance = $this->value['search_distance'];
+ if ($this->options['search_units'] == 'm') {
+ $distance_meters = $distance;
+ }
+ else {
+ $distance_meters = _location_convert_distance_to_meters($distance, $this->options['search_units']);
+ }
+
+ $latrange = earth_latitude_range($lon, $lat, $distance_meters);
+ $lonrange = earth_longitude_range($lon, $lat, $distance_meters);
+ }
+
+ // Add MBR check (always).
+ // In case we go past the 180/-180 mark for longitude.
+ if ($lonrange[0] > $lonrange[1]) {
+ $where = "$this->table_alias.latitude > %f AND $this->table_alias.latitude < %f AND (($this->table_alias.longitude < 180 AND $this->table_alias.longitude > %f) OR ($this->table_alias.longitude < %f AND $this->table_alias.longitude > -180))";
+ }
+ else {
+ $where = "$this->table_alias.latitude > %f AND $this->table_alias.latitude < %f AND $this->table_alias.longitude > %f AND $this->table_alias.longitude < %f";
+ }
+ $this->query->add_where($this->options['group'], $where, $latrange[0], $latrange[1], $lonrange[0], $lonrange[1]);
+
+ if ($this->options['search_method'] == 'dist') {
+ // Add radius check.
+ $this->query->add_where($this->options['group'], earth_distance_sql($lon, $lat, $this->table_alias) . ' < %f', $distance_meters);
+ }
+ }
+}
diff -rupN location/location.views.inc location_new/location.views.inc
--- location/location.views.inc 2008-12-04 09:51:23.000000000 +1100
+++ location.views.inc 2010-07-01 21:09:40.000000000 +1000
@@ -51,6 +51,9 @@ function location_views_handlers() {
'location_handler_argument_location_province' => array(
'parent' => 'views_handler_argument',
),
+ 'location_handler_argument_location_proximity' => array(
+ 'parent' => 'views_handler_argument',
+ ),
'location_handler_field_location_address' => array(
'parent' => 'views_handler_field',
),
@@ -303,6 +306,9 @@ function location_views_data() {
'sort' => array(
'handler' => 'location_handler_sort_location_distance',
),
+ 'argument' => array(
+ 'handler' => 'location_handler_argument_location_proximity',
+ ),
'filter' => array(
'handler' => 'location_views_handler_filter_proximity',
),