Newer
Older
define('LOCATION_PATH', drupal_get_path('module', 'location'));
Ankur Rishi
committed
define('LOCATION_LATLON_UNDEFINED', 0);
define('LOCATION_LATLON_USER_SUBMITTED', 1);
define('LOCATION_LATLON_GEOCODED_APPROX', 2);
define('LOCATION_LATLON_GEOCODED_EXACT', 3);
define('LOCATION_USER_DONT_COLLECT', 0);
define('LOCATION_USER_COLLECT', 1);
include_once LOCATION_PATH .'/location.inc';
include_once LOCATION_PATH .'/location.theme';
Ankur Rishi
committed
// include the geocoders; need a better way of doing this as opposed to hard-coding here
foreach (variable_get('location_general_geocoders_in_use', array()) as $geocoder) {
include_once LOCATION_PATH. '/geocoding/'. $geocoder .'.inc';
}
Ankur Rishi
committed
/**
* Implementation of hook_menu.
*
*/
function location_menu($may_cache = FALSE) {
$items = array();
if ($may_cache) {
$items[] = array('path' => 'search/location', 'title' => t('By location'), 'callback' => 'location_search_view', 'access' => user_access('search content by location'), 'type' => MENU_LOCAL_TASK, 'weight' => 9);
$items[] = array('path' => 'admin/settings/location/main', 'title' => t('Main settings'), 'type' => MENU_DEFAULT_LOCAL_TASK,);
$items[] = array('path' => 'admin/settings/location/maplinking', 'title' => t('Map links'), 'callback' => 'location_map_link_options_page', 'access' => user_access('administer site configuration'), 'type' => MENU_LOCAL_TASK, 'weight' => 1,);
$items[] = array('path' => 'admin/settings/location/geocoding', 'title' => t('Geocoding options'), 'callback' => 'location_geocoding_options_page', 'access' => user_access('administer site configuration'), 'type' => MENU_LOCAL_TASK, 'weight' => 2,);
$items[] = array('path' => 'admin/settings/location', 'title' => t('Location'), 'description' => t('Settings for Location module'), 'callback' => 'drupal_get_form', 'callback arguments' => array('location_admin_settings'), 'access' => user_access('administer site configuration'), 'type' => MENU_NORMAL_ITEM, );
}
return $items;
}
Ankur Rishi
committed
function location_perm() {
return array('search content by location', 'submit latitude/longitude');
Ankur Rishi
committed
}
/**
* Implementation of hook_help.
*
*
*
*/
function location_help($section) {
switch ($section) {
Robin Monks
committed
case 'admin/help#location':
$output = '<p>'. t('The location module allows you to associate a geographic location with content and users. Users can do proximity searches by postal code. This is useful for organizing communities that have a geographic presence.') .'</p>';
$output .= '<p>'. t('To administer locative information for content, use the content type administration page. To support most location enabled features, you will need to install the country specific include file. To support postal code proximity searches for a particular country, you will need a database dump of postal code data for that country. As of June 2007 only U.S. and German postal codes are supported.') .'</p>';
Robin Monks
committed
$output .= t('<p>You can</p>
<ul>
<li>administer locative information at <a href="@admin-node-configure-types">Administer >> Content management >> Content types</a> to configure a type and see the locative information.</li>
<li>administer location at <a href="@admin-settings-location">Administer >> Site configuration >> Location</a>.</li>
<li>use a database dump for a U.S. and/or German postal codes table that can be found at <a href="@external-http-cvs-drupal-org">zipcode database</a>.</li>
', array('@admin-node-configure-types' => url('admin/content/types'), '@admin-settings-location' => url('admin/settings/location'), '@external-http-cvs-drupal-org' => 'http://cvs.drupal.org/viewcvs/drupal/contributions/modules/location/database/')) .'</ul>';
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@location">Location page</a>.', array('@location' => 'http://www.drupal.org/handbook/modules/location/')) .'</p>';
Robin Monks
committed
return $output;
//TODO: check/fix this: admin/content/configure/types above (still use %? still same url?)
function location_search_view() {
$location_params = array(
//'street' => $_GET['street'],
//'city' => $_GET['city'],
//'province' => $_GET['province'],
'postal_code' => $_GET['postal_code'],
'country' => $_GET['country'] ? $_GET['country'] : variable_get('location_default_country', 'us')
$proximity_params = array(
'distance' => $_GET['distance'],
'unit' => $_GET['unit'],
);
$output .= drupal_get_form('location_search_form', $location_params, $proximity_params);
if ($_GET['postal_code'] && $_GET['country'] && $_GET['distance'] && $_GET['country']) {
$output .= location_search_results($location_params, $proximity_params);
}
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
return $output;
}
function location_search_form($location_params = array(), $proximity_params = array()) {
$form = array();
$location_search_distance_unit_setting = variable_get('location_search_distance_unit', 0);
$proximity_suppressed_values = $location_search_distaince_unit_setting ? array('unit' => $location_search_distance_unit_setting) : array();
$form['proximity'] = location_proximity_form($proximity_params, $proximity_suppressed_values);
$location_suppressed_values = variable_get('location_suppress_country', 0) ? array('country' => variable_get('location_default_country', 'us')) : array();
$form['location'] = location_form(
array('postal_code', 'country'),
$location_params,
array('postal_code', 'country'),
$location_suppressed_values,
'',
'nearby_postalcodes_bylocation'
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Search')
);
//$form_exp = var_export($form, TRUE);
//drupal_set_message("location_search_form() returning <pre>$form_exp</pre>");
$form['#submit'] = array_merge(
$form['#submit'] ? $form['#submit'] : array(),
array('location_search_form_submit' => array())
);
return $form;
function location_search_form_validate($form_id, &$form_values) {
//$form_values_exp = var_export($form_values, TRUE);
//drupal_set_message("IN location_search_form_validate(): \$form_id == $form_id, \$form_values == <pre>$form_values_exp</pre>");
// TODO: Need to offer ability to configure which fields are included in the search form
// TODO: And need to adjust how fields are validated
// For now, just require postal code
if (!$form_values['postal_code']) {
//form_set_error('postal_code', t('You must include a postal code in your search.'));
}
if (!$form_values['country']) {
//form_set_error('country', t('You much include a country in your search.'));
}
function location_search_form_submit($form_id, &$form_values) {
//$form_values_exp = var_export($form_values, TRUE);
//drupal_set_message("IN location_search_form_submit(): \$form_id == $form_id and \$form_values == <pre>$form_values_exp</pre>");
/*
$location_fields = array('street', 'additional', 'province', 'postal_code', 'country');
foreach ($locations_fields as $field_name) {
if ($form_values[$field_name]) {
if ($query_string) {
$query_string .= '&'. $field_name .'='. $form_values[$field_name];
}
else {
$query_string = $field_name .'='. $form_values[$field_name];
}
}
$query_string = '&distance='. $form_values['distance'] .'&unit='. $unit;
*/
return array('search/location', 'postal_code='. $form_values['postal_code'] .'&country='. $form_values['country'] .'&distance='. $form_values['distance'] .'&unit='. $form_values['unit']);
}
function location_search_results($location_params, $proximity_params) {
// DEBUG: commented code for testing/debugging purposes
$start_time = microtime();
// First things first: find lat/lon for submitted postal_code
// TODO: will need to replace be able to get lat/lon of search point for more than just postal_code
$latlon = location_latlon_rough($location_params);
if (!$latlon['lat'] || !$latlon['lon']) {
drupal_set_message(t('No search results; could not determine the location of the submitted postal code.'));
return '';
// If the distance parameters did not make sense, return an empty search result set.
$distance_float = _location_convert_distance_to_meters($proximity_params['distance'], $proximity_params['unit']);
// Find the pairs of lats and lons that define the corners of a square that is $distance X $distance and centered on $latlon
$latrange = earth_latitude_range($latlon['lon'], $latlon['lat'], $distance_float);
$lonrange = earth_longitude_range($latlon['lon'], $latlon['lat'], $distance_float);
Ankur Rishi
committed
$count_query = 'SELECT COUNT(nid) AS count FROM {node} n INNER JOIN {location} l ON n.vid = l.eid WHERE l.type =\'node\' AND l.latitude > %f AND l.latitude < %f AND l.longitude > %f AND l.longitude < %f AND '. earth_distance_sql($latlon['lon'], $latlon['lat']) .' < %f';
$query = 'SELECT n.nid, l.*, '. earth_distance_sql($latlon['lon'], $latlon['lat'], 'l') .' as distance FROM {node} n INNER JOIN {location} l ON n.vid = l.eid WHERE l.type =\'node\' AND l.latitude > %f AND l.latitude < %f AND l.longitude > %f AND l.longitude < %f AND '. earth_distance_sql($latlon['lon'], $latlon['lat']) .' < %f GROUP BY n.nid ORDER by distance';
$query_args = array(
$latrange[0],
$latrange[1],
$lonrange[0],
$lonrange[1],
$distance_float
);
$pager_count_query = 'SELECT COUNT(DISTINCT nid) AS count FROM {node} n INNER JOIN {location} l ON n.vid = l.eid WHERE l.type =\'node\' AND l.latitude > '. $latrange[0] .' AND l.latitude < '. $latrange[1] .' AND l.longitude > '. $lonrange[0] .' AND l.longitude < '. $lonrange[1] .' AND '. earth_distance_sql($latlon['lon'], $latlon['lat']) .' < '. $distance_float;
$pager_query = 'SELECT n.nid, n.vid, l.*, '. earth_distance_sql($latlon['lon'], $latlon['lat'], 'l') .' AS distance FROM {node} n INNER JOIN {location} l ON n.vid = l.eid WHERE l.type =\'node\' AND l.latitude > '. $latrange[0] .' AND l.latitude < '. $latrange[1] .' AND l.longitude > '. $lonrange[0] .' AND l.longitude < '. $lonrange[1] .' AND '. earth_distance_sql($latlon['lon'], $latlon['lat']) .' < '. $distance_float .' GROUP BY n.nid ORDER by distance';
Ankur Rishi
committed
$result = pager_query(db_rewrite_sql($query), 10, 0, db_rewrite_sql($count_query), $query_args);
$result_count = db_result(db_query(db_rewrite_sql($count_query), $query_args));
if (!$result_count) {
$output = theme('box', t('Your search yielded no results.'), '');
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
$results_offset = isset($_GET['from']) ? $_GET['from'] : 0;
$page_count = db_num_rows($result);
$output = '<p>'. t('Displaying results %a - %b of %count for search on %c', array('%a' => $results_offset + 1, '%b' => $results_offset + $page_count, '%count' => $result_count, '%c' => filter_xss($_GET['postal_code']))) .'</p>';
while ($row = db_fetch_object($result)) {
$extra = array();
unset($location_line);
if ($row->postal_code || $row->city) {
$location_line = t('Local to ');
if ($row->postal_code && $row->city) {
if ($row->postal_code) {
$location_line .= $row->postal_code;
}
if ($row->postal_code && $row->city) {
$location_line .= ' ('. $row->city;
$location_line .= $row->province ? ', '. $row->province : '';
$location_line .= ')';
}
elseif ($row->city) {
$location_line .= $row->city . ($row->province ? ', '. $row->province : '');
}
}
}
if ($location_line) {
$extra['location'] = $location_line;
}
if (($row->postal_code == $location_params['postal_code'] && $row->country == $location_params['country']) ||
($row->distance < 10)) {
$extra['distance'] = t('Result is <strong>also from %postal_code</strong>', array('%postal_code' => $location_params['postal_code']));
}
else {
$adjusted_distance = round($row->distance / (($proximity_params['unit'] == 'km') ? 1000.0 : 1609.347), 1);
if ($adjusted_distance != 1) {
$distance_unit = ($edit['distance_unit'] == 'km') ? t('km') : t('miles');
}
else {
$distance_unit = ($edit['distance_unit'] == 'km') ? t('km') : t('mile');
}
$extra['distance'] = t('Approximately %distance %distanceunit from <strong>%location</strong> ', array('%distance' => round($adjusted_distance, 1), '%distanceunit' => $distance_unit, '%location' => $location_params['postal_code']));
}
$node = node_load($row->nid);
$output .= theme(
'search_item',
array(
'link' => url('node/'. $row->nid),
'title' => $node->title,
'type' => $node->type,
'user' => db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $node->uid)),
'date' => $node->created,
'snippet' => $row->teaser,
'extra' => $extra
),
'node'
);
}
$output .= theme('pager');
return $output;
/**
*
*
*/
function location_map_link_options_page() {
return drupal_get_form('location_map_link_options_form');
}
function location_map_link_options_form() {
$form = array(
);
$form['countries'] = array(
'#type' => 'markup',
'#value' => ''
);
foreach (location_configured_countries() as $country_iso => $country_name) {
$form['countries'][$country_iso] = array(
'#type' => 'markup',
'#value' => ''
);
$form['countries'][$country_iso]['label_'. $country_iso] = array(
'#type' => 'markup',
'#value' => $country_name
);
// Set up '#options' array for mapping providers for the current country
$mapping_options = array();
$provider_function = 'location_map_link_'. $country_iso .'_providers';
$default_provider_function = 'location_map_link_'. $country_iso .'_default_providers';
$checked = variable_get('location_map_link_'. $country_iso, function_exists($default_provider_function) ? $default_provider_function() : array());
//print "Calling provider function $provider_function";
if (function_exists($provider_function)) {
foreach ($provider_function() as $name => $details) {
$mapping_options[$name] = '<a href="'. $details['url'] .'">'. $details['name'] .'</a> (<a href="'. $details['tos'] .'">Terms of Use</a>)';
}
}
if (count($mapping_options)) {
$form['countries'][$country_iso]['location_map_link_'. $country_iso] = array(
'#title' => '',
'#type' => 'checkboxes',
'#default_value' => $checked,
'#options' => $mapping_options
);
}
else {
$form['countries'][$country_iso]['location_map_link_'. $country_iso] = array(
'#type' => 'markup',
'#value' => t('None supported.')
);
}
}
$form['#theme'] = 'location_map_link_options';
return system_settings_form($form);
}
Ankur Rishi
committed
function location_field_names() {
return array('name' => t('Location name'), 'street' => t('Street location'), 'city' => t('City'), 'province' => t('State/Province'), 'postal_code' => t('Postal code'), 'country' => t('Country'));
}
function location_geocoding_parameters_page($country_iso, $service) {
Ankur Rishi
committed
drupal_set_title(t('Configure parameters for %service geocoding', array('%service' => $service)));
$breadcrumbs = drupal_get_breadcrumb();
$breadcrumbs[] = l('location', 'admin/settings/locaiton');
$breadcrumbs[] = l('geocoding', 'admin/settings/location/geocoding');
$countries = location_get_iso3166_list();
$breadcrumbs[] = l($countries[$country_iso], 'admin/settings/location/geocoding', array(), NULL, $country_iso);
drupal_set_breadcrumb($breadcrumbs);
return drupal_get_form('location_geocoding_parameters_form', $country_iso, $service);
}
function location_geocoding_parameters_form($country_iso, $service) {
Ankur Rishi
committed
$geocode_settings_form_function_specific = 'location_geocode_'. $country_iso .'_'. $service .'_settings';
$geocode_settings_form_function_general = $service .'_geocode_settings';
if (function_exists($geocode_settings_form_function_specific)) {
return system_settings_form($geocode_settings_form_function_specific());
}
elseif (function_exists($geocode_settings_form_function_general)) {
return system_settings_form($geocode_settings_form_function_general());
}
else {
return system_settings_form(array(
'#type' => 'markup',
'#value' => t('No configuration parameters are necessary, or a form to take such paramters has not been implemented.')
}
}
function location_geocoding_options_page() {
$iso = arg(4);
$service = arg(5);
if (!empty($iso) || !empty($service)) {
return location_geocoding_parameters_page($iso, $service);
}
return drupal_get_form('location_geocoding_options_form');
}
function location_geocoding_options_form() {
$form = array(
);
Ankur Rishi
committed
// First, we build two arrays to help us figure out on the fly whether a specific country is covered by a multi-country geocoder,
// and what the details of the multi-country geocoder are
// (1) Get list of geocoders
$general_geocoders_list = location_get_general_geocoder_list();
// (2) get data about each geocoder and the list of coutnries covered by each geocoder
$general_geocoders_data = array();
$general_geocoders_countries = array();
foreach ($general_geocoders_list as $geocoder_name) {
include_once LOCATION_PATH .'/geocoding/'. $geocoder_name .'.inc';
Ankur Rishi
committed
$info_function = $geocoder_name .'_geocode_info';
if (function_exists($info_function)) {
$general_geocoders_data[$geocoder_name] = $info_function();
}
$countries_function = $geocoder_name .'_geocode_country_list';
if (function_exists($countries_function)) {
$general_geocoders_countries[$geocoder_name] = $countries_function();
}
}
foreach (location_configured_countries() as $country_iso => $country_name) {
Ankur Rishi
committed
$geocoding_options = array();
$form['countries'][$country_iso] = array(
'#type' => 'markup',
'#value' => ''
);
$form['countries'][$country_iso]['label_'. $country_iso] = array(
'#type' => 'markup',
'#value' => '<div id="'. $country_iso .'">'. $country_name .'</div>'
);
Ankur Rishi
committed
// Next, we look for options presented by country specific providers
$country_specific_provider_function = 'location_geocode_'. $country_iso .'_providers';
if (function_exists($country_specific_provider_function)) {
foreach ($country_specific_provider_function() as $name => $details) {
$geocoding_options[$name . '|'. $country_iso] = '<a href="'. $details['url'] .'">'. $details['name'] .'</a> (<a href="'. $details['tos'] .'">Terms of Use</a>)';
}
}
foreach ($general_geocoders_list as $geocoder_name) {
if (in_array($country_iso, $general_geocoders_countries[$geocoder_name])) {
$geocoding_options[$geocoder_name] = '<a href="'. $general_geocoders_data[$geocoder_name]['url'] .'">'. $general_geocoders_data[$geocoder_name]['name'] .'</a> (<a href="'. $general_geocoder_data[$geocoder_name]['tos'] .'">Terms of Use</a>)';
Ankur Rishi
committed
$geocoding_options = array_merge(array('none' => t('None')), $geocoding_options);
$form['countries'][$country_iso]['location_geocode_'. $country_iso] = array(
'#type' => 'radios',
'#default_value' => variable_get('location_geocode_'. $country_iso, 'none'),
'#options' => $geocoding_options
);
}
else {
$form['countries'][$country_iso]['location_geocode_'. $country_iso] = array(
'#type' => 'markup',
'#value' => t('None supported.')
);
$current_value = variable_get('location_geocode_'. $country_iso, 'none');
if ($current_value == 'none') {
$form['countries'][$country_iso]['location_geocode_config_link_'. $country_iso] = array(
'#type' => 'markup',
'#value' => t('No service selected for country.')
Ankur Rishi
committed
$current_val_chopped = substr($current_value, 0, strpos($current_value, '|'));
$geocode_settings_form_function_specific = 'location_geocode_'. $country_iso .'_'. $current_val_chopped .'_settings';
$geocode_settings_form_function_general = $current_value .'_geocode_settings';
if (function_exists($geocode_settings_form_function_specific)) {
$form['countries'][$country_iso]['location_geocode_config_link_'. $country_iso] = array(
'#type' => 'markup',
'#value' => l(t('Configure parameters'), 'admin/settings/location/geocoding/'. $country_iso .'/'. $current_val_chopped)
);
}
elseif (function_exists($geocode_settings_form_function_general)) {
$form['countries'][$country_iso]['location_geocode_config_link_'. $country_iso] = array(
'#type' => 'markup',
'#value' => l(t('Configure parameters'), 'admin/settings/location/geocoding/'. $country_iso .'/'. $current_value)
);
}
else {
$form['countries'][$country_iso]['location_geocode_config_link_'. $country_iso] = array(
'#type' => 'markup',
'#value' => t('No configuration necessary for selected service.')
);
}
$form['#theme'] = 'location_geocoding_options';
Ankur Rishi
committed
function location_geocoding_options_form_submit($form_id, $form_values) {
$general_geocoders = location_get_general_geocoder_list();
$general_geocoders_in_use = array();
foreach ($form_values as $key => $value) {
if (substr($key, 0, 17) == 'location_geocode_') {
if (in_array($value, $general_geocoders)) {
$general_geocoders_in_use[$value] = $value;
}
}
}
variable_set('location_general_geocoders_in_use', $general_geocoders_in_use);
};
Ankur Rishi
committed
function location_form_alter($form_id, &$form) {
Ankur Rishi
committed
if ($form_id == 'location_geocoding_options_form') {
//$form_exp = var_export($form, TRUE);
//drupal_set_message("\$form == <pre>$form_exp</pre>");
$form['#submit'] = array_merge(array('location_geocoding_options_form_submit' => array(), 'system_settings_form_submit' => array()), $form['#submit'] ? $form['#submit'] : array());
}
elseif ($form_id == 'node_type_form') {
$type = $form['#node_type']->type;
Ankur Rishi
committed
$form['#validate'] = array_merge(
is_array($form['#validate']) ? $form['#validate'] : array(),
array('location_node_settings_validate' => array())
);
Ankur Rishi
committed
$form['location'] = array_merge(
is_array($form['location']) ? $form['location'] : array(),
array(
'#type' => 'fieldset',
'#title' => t('Locative information'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#weight' => 0
)
Ankur Rishi
committed
);
// Variables for how many default location forms should show on edit forms and how many maximum locations can be submitted for this node type
Ankur Rishi
committed
$form['location']['multiple_locations'] = array_merge(
is_array($form['location']['multiple_locations']) ? $form['location']['multiple_locations'] : array(),
array(
'#type' => 'fieldset',
'#title' => t('Number of locations'),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#weight' => 0
)
);
$form['location']['multiple_locations']['location_maxnum'] = array(
'#type' => 'select',
'#title' => t('Maximum number of locations allowed for this type.'),
'#default_value' => variable_get('location_maxnum_'. $type, 0),
'#options' => drupal_map_assoc(range(0,100)),
'#description' => t('This setting determines the maximum number of locations that can be assigned to a node of this type. This number must be greater than or equal to the default number of location forms selected below. By selecting a number greater than zero, users will be able to add a full or partial address(es) to each node of this type (depending on which fields you enable or require below).')
Ankur Rishi
committed
);
$form['location']['multiple_locations']['location_defaultnum'] = array(
'#type' => 'select',
'#title' => t('Default number of location forms'),
'#default_value' => variable_get('location_defaultnum_'. $type, 0),
'#options' => drupal_map_assoc(range(0,10)),
'#description' => t('This setting only applies when you have enabled locations for this node type. It determines how many blank location forms will show up on the original edit-screen for a node of this type. It also only applies when you have enabled a maximum of 1 or more locations to be submitted for this node type.')
);
// End of variables for how many default location forms should show on edit forms and how many maximum locations can be submitted for this node type
$options = array();
for ($i=-10; $i<11; $i++) {
$options[$i] = $i;
}
$form['location']['location_weight'] = array(
Ankur Rishi
committed
'#prefix' => '<div style="margin-left: 40px">',
'#type' => 'select',
'#title' => t('Location weight'),
'#options' => $options,
'#default_value' => variable_get('location_weight_'. $type, 9),
'#description' => t('Weight of the location box in the input form. Lowest values will be displayed higher in the form.')
);
$form['location']['location_collapsible'] = array(
'#type' => 'checkbox',
'#title' => t('Collapsible'),
'#return_value' => 1,
'#default_value' => variable_get('location_collapsible_'. $type, 1),
'#description' => t('Make the location box collapsible.')
);
$form['location']['location_collapsed'] = array(
'#type' => 'checkbox',
'#title' => t('Collapsed'),
'#return_value' => 1,
'#default_value' => variable_get('location_collapsed_'. $type, 1),
'#description' => t('Display the location box collapsed.')
);
$form['location']['location_addanother'] = array(
'#type' => 'checkbox',
'#title' => t('Add another location from node view page'),
'#return_value' => 1,
'#default_value' => variable_get('location_addanother_'. $type, 0),
'#description' => t('Display the "Add another location" option on the node view page.')
);
$form['location']['required_field_notice'] = array(
'#type' => 'markup',
'#value' => '<p><strong>'. t('NOTE:') .'</strong> '. t('Locations fields you choose to require will only be required for the first location if you have allowed more than one location to be submitted for this node type.') .'</p>'
);
$form['location']['location_name'] = array(
Ankur Rishi
committed
'#type' => 'radios',
'#title' => t('Location names'),
'#default_value' => variable_get('location_name_'. $type, $default),
'#options' => array(t('Do not collect location names (e.g. place of business) for this node type.'), t('Allow location names for content of this type.'), t('Require location names for content of this type.'))
);
$form['location']['location_street'] = array(
Ankur Rishi
committed
'#type' => 'radios',
'#title' => t('Street locations'),
'#default_value' => variable_get('location_street_'. $type, $default),
'#options' => array(t('Do not collect a street location for content of this type.'), t('Allow street locations to be submitted for content of this type.'), t('Require street locations to be submitted for content of this type.'))
);
$form['location']['location_city'] = array(
Ankur Rishi
committed
'#type' => 'radios',
'#title' => t('City names'),
'#default_value' => variable_get('location_city_'. $type, 0),
'#options' => array(t('Do not collect city names for content of this type.'), t('Allow city names to be submitted for content of this type.'), t('Require city names to be submitted for content of this type.'))
);
$form['location']['location_province'] = array(
Ankur Rishi
committed
'#type' => 'radios',
'#title' => 'State/Province names',
'#default_value' => variable_get('location_province_'. $type, 0),
'#options' => array(t('Do not collect state/province names for content of this type.'), t('Allow state/province names to be submitted for content of this type.'), t('Require state/province names to be submitted for content of this type.'))
);
$form['location']['location_postal_code'] = array(
Ankur Rishi
committed
'#type' => 'radios',
'#title' => 'Postal codes',
'#default_value' => variable_get('location_postal_code_'. $type, 0),
'#options' => array(t('Do not collect postal codes for content of this type.'), t('Allow postal codes to be submitted for content of this type.'), t('Require postal codes to be submitted for content of this type.'))
);
$form['location']['location_country'] = array(
Ankur Rishi
committed
'#type' => 'radios',
'#title' => 'Country names',
'#default_value' => variable_get('location_country_'. $type, 1),
'#options' => array(1 => t('Allow country names to be submitted for content of this type.'), 2 => t('Require country names to be submitted for content of this type.')),
'#description' => t('The selection of a country can be hidden and/or forced to a default country selection by going to the <a href="@location_settings">location settings page</a> and checking the box marked "Hide country selection" and selecting a country from the drop down select labelled "Default country selection".', array('@location_settings' => url('admin/settings/location'))),
Ankur Rishi
committed
'#suffix' => '</div>'
);
// clear the views cache in case anything was changed
if (function_exists('views_invalidate_cache')) {
views_invalidate_cache();
}
Ankur Rishi
committed
}
elseif (isset($form['type']['#value']) && $form['type']['#value'] .'_node_form' == $form_id && variable_get('location_maxnum_'. $form['type']['#value'], 0)) {
Ankur Rishi
committed
$node = $form['#node'];
Ankur Rishi
committed
$location_fields = array();
$required_fields = array();
foreach (array_keys(location_field_names()) as $field_name) {
$workflow_setting = variable_get('location_'. $field_name .'_'. $node->type, $field_name == 'country' ? 1 : 0);
if ($workflow_setting) {
$location_fields[] = $field_name;
if ($workflow_setting == 2) {
$required_fields[] = $field_name;
}
}
}
$location_form_count = ($node->nid) ? max(count($node->locations), variable_get('location_defaultnum_'. $node->type, 1)) : variable_get('location_defaultnum_'. $node->type, 1);
Ankur Rishi
committed
$form['locations'] = array_merge(
is_array($form['locations']) ? $form['locations'] : array(),
array(
'#type' => 'fieldset',
'#title' => format_plural($location_form_count, 'Location', 'Locations'),
Ankur Rishi
committed
'#tree' => TRUE,
'#attributes' => array_merge(is_array($form['locations']['#attributes']) ? $form['locations']['#attributes'] : array(), array('class' => 'locations')),
'#weight' => variable_get('location_weight_'. $form['type']['#value'], 9),
'#collapsible' => variable_get('location_collapsible_'. $form['type']['#value'], 0) == 0 ? FALSE : TRUE,
'#collapsed' => variable_get('location_collapsed_'. $form['type']['#value'], 0) == 0 ? FALSE : TRUE
)
);
for ($index = 0; $index < $location_form_count; $index++) {
Ankur Rishi
committed
$form['locations'][$index] = array_merge(
is_array($form['locations'][$index]) ? $form['locations'][$index] : array(),
array(
'#type' => 'fieldset',
'#title' => t('Location #%number', array('%number' => $index + 1)),
'#tree' => TRUE,
'#attributes' => array('class' => 'location')
)
);
}
Ankur Rishi
committed
if ($location_form_count == 1) {
$form['locations'][0]['#title'] = t('Location');
}
for ($index = 0; $index < $location_form_count; $index++) {
if (!isset($node->locations[$index]['country']) || $node->locations[$index]['country'] == '') {
$node->locations[$index]['country'] = variable_get('location_default_country', 'us');
}
Ankur Rishi
committed
}
$suppressed_values = variable_get('location_suppress_country', 0) ? array('country' => variable_get('location_default_country', 'us')) : array();
Ankur Rishi
committed
if ($_POST['op'] == t('Preview') || ($_POST['op'] == t('Submit') && form_get_errors())) {
for ($index = 0; $index < $location_form_count; $index++) {
$form['locations'][$index] = array_merge($form['locations'][$index], location_form($location_fields, $node->locations[$index] ? $node->locations[$index] : array(), ($index == 0) ? $required_fields : array(), $suppressed_values));
}
Ankur Rishi
committed
}
else {
for ($index = 0; $index < $location_form_count; $index++) {
if (!isset($form['locations'][$index])) $form['locations'][$index] = array();
$form['locations'][$index] = array_merge($form['locations'][$index], location_form($location_fields, $node->locations[$index] ? location_api2form($node->locations[$index]) : array(), ($index == 0) ? $required_fields : array(), $suppressed_values));
}
Ankur Rishi
committed
}
Ankur Rishi
committed
if (user_access('submit latitude/longitude')) {
for ($index = 0; $index < $location_form_count; $index++) {
$form['locations'][$index][] = array(
'#type' => 'markup',
'#value' => "<br/>\n"
Ankur Rishi
committed
);
if ($node->nid || isset($node->locations[$index]['previous_source'])) {
$form['locations'][$index]['previous_source'] = array(
'#type' => 'hidden',
'#value' => $node->locations[$index]['source']
);
$form['locations'][$index]['previous_latitude'] = array(
'#type' => 'hidden',
'#value' => $node->locations[$index]['latitude']
);
$form['locations'][$index]['previous_longitude'] = array(
'#type' => 'hidden',
'#value' => $node->locations[$index]['longitude']
);
}
Ankur Rishi
committed
$form['locations'][$index] = array_merge($form['locations'][$index], location_latlon_form(t('If you wish to supply your own latitude/longitude, you may do so here. Leaving these fields blank means that the system will determine a latitude/longitude for you, if possible.'), $node->locations[$index] ? location_api2form($node->locations[$index]) : array()));
}
}
// foreach of the locations, make sure we have an lid field
for ($index = 0; $index < $location_form_count; $index++) {
$form['locations'][$index]['lid'] = array(
'#type' => 'hidden',
'#value' => $node->locations[$index]['lid']
);
Ankur Rishi
committed
}
Ankur Rishi
committed
}
}
Ankur Rishi
committed
function location_node_settings_validate($form_id, $form_values) {
$type = $form_values['type'];
$maxnum_name = 'location_maxnum_'. $type;
$defaultnum_name = 'location_defaultnum_'. $type;
if ($form_values[$defaultnum_name] > $form_values[$maxnum_name]) {
form_set_error($defaultnum_name, t("Your default number of location-forms that show up can't be greater than the maximum number of locations allowed for this node type."));
}
if (!$form_values[$defaultnum_name] && $form_values[$maxnum_name]) {
form_set_error($defaultnum_name, t("You must have at least 1 default location-form enabled if you are going to allow locations to be submitted for nodes of this type. If you don't intend to allow locations to be submitted for nodes of this type, set the maximum number of locations allowed for this type to 0."));
}
}
Ankur Rishi
committed
/**
* Implementation of hook_nodeapi().
*/
function location_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
if (!variable_get('location_maxnum_'. $node->type, 0)) {
Ankur Rishi
committed
return;
}
Ankur Rishi
committed
switch ($op) {
case 'validate':
foreach ($node->locations as $index => $location) {
// For now, validation just makes sure that required fields have any value
// If syntax specific checks are implemented for locations in the future, they can be called as well.
foreach (location_field_names() as $field_name => $display_name) {
$workflow_setting = variable_get('location_'. $field_name .'_'. $node->type, $field_name == 'country' ? 1 : 0);
// We only enforce required fields on the first location if there are multiple locations
if ($index == 0) {
if (variable_get('location_'. $field_name .'_'. $node->type, 0) == 2) {
if (isset($node->locations[$index][$field_name]) && !strlen(trim($node->locations[$index][$field_name]))) {
form_set_error('locations]['. $index .']['. $field_name, t('The field %field is required.', array('%field' => $display_name)));
}
}
$node->locations[$index][$field_name] = trim($node->locations[$index][$field_name]);
// Check if the (province, country) pair is valid
if (isset($node->locations[$index]['province']) && !empty($node->locations[$index]['province']) && $node->locations[$index]['province'] != 'xx' &&
isset($node->locations[$index]['country']) && !empty($node->locations[$index]['country']) && $node->locations[$index]['country'] != 'xx') {
$province_list_function = 'location_province_list_'. $node->locations[$index]['country'];
if (function_exists($province_list_function)) {
$translated_location = location_form2api($node->locations[$index]);
if (!in_array($translated_location['province'], array_keys($province_list_function()))) {
form_set_error('locations]['. $index .'][province', t('Please make sure to select a state/province from the country you have selected.'));
}
Ankur Rishi
committed
}
}
// Check if submitted lat/lon are valid
if (user_access('submit latitude/longitude')) {
if ((!strlen(trim($node->locations[$index]['latitude'])) && strlen(trim($node->locations[$index]['longitude']))) ||
(strlen(trim($node->locations[$index]['latitude'])) && !strlen(trim($node->locations[$index]['longitude'])))) {
form_set_error('locations]['. $index .'][latitude', t('You must fill out both longitude and latitude or you must leave them both blank.'));
form_set_error('locations]['. $index .'][longitude', NULL);
Ankur Rishi
committed
}
elseif (strlen(trim($node->locations[$index]['latitude'])) && strlen(trim($node->locations[$index]['longitude']))) {
if (!is_numeric($node->locations[$index]['latitude']) || $node->locations[$index]['latitude'] > 90.0 || $node->locations[$index]['latitude'] < -90.0) {
form_set_error('locations]['. $index .'][latitude', t('Your latitude must be a numeric value between -90.0 and 90.0.'));
}
Ankur Rishi
committed
if (!is_numeric($node->locations[$index]['longitude']) || $node->locations[$index]['longitude'] > 180.0 || $node->locations[$index]['longitude'] < -180.0) {
form_set_error('locations]['. $index .'][longitude', t('Your longitude must be a numeric value between -180.0 and 180.0.'));
}
Ankur Rishi
committed
}
}
}
break;
case 'insert':
case 'update':
// handy to have these field names later
$location_fields = array();
$required_fields = array();
foreach (array_keys(location_field_names()) as $field_name) {
$workflow_setting = variable_get('location_'. $field_name .'_'. $node->type, $field_name == 'country' ? 1 : 0);
if ($workflow_setting) {
$location_fields[] = $field_name;
if ($workflow_setting == 2) {
$required_fields[] = $field_name;
}
}
}
foreach ($node->locations as $index => $location) {
$node->locations[$index] = location_form2api($node->locations[$index]);
if (user_access('submit latitude/longitude')) {
$node->locations[$index]['latitude'] = trim($node->locations[$index]['latitude']);
$node->locations[$index]['longitude'] = trim($node->locations[$index]['longitude']);
// At this point, we know that the user has permission to submit lat/lons and that the
// submitted lat/lons are either blank or valid numbers. Now, we need to find out determine
// the source of these lat/lons since they can either be prefilled from postalcode data
// or manually entered by the user.
if (!empty($node->locations[$index]['latitude']) && !empty($node->locations[$index]['longitude'])) {
if (($data = location_latlon_exact($node->locations[$index])) &&
_location_floats_are_equal(floatval($node->locations[$index]['latitude']), floatval($data['lat'])) &&
_location_floats_are_equal(floatval($node->locations[$index]['longitude']), floatval($data['lon']))) {
$node->locations[$index]['lat'] = $node->locations[$index]['latitude'];
$node->locations[$index]['lon'] = $node->locations[$index]['longitude'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
}
elseif (($data = location_get_postalcode_data($node->locations[$index])) &&
_location_floats_are_equal(floatval($node->locations[$index]['latitude']), floatval($data['lat'])) &&
_location_floats_are_equal(floatval($node->locations[$index]['longitude']), floatval($data['lon']))) {
$node->locations[$index]['lat'] = $node->locations[$index]['latitude'];
$node->locations[$index]['lon'] = $node->locations[$index]['longitude'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
}
else {
$node->locations[$index]['lat'] = $node->locations[$index]['latitude'];
$node->locations[$index]['lon'] = $node->locations[$index]['longitude'];
$node->locations[$index]['source'] = LOCATION_LATLON_USER_SUBMITTED;
}
}
Ankur Rishi
committed
else {
if ($data = location_latlon_exact($node->locations[$index])) {
$node->locations[$index]['latitude'] = $data['lat'];
$node->locations[$index]['longitude'] = $data['lon'];
$node->locations[$index]['lat'] = $data['lat'];
$node->locations[$index]['lon'] = $data['lon'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
}
elseif ($data = location_get_postalcode_data($node->locations[$index])) {
$node->locations[$index]['latitude'] = $data['lat'];
$node->locations[$index]['longitude'] = $data['lon'];
$node->locations[$index]['lat'] = $data['lat'];
$node->locations[$index]['lon'] = $data['lon'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
}
else {
unset($node->locations[$index]['latitude']);
unset($node->locations[$index]['longitude']);
unset($node->locations[$index]['lat']);
unset($node->locations[$index]['lon']);
$node->locations[$index]['source'] = LOCATION_LATLON_UNDEFINED;
}
}
}
else {
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
// If the user does NOT have permission to explicitly set a lat/lon for the given location, we still want to check
// whether this location was previously assigned a lat/lon manually or whether it was determined via geocoding.
// If the lat/lon was determined from geocoding, then we will want to update the lat/lon using postal codes.
// If the lat/lon was user-submitted, then we don't want to allow the current editor to change the lat/lon
if ($node->nid) {
$result = db_query("SELECT * FROM {location} WHERE type = 'node' AND eid = %d", $node->nid);
if ($location = db_fetch_object($result)) {
if ($location->source != LOCATION_LATLON_USER_SUBMITTED) {
if ($data = location_latlon_exact($node->locations[$index])) {
$node->locations[$index]['lat'] = $data['lat'];
$node->locations[$index]['lon'] = $data['lon'];
$node->locations[$index]['latitude'] = $data['lat'];
$node->locations[$index]['longitude'] = $data['lon'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
}
elseif ($data = location_get_postalcode_data($node->location)) {
$node->locations[$index]['lat'] = $data['lat'];
$node->locations[$index]['lon'] = $data['lon'];
$node->locations[$index]['latitude'] = $data['lat'];
$node->locations[$index]['longitude'] = $data['lon'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
}
else {
unset($node->locations[$index]['lat']);
unset($node->locations[$index]['lon']);
unset($node->locations[$index]['latitude']);
unset($node->locations[$index]['longitude']);
$node->locations[$index]['source'] = LOCATION_LATLON_UNDEFINED;
}
}
}
}
elseif ($data = location_latlon_exact($node->locations[$index])) {
$node->locations[$index]['lat'] = $data['lat'];
$node->locations[$index]['lon'] = $data['lon'];
$node->locations[$index]['latitude'] = $data['lat'];
$node->locations[$index]['longitude'] = $data['lon'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_EXACT;
}
elseif ($data = location_get_postalcode_data($node->location)) {
$node->locations[$index]['lat'] = $data['lat'];
$node->locations[$index]['lon'] = $data['lon'];
$node->locations[$index]['latitude'] = $data['lat'];
$node->locations[$index]['longitude'] = $data['lon'];
$node->locations[$index]['source'] = LOCATION_LATLON_GEOCODED_APPROX;
}
else {
unset($node->locations[$index]['lat']);
unset($node->locations[$index]['lon']);
unset($node->locations[$index]['latitude']);
unset($node->locations[$index]['longitude']);
$node->locations[$index]['source'] = LOCATION_LATLON_UNDEFINED;
Ankur Rishi
committed
}
}
// If no city and/or province were supplied in the address (whether the user left it blank or whether the user did not have the option
// of entering them) then we want to use the data we have based strictly on the postal code.
if ($data = location_get_postalcode_data($node->locations[$index])) {
$node->locations[$index]['city'] = (!isset($node->locations[$index]['city']) || strlen($node->locations[$index]['city']) == 0) ? $data['city'] : $node->locations[$index]['city'];
$node->locations[$index]['province'] = (!isset($node->locations[$index]['province']) || strlen($node->locations[$index]['province']) == 0) ? $data['province'] : $node->locations[$index]['province'];
}
// Finally, if there are multiple forms, it's possible for the default country to still be selected with all the other fields blank, and
// very possible that the user didn't intend to fill out that default country value. So, we use the following rules to determine whether
// a location is bogus or not:
// IF $index == 0, then
// --> if no other fields are enabled, we consider the country to be important and save the location
// --> if other fields are enabled, but are all left blank, we consider the location empty and don't save
// --> if latitude and longitude coordinates are entered then we save the location
// IF $index != 1, then
// --> if country is default and no other fields are saved, we don't save
// --> if latitude and longitude coordinates are entered then we save the location
$keep = FALSE;
if (!empty($node->locations[$index]['country']) || (!empty($node->locations[$index]['latitude']) && !empty($node->locations[$index]['longitude']))) {
if ($index == 0) { // first location
if (in_array('country', $required_fields)) {
$keep = TRUE;
}
if (isset($node->locations[$index]['latitude']) && isset($node->locations[$index]['longitude'])) {
$keep = TRUE;
}
elseif (count($location_fields) == 1) {
$keep = TRUE;
}
else {
// Else we have to check all the other fields to make sure they're not empty