public function views_geojson_bbox_argument::query in Views GeoJSON 7
Same name and namespace in other branches
- 6 views/views_geojson_bbox_argument.inc \views_geojson_bbox_argument::query()
Use the argument to modify the query.
Overrides views_handler_argument::query
File
- views/
views_geojson_bbox_argument.inc, line 60
Class
- views_geojson_bbox_argument
- Custom filter to return only points within a provided bounding box.
Code
public function query($group_by = FALSE) {
// Apply no bbox filtering if the argument is absent or if this is a
// search_api based view (which doesn't support sql specific query changes).
if (empty($this->argument) || $this->view->base_field === 'search_api_id') {
// @TODO: Implement Search API filtering if Solr BBOX is not an option.
// @see: https://www.drupal.org/project/search_api_location_solr_bboxfield
return;
}
$this
->ensure_my_table();
// Process coordinates: split string and make sure coordinates are clean.
$bbox = $this
->_explode_bbox_coords($this->argument);
if (empty($bbox)) {
// Return no values if arg is invalid.
$this->argument = FALSE;
$this->view->built = TRUE;
$this->view->executed = TRUE;
return;
}
if (isset($this->view->display_handler->display->display_options['style_options'])) {
$data_source = $this->view->display_handler->display->display_options['style_options']['data_source'];
}
else {
$data_source = $this->view->display['default']->display_options['style_options']['data_source'];
}
// We handle latlon and geofield data_source types.
// No support yet for WKT.
if ($data_source['value'] === 'latlon') {
$lat_field_obj = $this->view->field[$data_source['latitude']];
$lon_field_obj = $this->view->field[$data_source['longitude']];
$lat_field_table = $lat_field_obj->table;
$lon_field_table = $lon_field_obj->table;
}
elseif ($data_source['value'] === 'geofield') {
// Geofield includes both Lat and Lon fields.
// We pretend they're distinct fields so we can use same code as for
// latlon, since we're just going to get lat & lon from geofield anyway.
$lat_field_obj = $lon_field_obj = $this->view->field[$data_source['geofield']];
$lat_field_table = $lon_field_table = $lat_field_obj->table;
}
else {
// @TODO: Implement WKT (and possibly other data source types).
$this->argument = FALSE;
$this->view->built = TRUE;
$this->view->executed = TRUE;
return;
}
// If the Latitude / Longitude fields are really geofields,
// we need to dig a bit deeper to find field names.
if (isset($lat_field_obj->field_info) && $lat_field_obj->field_info['type'] === 'geofield') {
// @TODO: Maybe the field name can really just be "${lat_field_obj}_lat"?
$lat_field_name = $lat_field_obj->field_info['storage']['details']['sql']['FIELD_LOAD_CURRENT'][$lat_field_table]['lat'];
}
else {
$lat_field_name = $lat_field_obj->real_field;
}
if (isset($lon_field_obj->field_info) && $lon_field_obj->field_info['type'] === 'geofield') {
$lon_field_name = $lon_field_obj->field_info['storage']['details']['sql']['FIELD_LOAD_CURRENT'][$lon_field_table]['lon'];
}
else {
$lon_field_name = $lon_field_obj->real_field;
}
// Add JOIN(s) to query.
$this->query
->ensure_table($lat_field_table);
if ($lon_field_table !== $lat_field_table) {
$this->query
->ensure_table($lon_field_table);
}
// Add WHERE(s) to query.
$left = $bbox['left'];
$bottom = $bbox['bottom'];
$right = $bbox['right'];
$top = $bbox['top'];
if ($this->options['bbox_wrap']) {
// OpenLayers' longitude bbox values can be >180 or <-180 when the map
// wraps around. We need to turn these into BETWEENs with OR.
if ($right - $left < 360) {
$group = $this->query
->set_where_group('AND');
if ($left > -180 && $left <= 180) {
$this->query
->add_where($group, "{$lon_field_table}.{$lon_field_name}", $left, '>=');
}
else {
$this->query
->set_where_group('OR', $group);
$left = ($left + 180) % 360;
if ($left <= 0) {
$left += 360;
}
// -12 % 7 will result in -5 and not 2 as expected
$left -= 180;
$this->query
->add_where($group, "{$lon_field_table}.{$lon_field_name}", array(
$left,
180,
), 'BETWEEN');
}
if ($right > -180 && $right <= 180) {
$this->query
->add_where($group, "{$lon_field_table}.{$lon_field_name}", $right, '<=');
}
else {
$this->query
->set_where_group('OR', $group);
$right = ($right + 180) % 360;
if ($right <= 0) {
$right += 360;
}
// -12 % 7 will result in -5 and not 2 as expected
$right -= 180;
$this->query
->add_where($group, "{$lon_field_table}.{$lon_field_name}", array(
-180,
$right,
), 'BETWEEN');
}
}
}
else {
$group = $this->query
->set_where_group('AND');
$this->query
->add_where($group, "{$lon_field_table}.{$lon_field_name}", $left, '>=');
$this->query
->add_where($group, "{$lon_field_table}.{$lon_field_name}", $right, '<=');
}
$group = $this->query
->set_where_group('AND');
$this->query
->add_where($group, "{$lat_field_table}.{$lat_field_name}", $bottom, '>=');
$this->query
->add_where($group, "{$lat_field_table}.{$lat_field_name}", $top, '<=');
}