function _location_search in Location 6.3
Same name and namespace in other branches
- 5.3 contrib/location_search/location_search.module \_location_search()
- 7.4 contrib/location_search/location_search.module \_location_search()
Implementation of hook_search(). (forwarded from location.module)
1 call to _location_search()
- location.module in ./
location.module - Location module main routines. An implementation of a universal API for location manipulation. Provides functions for postal_code proximity searching, deep-linking into online mapping services. Currently, some options are configured through an…
File
- contrib/
location_search/ location_search.module, line 45 - Location search interface.
Code
function _location_search($op = 'search', $keys = null) {
switch ($op) {
case 'name':
return t('Locations');
case 'reset':
db_query('DELETE FROM {location_search_work}');
db_query('INSERT INTO {location_search_work} (lid) (SELECT lid FROM {location})');
break;
case 'status':
$total = db_result(db_query('SELECT COUNT(lid) FROM {location}'));
$remaining = db_result(db_query('SELECT COUNT(lid) FROM {location_search_work}'));
return array(
'remaining' => $remaining,
'total' => $total,
);
case 'search':
$proximity = FALSE;
$arguments1 = array();
$conditions1 = '1 = 1';
$access_joins = array();
$access_conditions = array();
$has_user_location_access = user_access('access user profiles') && user_access('view all user locations');
$has_content_access = user_access('access content');
if (!$has_user_location_access && !$has_content_access) {
// The user has access to no locations
$conditions1 = '1 = 0';
}
elseif ($has_user_location_access && !$has_content_access) {
// The user doesn't have access to nodes, so include only locations
// that don't belong to nodes
$access_joins[] = ' INNER JOIN {location_instance} li ON (l.lid = li.lid AND li.nid = 0) ';
}
elseif (!$has_user_location_access && $has_content_access) {
// The user doesn't have access to user locations, so include only
// locations that don't belong to users.
// Since this also means we'll need to enforce node access, we'll want
// to include the query fragments returned by _db_rewrite_sql()
$access_joins[] = ' INNER JOIN {location_instance} li ON (l.lid = li.lid AND li.uid = 0) ';
$access_joins[] = ' INNER JOIN {node} n ON (li.nid = n.nid AND n.status = 1) ';
$sql_rewrites = _db_rewrite_sql();
if ($sql_rewrites[0]) {
$access_joins[] = $sql_rewrites[0];
}
if ($sql_rewrites[1]) {
$access_conditions[] = $sql_rewrites[1];
}
}
else {
// The user has access to both. However, for the locations that
// belong to nodes, we want to use the node access sql clauses
// returned by _db_rewrite_sql(). These are the ones with
// location_instance.nid != 0
// location_instance.nid = 0 means the location instance belongs
// to a user record.
$access_joins[] = ' INNER JOIN {location_instance} li ON (l.lid = li.lid) ';
$access_joins[] = ' LEFT JOIN {node} n ON (li.nid = n.nid AND n.status = 1) ';
$sql_rewrites = _db_rewrite_sql();
// If we have rewrite JOINs or WHEREs, restrict the results.
if ($sql_rewrites[0] || $sql_rewrites[1]) {
// The node part must use a sub-select because if the node access
// rewrites get added to the main query there will never be any user
// results because location instance will be inner joined to node
// access.
$access_conditions[] = ' (li.uid <> 0 OR (li.nid <> 0 AND li.nid IN (SELECT n.nid FROM {node} n ' . $sql_rewrites[0] . ($sql_rewrites[1] ? ' WHERE ' . $sql_rewrites[1] : '') . '))) ';
}
}
$access_joins = implode(' ', $access_joins);
$access_conditions = implode(' ', $access_conditions);
// This gets rewritten for proximity searches.
$select2 = 'i.relevance AS score';
$join2 = '';
$sort_parameters = 'ORDER BY score DESC';
if ($country = search_query_extract($keys, 'country')) {
$countries = array();
foreach (explode(',', $country) as $c) {
$countries[] = "l.country = '%s'";
$arguments1[] = $c;
}
$conditions1 .= ' AND (' . implode(' OR ', $countries) . ')';
$keys = search_query_insert($keys, 'country');
}
if ($province = search_query_extract($keys, 'province')) {
$provinces = array();
foreach (explode(',', $province) as $p) {
$provinces[] = "l.province = '%s'";
$arguments1[] = $p;
}
$conditions1 .= ' AND (' . implode(' OR ', $provinces) . ')';
$keys = search_query_insert($keys, 'province');
}
if ($city = search_query_extract($keys, 'city')) {
$city = str_replace('_', ' ', city);
$conditions1 .= " AND (l.city = '%s')";
$arguments1[] = $city;
$keys = search_query_insert($keys, 'city');
}
if ($from = search_query_extract($keys, 'from')) {
// Set up a proximity search.
$proximity = TRUE;
list($lat, $lon, $dist, $unit) = explode(',', $from);
$distance_meters = _location_convert_distance_to_meters($dist, $unit);
// MBR query to make it easier on the database.
$conditions1 .= " AND l.latitude > %f AND l.latitude < %f AND l.longitude > %f AND l.longitude < %f";
$latrange = earth_latitude_range($lon, $lat, $distance_meters);
$lonrange = earth_longitude_range($lon, $lat, $distance_meters);
$arguments1[] = $latrange[0];
$arguments1[] = $latrange[1];
$arguments1[] = $lonrange[0];
$arguments1[] = $lonrange[1];
// Distance query to finish the job.
$conditions1 .= ' AND ' . earth_distance_sql($lon, $lat) . ' < %f';
$arguments1[] = $distance_meters;
// Override the scoring mechanism to use calculated distance
// as the scoring metric.
$join2 = 'INNER JOIN {location} l ON i.sid = l.lid';
$select2 = earth_distance_sql($lon, $lat, 'l') . ' AS distance';
$sort_parameters = 'ORDER BY distance ASC';
$keys = search_query_insert($keys, 'from');
}
if (!empty($access_conditions)) {
$conditions1 = $access_conditions . ' AND ' . $conditions1;
}
$lids = array();
if (empty($keys)) {
// Non-fulltext search. We will be skipping the built-in logic.
$add = '';
if ($proximity) {
$add = ', ' . earth_distance_sql($lon, $lat, 'l') . ' AS distance';
}
$query = "SELECT l.lid{$add} FROM {location} l {$access_joins} WHERE {$conditions1}";
$countquery = "SELECT COUNT(*) FROM {location} l {$access_joins} WHERE {$conditions1}";
$result = pager_query($query, 10, 0, $countquery, $arguments1);
while ($row = db_fetch_object($result)) {
$lids[] = $row->lid;
}
}
else {
// Fuzzy search -- Use the fulltext routines against the indexed locations.
$find = do_search($keys, 'location', 'INNER JOIN {location} l ON l.lid = i.sid ' . $access_joins, $conditions1 . (empty($where1) ? '' : ' AND ' . $where1), $arguments1, $select2, $join2, array(), $sort_parameters);
foreach ($find as $item) {
$lids[] = $item->sid;
}
}
$results = array();
foreach ($lids as $lid) {
$loc = location_load_location($lid);
$result = db_query('SELECT nid, uid FROM {location_instance} WHERE lid = %d', $lid);
$instance_links = array();
while ($row = db_fetch_array($result)) {
$instance_links[] = $row;
}
location_invoke_locationapi($instance_links, 'instance_links');
$results[] = array(
'links' => $instance_links,
'location' => $loc,
);
}
return $results;
}
}