location_views.module in Location 5.3
Same filename and directory in other branches
Views-enables the location module.
File
contrib/location_views/location_views.moduleView source
<?php
/**
* @file
* Views-enables the location module.
*/
/**
* Implementation of hook_views_tables().
*/
function location_views_tables() {
$tables['location'] = array(
'name' => 'location',
'join' => array(
'left' => array(
'table' => 'location_instance_node',
'field' => 'lid',
),
'right' => array(
'field' => 'lid',
),
),
'fields' => array(
'name' => array(
'name' => t('Name'),
'sortable' => TRUE,
),
'street' => array(
'name' => t('Street'),
'sortable' => TRUE,
),
'additional' => array(
'name' => t('Additional'),
'sortable' => TRUE,
),
'city' => array(
'name' => t('City'),
'sortable' => TRUE,
),
// Should be province_name, but can't change history.
'province' => array(
'name' => t('Province name'),
'handler' => 'location_views_province_handler',
'addlfields' => array(
'country',
),
'sortable' => TRUE,
),
'province_code' => array(
'field' => 'province',
'name' => t('Province code'),
'sortable' => TRUE,
),
'postal_code' => array(
'name' => t('Postal Code'),
'sortable' => TRUE,
),
// Should be country_name, but can't change history.
'country' => array(
'name' => t('Country'),
'handler' => 'location_views_country_handler',
'sortable' => TRUE,
),
'country_code' => array(
'field' => 'country',
'name' => t('Country code'),
'sortable' => TRUE,
),
'latitude' => array(
'name' => t('Latitude'),
'sortable' => TRUE,
),
'longitude' => array(
'name' => t('Longitude'),
'sortable' => TRUE,
),
// add a complete address in a single box as a field option
'address' => array(
'field' => 'lid',
'name' => t('Address'),
'handler' => 'location_views_field_handler_address',
'sortable' => FALSE,
'help' => t('Complete formatted address in a single cell, using the location theme.'),
),
// @@@ This one DEFINATELY needs a sanity check.
// add field showing distance from selected zip code
'distance' => array(
'name' => t('Distance'),
'handler' => 'location_views_field_handler_distance',
'notafield' => TRUE,
// @@@
'sortable' => FALSE,
'addlfields' => array(
'name',
'street',
'additional',
'city',
'province',
'country',
'postal_code',
'longitude',
'latitude',
),
'help' => t('Combine with proximity filter. Displays distance from each node to the central location selected with the proximity filter.'),
),
),
'sorts' => array(
'name' => array(
'name' => t('Name'),
),
'street' => array(
'name' => t('Street'),
),
'additional' => array(
'name' => t('Additional'),
),
'city' => array(
'name' => t('City'),
),
'province' => array(
'name' => t('Province'),
),
'country' => array(
'name' => t('Country'),
),
'postal_code' => array(
'name' => t('Postal Code'),
),
),
'filters' => array(
'name' => array(
'field' => 'name',
'name' => t('Name'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
),
'additional' => array(
'field' => 'additional',
'name' => t('Additional'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
),
'street' => array(
'field' => 'street',
'name' => t('Street'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
),
'city' => array(
'field' => 'city',
'name' => t('City'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
),
// Note: Only checks latitude for now.
'has_coordinates' => array(
'field' => 'latitude',
'name' => t('Has coordinates'),
'operator' => array(
'IS NOT' => t('Has coordinates'),
'IS' => t('No coordinates'),
),
'handler' => 'views_handler_filter_null',
),
'province_select' => array(
'field' => 'province',
'name' => t('Province Selector'),
'operator' => 'location_handler_operator_eq',
'handler' => 'location_handler_filter_eq',
'value' => array(
'#type' => 'textfield',
// Used so we can find ourselves during alter.
'#location_views_province_field' => TRUE,
'#autocomplete_path' => 'location/autocomplete/' . variable_get('location_default_country', 'us'),
'#size' => 64,
'#maxlength' => 64,
// Used by province autocompletion js.
'#attributes' => array(
'class' => 'location_views_auto_province',
),
// Used to ensure the JS is loaded.
'#theme' => 'location_views_province_textfield',
),
'cacheable' => 'no',
),
'province' => array(
'field' => 'province',
'name' => t('Province'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
),
'postal_code' => array(
'field' => 'postal_code',
'name' => t('Postal Code'),
'operator' => 'views_handler_operator_like',
'handler' => 'views_handler_filter_like',
),
'country' => array(
'field' => 'country',
'name' => t('Country'),
'operator' => 'location_handler_operator_eq',
'handler' => 'location_handler_filter_eq',
'value' => array(
'#type' => 'select',
'#options' => array_merge(array(
'' => t('Please select'),
'xx' => 'NOT LISTED',
), location_get_iso3166_list()),
// Used by province autocompletion js.
'#attributes' => array(
'class' => 'location_views_auto_country',
),
),
),
'latitude' => array(
'field' => 'latitude',
'name' => t('Latitude'),
'operator' => 'views_handler_operator_gtlt',
),
'longitude' => array(
'field' => 'longitude',
'name' => t('Longitude'),
'operator' => 'views_handler_operator_gtlt',
),
'proximity' => array(
'field' => 'distance',
'name' => t('Proximity'),
'operator' => location_views_proximity_operators(),
'handler' => 'location_views_filter_handler_proximity',
'value' => location_views_proximity_form(),
'help' => t('Select the postal code and the distance units to be used for the proximity filter.'),
'cacheable' => 'no',
),
),
);
if (module_exists('gmap')) {
$tables['location']['filters']['proximity_map'] = array(
'field' => 'distance',
'name' => t('Proximity Map'),
'operator' => location_views_proximity_operators(),
'handler' => 'location_views_filter_handler_proximity',
'value' => array(
'#type' => 'location_views_map',
),
'help' => t('Map the central point and the distance units to be used for the proximity filter.'),
'cacheable' => 'no',
);
}
// location <-> location_instance <-> node
$tables['location_instance_node'] = array(
'name' => 'location_instance',
'join' => array(
'left' => array(
'table' => 'node',
'field' => 'vid',
),
'right' => array(
'field' => 'vid',
),
),
'filters' => array(
'has_location' => array(
'field' => 'vid',
'name' => t('Location: Has location'),
'operator' => array(
'IS NOT' => t('Has location'),
'IS' => t('No location'),
),
'handler' => 'views_handler_filter_null',
),
),
);
if (module_exists('usernode')) {
$tables['location_instance_user'] = array(
'name' => 'location_instance',
'join' => array(
'left' => array(
'table' => 'usernode',
'field' => 'uid',
),
'right' => array(
'field' => 'uid',
),
),
'filters' => array(
'has_location' => array(
'field' => 'uid',
'name' => t('User Location: Has location'),
'operator' => array(
'IS NOT' => t('Has location'),
'IS' => t('No location'),
),
'handler' => 'views_handler_filter_null',
),
),
);
$tables['user_location'] = $tables['location'];
// Change join for user_location.
$tables['user_location']['join']['left']['table'] = 'location_instance_user';
// @@@ Fix these stupid handlers.
$tables['user_location']['filters']['proximity']['handler'] = 'location_views_filter_handler_user_proximity';
$tables['user_location']['filters']['proximity_map']['handler'] = 'location_views_filter_handler_user_proximity';
foreach (array(
'fields',
'sorts',
'filters',
) as $key) {
foreach ($tables['user_location'][$key] as $k => $v) {
if (isset($tables['user_location'][$key][$k]['name'])) {
$tables['user_location'][$key][$k]['name'] = t('User Location: !field', array(
'!field' => $v['name'],
));
}
}
}
}
foreach (array(
'fields',
'sorts',
'filters',
) as $key) {
foreach ($tables['location'][$key] as $k => $v) {
if (isset($tables['location'][$key][$k]['name'])) {
$tables['location'][$key][$k]['name'] = t('Location: !field', array(
'!field' => $v['name'],
));
}
}
}
return $tables;
}
/**
* Create default location view
*/
function location_views_default_views() {
$view = new stdClass();
$view->name = 'location_table';
$view->description = 'Node location table.';
$view->disabled = TRUE;
$view->access = array();
$view->view_args_php = '';
$view->page = TRUE;
$view->page_title = '';
$view->page_header = '';
$view->page_header_format = '1';
$view->page_footer = '';
$view->page_footer_format = '1';
$view->page_empty = '';
$view->page_empty_format = '1';
$view->page_type = 'table';
$view->url = 'location/views';
$view->use_pager = TRUE;
$view->nodes_per_page = '10';
$view->menu = TRUE;
$view->menu_title = 'Location table';
$view->menu_tab = FALSE;
$view->menu_tab_weight = '0';
$view->menu_tab_default = FALSE;
$view->menu_tab_default_parent = NULL;
$view->menu_tab_default_parent_type = 'tab';
$view->menu_parent_tab_weight = '0';
$view->menu_parent_title = '';
$view->sort = array();
$view->argument = array();
$view->field = array(
array(
'tablename' => 'node',
'field' => 'title',
'label' => 'Title:',
'handler' => 'views_handler_field_nodelink',
'options' => 'link',
'sortable' => '1',
'defaultsort' => 'ASC',
),
array(
'tablename' => 'location',
'field' => 'street',
'label' => 'Street:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'city',
'label' => 'City:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'province',
'label' => 'Province:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'postal_code',
'label' => 'Postal Code:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'country',
'label' => 'Country:',
'sortable' => '1',
),
);
$view->filter = array(
array(
'tablename' => 'node',
'field' => 'status',
'operator' => '=',
'options' => '',
'value' => '1',
),
array(
'tablename' => 'location_instance_node',
'field' => 'has_location',
'operator' => 'IS NOT',
'options' => '',
'value' => '',
),
);
$view->exposed_filter = array();
$view->requires = array(
'node',
'location',
'location_instance_node',
);
$views[$view->name] = $view;
$view = new stdClass();
$view->name = 'location_directory';
$view->description = 'Location directory filtered by arguments in the url.';
$view->disabled = TRUE;
$view->access = array();
$view->view_args_php = '';
$view->page = TRUE;
$view->page_title = 'Locations';
$view->page_header = '';
$view->page_header_format = '1';
$view->page_footer = '';
$view->page_footer_format = '1';
$view->page_empty = '';
$view->page_empty_format = '1';
$view->page_type = 'table';
$view->url = 'location/directory';
$view->use_pager = TRUE;
$view->nodes_per_page = '10';
$view->menu = TRUE;
$view->menu_title = 'Locations';
$view->menu_tab = FALSE;
$view->menu_tab_weight = '0';
$view->menu_tab_default = FALSE;
$view->menu_tab_default_parent = NULL;
$view->menu_tab_default_parent_type = 'tab';
$view->menu_parent_tab_weight = '0';
$view->menu_parent_title = '';
$view->sort = array();
$view->argument = array(
array(
'type' => 'country',
'argdefault' => '6',
'title' => '%1',
'options' => '',
'wildcard' => '',
'wildcard_substitution' => '',
),
array(
'type' => 'province',
'argdefault' => '6',
'title' => '%2',
'options' => '',
'wildcard' => '',
'wildcard_substitution' => '',
),
array(
'type' => 'city',
'argdefault' => '6',
'title' => '%3',
'options' => '1',
'wildcard' => '',
'wildcard_substitution' => '',
),
);
$view->field = array(
array(
'tablename' => 'node',
'field' => 'title',
'label' => 'Title:',
'handler' => 'views_handler_field_nodelink',
'sortable' => '1',
'options' => 'link',
),
array(
'tablename' => 'location',
'field' => 'street',
'label' => 'Street:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'city',
'label' => 'City:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'province',
'label' => 'Province:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'postal_code',
'label' => 'Postal Code:',
'sortable' => '1',
),
array(
'tablename' => 'location',
'field' => 'country',
'label' => 'Country:',
'sortable' => '1',
),
);
$view->filter = array(
array(
'tablename' => 'node',
'field' => 'status',
'operator' => '=',
'options' => '',
'value' => '1',
),
array(
'tablename' => 'location_instance_node',
'field' => 'has_location',
'operator' => 'IS NOT',
'options' => '',
'value' => '',
),
);
$view->exposed_filter = array();
$view->requires = array(
node,
location,
location_instance_node,
);
$views[$view->name] = $view;
if (module_exists('usernode')) {
$view = new stdClass();
$view->name = 'user_location_table';
$view->description = 'User location table.';
$view->disabled = TRUE;
$view->access = array();
$view->view_args_php = '';
$view->page = TRUE;
$view->page_title = '';
$view->page_header = '';
$view->page_header_format = '1';
$view->page_footer = '';
$view->page_footer_format = '1';
$view->page_empty = '';
$view->page_empty_format = '1';
$view->page_type = 'table';
$view->url = 'location/users';
$view->use_pager = TRUE;
$view->nodes_per_page = '10';
$view->menu = TRUE;
$view->menu_title = 'User location table';
$view->menu_tab = FALSE;
$view->menu_tab_weight = '0';
$view->menu_tab_default = FALSE;
$view->menu_tab_default_parent = NULL;
$view->menu_tab_default_parent_type = 'tab';
$view->menu_parent_tab_weight = '0';
$view->menu_parent_title = '';
$view->sort = array();
$view->argument = array();
$view->field = array(
array(
'tablename' => 'node',
'field' => 'title',
'label' => 'Title:',
'handler' => 'views_handler_field_nodelink',
'sortable' => '1',
'defaultsort' => 'ASC',
'options' => 'link',
),
array(
'tablename' => 'user_location',
'field' => 'street',
'label' => 'Street:',
'sortable' => '1',
),
array(
'tablename' => 'user_location',
'field' => 'city',
'label' => 'City:',
'sortable' => '1',
),
array(
'tablename' => 'user_location',
'field' => 'province',
'label' => 'Province:',
'sortable' => '1',
),
array(
'tablename' => 'user_location',
'field' => 'postal_code',
'label' => 'Postal Code:',
'sortable' => '1',
),
array(
'tablename' => 'user_location',
'field' => 'country',
'label' => 'Country:',
'sortable' => '1',
),
);
$view->filter = array(
array(
'tablename' => 'node',
'field' => 'status',
'operator' => '=',
'options' => '',
'value' => '1',
),
array(
'tablename' => 'node',
'field' => 'type',
'operator' => 'OR',
'options' => '',
'value' => array(
0 => 'usernode',
),
),
array(
'tablename' => 'location_instance_user',
'field' => 'has_location',
'operator' => 'IS NOT',
'options' => '',
'value' => '',
),
);
$view->exposed_filter = array();
$view->requires = array(
node,
user_location,
location_instance_user,
);
$views[$view->name] = $view;
}
return $views;
}
function location_views_arguments() {
$arguments = array(
'city' => array(
'name' => t('Location: City'),
'handler' => 'location_views_handler_arg_city',
'option' => 'string',
'help' => t('This argument allows users to filter a view by specifying the city. Set the option to the number of characters to use in summaries, using 0 for full name; use 1 for an A/B/C style directory of cities.'),
),
'province' => array(
'name' => t('Location: Province'),
'handler' => 'location_views_handler_arg_province',
'help' => t('This argument allows users to filter a view by specifying the province.'),
),
'country' => array(
'name' => t('Location: Country'),
'handler' => 'location_views_handler_arg_country',
'help' => t('This argument allows users to filter a view by specifying the country.'),
),
'postal_code' => array(
'name' => t('Location: Postal Code'),
'handler' => 'location_views_handler_arg_postal_code',
'help' => t('This argument allows users to filter a view by specifying the postal code.'),
),
);
if (module_exists('usernode')) {
$arguments['user_city'] = array(
'name' => t('User Location: City'),
'handler' => 'location_views_handler_arg_user_city',
'option' => 'string',
'help' => t('This argument allows users to filter a view by specifying the city. Set the option to the number of characters to use in summaries, using 0 for full name; use 1 for an A/B/C style directory of cities.'),
);
$arguments['user_province'] = array(
'name' => t('User Location: Province'),
'handler' => 'location_views_handler_arg_user_province',
'help' => t('This argument allows users to filter a view by specifying the province.'),
);
$arguments['user_country'] = array(
'name' => t('User Location: Country'),
'handler' => 'location_views_handler_arg_user_country',
'help' => t('This argument allows users to filter a view by specifying the country.'),
);
}
return $arguments;
}
function theme_location_views_province_textfield($element) {
drupal_add_js(drupal_get_path('module', 'location_views') . '/location_views_autocomplete.js');
return theme('textfield', $element);
}
function location_views_handler_any($op, &$query, $argtype, $arg = '', $type = 'node', $col) {
switch ($op) {
case 'summary':
$query
->ensure_table('location');
if ($type == 'node') {
$query
->add_where("location_instance_node.vid IS NOT NULL");
}
else {
if ($type == 'user') {
$query
->add_where("location_instance_user.uid IS NOT NULL");
}
}
// if a length option has been provided, display only the $len left letters of the name
$len = intval($arg);
if ($len <= 0) {
$fieldinfo['field'] = "IF (location.{$col} = '' OR location.{$col} IS NULL, '" . t('unknown') . "', location.{$col})";
}
else {
$fieldinfo['field'] = "IF (location.{$col} = '' OR location.{$col} IS NULL, '" . t('unknown') . "', LEFT(location.{$col}, {$len}))";
}
$fieldinfo['fieldname'] = $col;
return $fieldinfo;
case 'sort':
$query
->add_orderby('location', $col, 'ASC');
break;
case 'filter':
$query
->ensure_table('location');
$query
->add_field($col, 'location');
// adjust the search based on whether you are looking for the full value or the first $len letters
$len = intval($argtype['options']);
if ($len <= 0) {
$query
->add_where("location.{$col} = '%s'", strcasecmp($arg, t('unknown')) ? $arg : '');
}
else {
$query
->add_where("LEFT(location.{$col}, {$len}) = '%s'", strcasecmp($arg, t('unknown')) ? $arg : '');
}
break;
// case 'link':
// break;
case 'title':
return $query;
}
}
/**
* City argument handler.
*/
function location_views_handler_arg_user_city($op, &$query, $argtype, $arg = '') {
switch ($op) {
case 'link':
// if using first letter directory, use strtoupper on the link
if ($len) {
return l($query->city == t('unknown') ? t('unknown') : strtoupper($query->city), "{$arg}/{$query->city}");
}
else {
return l($query->city == t('unknown') ? t('unknown') : $query->city, "{$arg}/{$query->city}");
}
default:
return location_views_handler_any($op, $query, $argtype, $arg, 'user', 'city');
}
}
function location_views_handler_arg_city($op, &$query, $argtype, $arg = '') {
switch ($op) {
case 'link':
// if using first letter directory, use strtoupper on the link
if ($len) {
return l($query->city == t('unknown') ? t('unknown') : strtoupper($query->city), "{$arg}/{$query->city}");
}
else {
return l($query->city == t('unknown') ? t('unknown') : $query->city, "{$arg}/{$query->city}");
}
default:
return location_views_handler_any($op, $query, $argtype, $arg, 'node', 'city');
}
}
/**
* Postal code argument handler.
*/
function location_views_handler_arg_postal_code($op, &$query, $argtype, $arg = '') {
switch ($op) {
case 'link':
return l($query->postal_code == t('unknown') ? t('unknown') : $query->postal_code, "{$arg}/{$query->postal_code}");
default:
return location_views_handler_any($op, $query, $argtype, $arg, 'node', 'postal_code');
}
}
/**
* Province argument handler.
*/
function location_views_handler_arg_user_province($op, &$query, $argtype, $arg = '') {
return location_views_handler_arg_province($op, $query, $argtype, $arg, 'user');
}
function location_views_handler_arg_province($op, &$query, $argtype, $arg = '', $type = 'node') {
switch ($op) {
case 'summary':
$query
->ensure_table('location');
// Figure out what country to load.
// This works best when the country argument appears before.
$country = isset($query->_location_country_arg) ? $query->_location_country_arg : variable_get('location_default_country', 'us');
if ($country == t('unknown')) {
$country = '';
}
// Add country as a fake field.
$query
->add_field("'{$country}'", NULL, 'location_country_arg');
if ($type == 'node') {
$query
->add_where("location_instance_node.vid IS NOT NULL");
}
else {
if ($type == 'user') {
$query
->add_where("location_instance_user.uid IS NOT NULL");
}
}
$fieldinfo['field'] = "IF (location.province = '' OR location.province IS NULL, '" . t('unknown') . "', location.province)";
$fieldinfo['fieldname'] = 'province';
return $fieldinfo;
case 'link':
$name = location_province_name($query->location_country_arg, $query->province);
return l(empty($name) ? t('unknown') : $name, "{$arg}/{$query->province}");
case 'title':
global $_location_views_country;
$title = FALSE;
if (isset($_location_views_country)) {
$title = location_province_name($_location_views_country, $query);
}
if (!$title) {
$title = location_province_name(variable_get('location_default_country', 'us'), $query);
}
if (!$title) {
$title = check_plain($query);
}
return $title;
default:
return location_views_handler_any($op, $query, $argtype, $arg, $type, 'province');
}
}
/**
* Country argument handler.
*/
function location_views_handler_arg_user_country($op, &$query, $argtype, $arg = '') {
switch ($op) {
case 'link':
return l($query->country == t('unknown') ? t('unknown') : location_country_name($query->country), "{$arg}/{$query->country}");
case 'title':
global $_location_views_country;
$_location_views_country = $query;
return $query == t('unknown') ? t('unknown') : $country_name;
default:
return location_views_handler_any($op, $query, $argtype, $arg, 'user', 'country');
}
}
function location_views_handler_arg_country($op, &$query, $argtype, $arg = '') {
switch ($op) {
case 'link':
return l($query->country == t('unknown') ? t('unknown') : location_country_name($query->country), "{$arg}/{$query->country}");
case 'title':
global $_location_views_country;
$_location_views_country = $query;
return $query == t('unknown') ? t('unknown') : location_country_name($query);
case 'filter':
// Stash the arg for use by the province arg.
$query->_location_country_arg = $arg;
default:
return location_views_handler_any($op, $query, $argtype, $arg, 'node', 'country');
}
}
/**
* A list of options to be used in = queries
*/
function location_handler_operator_eq() {
return array(
'' => t('<All>'),
'=' => t('='),
'!=' => t('not ='),
);
}
/**
* Custom filter for = queries.
*/
function location_handler_filter_eq($op, $filter, $filterinfo, &$query) {
if ($op == 'handler') {
// If there isn't a value available, give up.
if (empty($filter['value'])) {
return;
}
// If there isn't an operator, give up.
if (empty($filter['operator'])) {
return;
}
$searchvalue = $filter['value'];
switch ($filterinfo['field']) {
case 'province':
//@@@ There's gotta be a better way to grab the country...
$country = substr($filterinfo['value']['#autocomplete_path'], -2);
$provinces = location_get_provinces($country);
$p = strtoupper($filter['value']);
foreach ($provinces as $k => $v) {
if ($p == strtoupper($k) || $p == strtoupper($v)) {
$searchvalue = $k;
break;
}
}
break;
case 'country':
// No extra processing needed.
break;
}
$query
->ensure_table($filterinfo['table']);
$query
->add_where("%s.%s %s '%s'", $filterinfo['table'], $filterinfo['field'], $filter['operator'], $searchvalue);
}
}
/**
* Format a country name.
*/
function location_views_country_handler($fieldinfo, $fielddata, $value, $data) {
return location_country_name($value);
}
/**
* Format a province name.
*/
function location_views_province_handler($fieldinfo, $fielddata, $value, $data) {
return location_province_name($data->location_country, $data->location_province);
}
/**
* Format complete address as a single field.
*/
function location_views_field_handler_address($fieldinfo, $fielddata, $value, $data) {
$location = location_load_location($value);
return theme('location', $location);
}
function location_views_field_handler_distance($fieldinfo, $fielddata, $value, $data) {
return number_format(round($data->distance, 2), 2) . ' ' . $distance_unit;
}
/**
* Proximity handling functions
*
* at the moment, everything is set up to assume the unit is miles
* need to find a way to provide an alternative for km
* not sure yet how to add another selector into the mix so user can select units
*/
function location_views_proximity_form() {
return array(
'#title' => t('from Postal Code'),
'#type' => 'textfield',
'#size' => 15,
);
}
function location_views_proximity_operators() {
$values = array(
5 => 5,
10 => 10,
25 => 25,
50 => 50,
100 => 100,
250 => 250,
);
foreach ($values as $val) {
$options[$val] = t('@distance miles', array(
'@distance' => $val,
));
}
return $options;
}
/**
* Proximity filter
* Uses functions and queries created in location.inc and earth.inc and re-factors them to work in views
*/
function location_views_filter_handler_user_proximity($op, $filter, $filterinfo, &$query) {
return location_views_filter_handler_proximity($op, $filter, $filterinfo, $query, 'user_location');
}
function location_views_filter_handler_proximity($op, $filter, $filterinfo, &$query, $table = 'location') {
$unit = 'miles';
$distance = $filter['operator'];
if (is_array($filter['value']) && isset($filter['value']['latitude'])) {
$lat = $filter['value']['latitude'];
$lon = $filter['value']['longitude'];
}
else {
$zip = $filter['value'];
// @@@ This needs to factor in country.
$result = db_query("SELECT * FROM {zipcodes} WHERE zip = '%s'", $zip);
while ($arr = db_fetch_array($result)) {
$lat = $arr['latitude'];
$lon = $arr['longitude'];
}
}
if (!$lat || !$lon) {
return;
}
$divisor = $unit == 'km' ? 1000 : 1609.347;
$latrange = earth_latitude_range($lon, $lat, $distance * $divisor);
$lonrange = earth_longitude_range($lon, $lat, $distance * $divisor);
$query
->ensure_table($table);
$query
->add_orderby(NULL, "((" . earth_distance_sql($lon, $lat) . ") / {$divisor})", 'ASC', 'distance');
$query
->add_where("{$table}.longitude IS NOT NULL");
$query
->add_where("{$table}.latitude > %f AND {$table}.latitude < %f AND {$table}.longitude > %f AND {$table}.longitude < %f", $latrange[0], $latrange[1], $lonrange[0], $lonrange[1]);
}
/**
* Implementation of hook_form_alter().
*/
function location_views_form_alter($form_id, &$form) {
// Fix the autocomplete path for the province field.
// @@@ Unfortunately, views seems to cache the form contents.
if ($form_id == 'views_filters') {
$country = FALSE;
foreach ($form['view']['#value']->filter as $k => $filter) {
if ($filter['field'] == 'location.country') {
$fv = views_get_filter_values();
$country = $fv[$k]['filter'];
if (!location_standardize_country_code($country)) {
// Invalid country, fall back to default.
$country = variable_get('location_default_country', 'us');
}
break;
}
}
if ($country) {
foreach ($form as $k => $field) {
if (is_array($field) && isset($field['#location_views_province_field'])) {
$form[$k]['#autocomplete_path'] = 'location/autocomplete/' . $country;
}
}
}
}
}
/**
* Implementation of hook_elements().
*/
function location_views_elements() {
return array(
'location_views_map' => array(
'#input' => TRUE,
'#tree' => TRUE,
'#process' => array(
'_location_views_expand_map' => array(),
),
),
);
}
function _location_views_expand_map($element) {
// Views 1.x has serious issues with persisting #tree.
// Repair stuff that views screwed up.
if (isset($element['#default_value']) && is_string($element['#default_value'])) {
$val = explode(',', $element['#default_value']);
$element['#default_value'] = array(
'latitude' => $val[0],
'longitude' => $val[1],
);
}
if (isset($element['#value']) && is_string($element['#value'])) {
$val = explode(',', $element['#value']);
$element['#value'] = array(
'latitude' => $val[0],
'longitude' => $val[1],
);
}
// @@@ I'm undecided as to whether this is a good idea to have.
// It seems to break the principle of least surprise...
if (!isset($element['#default_value']['latitude']) || empty($element['#default_value']['latitude'])) {
// Default value not set. Attempt to come up with a default value based on the user's location.
global $user;
$result = db_query('SELECT l.latitude, l.longitude FROM {location} l INNER JOIN {location_instance} i ON l.lid = i.lid WHERE i.uid = %d', $user->uid);
if ($row = db_fetch_array($result)) {
$element['#default_value'] = $row;
}
}
if (!isset($element['#default_value']['latitude']) || empty($element['#default_value']['latitude'])) {
// Default value not set, tidy up things a bit to prevent warnings.
$element['#default_value'] = array(
'latitude' => '',
'longitude' => '',
);
}
// The rest of this used to be location_latlon_form(), before it got removed.
$usegmap = function_exists('gmap_set_location') && variable_get('location_usegmap', FALSE);
if ($usegmap) {
$element['map'] = array();
//reserve spot at top of form for map
}
$element['latitude'] = array(
'#type' => 'textfield',
'#title' => t('Latitude'),
'#default_value' => isset($element['#default_value']['latitude']) ? $element['#default_value']['latitude'] : '',
'#size' => 64,
'#maxlength' => 64,
);
$element['longitude'] = array(
'#type' => 'textfield',
'#title' => t('Longitude'),
'#default_value' => isset($element['#default_value']['longitude']) ? $element['#default_value']['longitude'] : '',
'#size' => 64,
'#maxlength' => 64,
'#description' => t('Click on the map to mark the center point for your search, then submit the values.'),
);
if ($usegmap) {
$map_macro = variable_get('gmap_user_map', '[gmap|id=usermap|center=0,30|zoom=16|width=100%|height=400px]');
$element['map']['gmap']['#value'] = gmap_set_location($map_macro, $element, array(
'latitude' => 'latitude',
'longitude' => 'longitude',
));
}
return $element;
}
function theme_location_views_map($element) {
return $element['#children'];
}