/** * Retrieves the metadata for all the supported spatial reference systems. * * @param boolean $refresh Set to true to force a full refresh, otherwise the result is cached. */ public static function system_metadata($refresh = false) { $cacheId = 'spatial-ref-systems'; if ($refresh) { $cache = Cache::instance(); $cache->delete($cacheId); self::$system_metadata = false; } if (self::$system_metadata === false) { $latlong_systems = Kohana::config('sref_notations.lat_long_systems'); $cache = Cache::instance(); if ($cached = $cache->get($cacheId)) { self::$system_metadata = $cached; } else { self::$system_metadata = array(); // fetch any systems that are just declared as srids, with no notation module required foreach (Kohana::config('sref_notations.sref_notations') as $code => $title) { self::$system_metadata["EPSG:{$code}"] = array('title' => $title, 'srid' => $code, 'treat_srid_as_x_y_metres' => !isset($latlong_systems[$code])); } // Now look for any modules which extend the sref systems available foreach (Kohana::config('config.modules') as $path) { $plugin = basename($path); if (file_exists("{$path}/plugins/{$plugin}.php")) { require_once "{$path}/plugins/{$plugin}.php"; if (function_exists($plugin . '_sref_systems')) { $metadata = call_user_func($plugin . '_sref_systems'); self::$system_metadata = array_merge(self::$system_metadata, $metadata); } } } $cache->set($cacheId, self::$system_metadata); } } return self::$system_metadata; }
/** * Postprocessing for building a geom from the list of grid squares to make an SQL based check easy */ function data_cleaner_without_polygon_data_cleaner_postprocess($id, $db) { $db->query('create temporary table geoms_without_polygon (geom geometry)'); try { $r = $db->select('key, header_name')->from('verification_rule_data')->where('verification_rule_id', $id)->in('header_name', array('10km_GB', '10km_Ireland', '1km_GB', '1km_Ireland', '10km_CI', '1km_CI'))->get()->result(); $wktList = array(); foreach ($r as $gridSquare) { switch ($gridSquare->header_name) { case '10km_GB': case '1km_GB': $system = 'osgb'; break; case '10km_Ireland': case '1km_Ireland': $system = 'osie'; break; case '10km_CI': case '1km_CI': $system = 'utm30ed50'; break; default: continue; // we don't know this grid square type - should not have come back from the query } $srid = kohana::config('sref_notations.internal_srid'); try { $wktList[] = "(st_geomfromtext('" . spatial_ref::sref_to_internal_wkt($gridSquare->key, $system) . "', {$srid}))"; } catch (Exception $e) { kohana::debug('alert', 'Did not import grid square ' . $gridSquare->key . " for rule {$id}"); error::log_error('Importing without polygon rules', $e); } } if (!empty($wktList)) { $db->query("insert into geoms_without_polygon values " . implode(',', $wktList)); } $date = date("Ymd H:i:s"); $uid = $_SESSION['auth_user']->id; $db->query("delete from verification_rule_data where verification_rule_id={$id} and header_name='geom'"); $db->query('insert into verification_rule_data (verification_rule_id, header_name, data_group, key, value, value_geom, created_on, created_by_id, updated_on, updated_by_id) ' . "select {$id}, 'geom', 1, 'geom', '-', st_union(geom), '{$date}', {$uid}, '{$date}', {$uid} from geoms_without_polygon"); $db->query('drop table geoms_without_polygon'); } catch (Exception $e) { $db->query('drop table geoms_without_polygon'); throw $e; } }
/** * Fills the temporary table called occdelta, which contains details of each proposed record to * verify. This is only done when calling verify directly, since occdelta is prepared by the * scheduled_tasks process when auto-checks are being run on the schedule. */ private function prepareOccdelta($db, $sample, $occurrences) { $website_id = $this->website_id; $srid = kohana::config('sref_notations.internal_srid'); $last_sref = ''; $last_sref_system = ''; foreach ($occurrences as $occurrence) { $record = array_merge($sample, $occurrence); $survey_id = $record['sample:survey_id']; $sref = $record['sample:entered_sref']; $sref_system = $record['sample:entered_sref_system']; $taxa_taxon_list_id = $record['occurrence:taxa_taxon_list_id']; if (isset($record['sample:geom'])) { $geom = $record['sample:geom']; } else { // avoid recalculating the geom if we don't have to as this is relatively expensive if ($sref !== $last_sref || $sref_system !== $last_sref_system) { $geom = spatial_ref::sref_to_internal_wkt($sref, $sref_system); } $last_sref = $sref; $last_sref_system = $sref_system; } $date = $record['sample:date']; $vd = vague_date::string_to_vague_date($date); $date_start = $vd[0]; $date_end = $vd[1]; $date_type = $vd[2]; $db->query("insert into occdelta (website_id, survey_id, date_start, date_end, date_type, public_entered_sref, entered_sref_system, public_geom, taxa_taxon_list_id)\n values ({$website_id}, {$survey_id}, '{$date_start}', '{$date_end}', '{$date_type}', '{$sref}', '{$sref_system}', st_geomfromtext('{$geom}', {$srid}), {$taxa_taxon_list_id});"); } // patch in some extra details about the taxon required for each cache entry $db->query("update occdelta o set taxon_meaning_id=ttl.taxon_meaning_id, taxon=ttl.taxon, taxa_taxon_list_external_key=ttl.external_key " . "from list_taxa_taxon_lists ttl where ttl.id=o.taxa_taxon_list_id"); }
/** * Define a form that is used to capture a set of predetermined values that apply to every record during an import. */ public function fixed_values_form() { $srefs = array(); $systems = spatial_ref::system_metadata(); foreach ($systems as $code => $metadata) { $srefs[] = "{$code}:" . $metadata['title']; } return array('website_id' => array('display' => 'Website', 'description' => 'Select the website to import records into.', 'datatype' => 'lookup', 'population_call' => 'direct:website:id:title'), 'location:centroid_sref_system' => array('display' => 'Spatial Ref. System', 'description' => 'Select the spatial reference system used in this import file. Note, if you have a file with a mix of spatial reference systems then you need a ' . 'column in the import file which is mapped to the Location Spatial Reference System field containing the spatial reference system code.', 'datatype' => 'lookup', 'lookup_values' => implode(',', $srefs))); }
/** * The upgrade might involve a change to spatial system support in plugins, so now is a good * time to refresh the spatial_systems metadata table. */ private function populate_spatial_systems_table() { $system_metadata = spatial_ref::system_metadata(true); $existing = $this->db->select('id', 'code')->from('spatial_systems')->get()->result_array(false); foreach ($system_metadata as $system => $metadata) { $id = false; foreach ($existing as $idx => $record) { if ($record['code'] === $system) { // record already exists $id = $record['id']; unset($existing[$idx]); break; } } $metadata['treat_srid_as_x_y_metres'] = isset($metadata['treat_srid_as_x_y_metres']) && $metadata['treat_srid_as_x_y_metres'] ? 't' : 'f'; if ($id) { $this->db->update('spatial_systems', array_merge($metadata, array('code' => $system)), array('id' => $id)); } else { $this->db->insert('spatial_systems', array_merge($metadata, array('code' => $system))); } } // delete any that remain in $existing, since they are no longer supported foreach ($existing as $idx => $record) { $this->db->delete('spatial_systems', array('id' => $record['id'])); } }
/** * Define a form that is used to capture a set of predetermined values that apply to every record during an import. */ public function fixed_values_form() { $srefs = array(); $systems = spatial_ref::system_metadata(); foreach ($systems as $code => $metadata) { $srefs[] = "{$code}:" . $metadata['title']; } return array('website_id' => array('display' => 'Website', 'description' => 'Select the website to import records into.', 'datatype' => 'lookup', 'population_call' => 'direct:website:id:title'), 'survey_id' => array('display' => 'Survey', 'description' => 'Select the survey to import records into.', 'datatype' => 'lookup', 'population_call' => 'direct:survey:id:title', 'linked_to' => 'website_id', 'linked_filter_field' => 'website_id'), 'sample:entered_sref_system' => array('display' => 'Spatial Ref. System', 'description' => 'Select the spatial reference system used in this import file. Note, if you have a file with a mix of spatial reference systems then you need a ' . 'column in the import file which is mapped to the Sample Spatial Reference System field containing the spatial reference system code.', 'datatype' => 'lookup', 'lookup_values' => implode(',', $srefs)), 'fkFilter:taxa_taxon_list:taxon_list_id' => array('display' => 'Species list', 'description' => 'Select the species checklist which will be used when attempting to match species names.', 'datatype' => 'lookup', 'population_call' => 'direct:taxon_list:id:title', 'linked_to' => 'website_id', 'linked_filter_field' => 'website_id'), 'occurrence:record_status' => array('display' => 'Record Status', 'description' => 'Select the initial status for imported records', 'datatype' => 'lookup', 'lookup_values' => 'C:Data entry complete/unverified,V:Verified,I:Data entry still in progress', 'default' => 'C')); }
/** * Define a form that is used to capture a set of predetermined values that apply to every record during an import. */ public function fixed_values_form() { $srefs = array(); $systems = spatial_ref::system_list(); foreach ($systems as $code => $title) { $srefs[] = "{$code}:{$title}"; } $retVal = array('website_id' => array('display' => 'Website', 'description' => 'Select the website to import records into.', 'datatype' => 'lookup', 'population_call' => 'direct:website:id:title', 'filterIncludesNulls' => true), 'survey_id' => array('display' => 'Survey', 'description' => 'Select the survey to import records into.', 'datatype' => 'lookup', 'population_call' => 'direct:survey:id:title', 'linked_to' => 'website_id', 'linked_filter_field' => 'website_id'), 'sample:entered_sref_system' => array('display' => 'Spatial Ref. System', 'description' => 'Select the spatial reference system used in this import file. Note, if you have a file with a mix of spatial reference systems then you need a ' . 'column in the import file which is mapped to the Sample Spatial Reference System field containing the spatial reference system code.', 'datatype' => 'lookup', 'lookup_values' => implode(',', $srefs)), 'occurrence:fkFilter:taxa_taxon_list:taxon_list_id' => array('display' => 'Species list', 'description' => 'Select the species checklist which will be used when attempting to match species names.', 'datatype' => 'lookup', 'population_call' => 'direct:taxon_list:id:title', 'linked_to' => 'website_id', 'linked_filter_field' => 'website_id', 'filterIncludesNulls' => true), 'occurrence:record_status' => array('display' => 'Record Status', 'description' => 'Select the initial status for imported species records', 'datatype' => 'lookup', 'lookup_values' => 'C:Data entry complete/unverified,V:Verified,I:Data entry still in progress', 'default' => 'C')); if (self::_check_module_active('occurrence_associations')) { $retVal['useAssociations'] = array('display' => 'Use Associations', 'description' => 'Select if this import uses occurrence associations: implies two species records uploaded for each entry in the file.', 'datatype' => 'checkbox'); } // default off $retVal['occurrence_association:fkFilter:association_type:termlist_id'] = array('display' => 'Term list for association types', 'description' => 'Select the term list which will be used to match the association types.', 'datatype' => 'lookup', 'population_call' => 'direct:termlist:id:title'); $retVal['occurrence_2:fkFilter:taxa_taxon_list:taxon_list_id'] = array('display' => 'Second Species list', 'description' => 'Select the species checklist which will be used when attempting to match second species names.', 'datatype' => 'lookup', 'population_call' => 'direct:taxon_list:id:title', 'linked_to' => 'website_id', 'linked_filter_field' => 'website_id', 'filterIncludesNulls' => true); $retVal['occurrence_2:record_status'] = array('display' => 'Record Status', 'description' => 'Select the initial status for second imported species records', 'datatype' => 'lookup', 'lookup_values' => 'C:Data entry complete/unverified,V:Verified,I:Data entry still in progress', 'default' => 'C'); return $retVal; }
<div id="details"> <?php echo $metadata; ?> <fieldset> <legend>Location details</legend> <input type="hidden" name="location:id" value="<?php echo html::initial_value($values, 'location:id'); ?> " /> <?php echo data_entry_helper::text_input(array('label' => 'Name', 'fieldname' => 'location:name', 'default' => html::initial_value($values, 'location:name'), 'validation' => 'required', 'disabled' => $disabled)); echo data_entry_helper::text_input(array('label' => 'Code', 'fieldname' => 'location:code', 'default' => html::initial_value($values, 'location:code'), 'disabled' => $disabled)); echo data_entry_helper::select(array('label' => 'Type', 'fieldname' => 'location:location_type_id', 'default' => html::initial_value($values, 'location:location_type_id'), 'lookupValues' => $other_data['type_terms'], 'blankText' => '<Please select>', 'disabled' => $disabled)); echo data_entry_helper::textarea(array('label' => 'Comment', 'fieldname' => 'location:comment', 'default' => html::initial_value($values, 'location:comment'), 'disabled' => $disabled)); echo data_entry_helper::sref_and_system(array('label' => 'Spatial Ref', 'fieldname' => 'location:centroid_sref', 'geomFieldname' => 'location:centroid_geom', 'default' => html::initial_value($values, 'location:centroid_sref'), 'defaultGeom' => html::initial_value($values, 'location:centroid_geom'), 'systems' => spatial_ref::system_list(), 'defaultSystem' => html::initial_value($values, 'location:centroid_sref_system'), 'class' => 'control-width-3', 'validation' => 'required', 'disabled' => $disabled)); ?> <input type="hidden" name="location:boundary_geom" id="imp-boundary-geom" value="<?php echo $boundary_geom; ?> "/> <p class="instruct">Zoom the map in by double-clicking then single click on the location's centre to set the spatial reference. The more you zoom in, the more accurate the reference will be.</p> <?php $readAuth = data_entry_helper::get_read_auth(0 - $_SESSION['auth_user']->id, kohana::config('indicia.private_key')); echo map_helper::map_panel(array('readAuth' => $readAuth, 'presetLayers' => array('osm'), 'editLayer' => true, 'layers' => array(), 'initial_lat' => 52, 'initial_long' => -2, 'initial_zoom' => 7, 'width' => 870, 'height' => 400, 'initialFeatureWkt' => $centroid_geom, 'standardControls' => $disabled_input === 'YES' ? array('layerSwitcher', 'panZoomBar') : array('layerSwitcher', 'panZoomBar', 'drawPolygon', 'drawLine', 'modifyFeature'), 'allowPolygonRecording' => true)); echo data_entry_helper::autocomplete(array('label' => 'Parent location', 'fieldname' => 'location:parent_id', 'table' => 'location', 'captionField' => 'name', 'valueField' => 'id', 'extraParams' => $readAuth, 'default' => html::initial_value($values, 'location:parent_id'), 'defaultCaption' => html::initial_value($values, 'parent:name'), 'disabled' => $disabled)); if ($this->auth->logged_in('CoreAdmin')) { //Only core admin can create public locations. echo data_entry_helper::checkbox(array('label' => 'Available to all websites', 'fieldname' => 'location:public', 'default' => html::initial_value($values, 'location:public'), 'disabled' => $disabled)); }
/** * Allow a service request to triangulate between 2 systems. GET parameters are: * from_sref * from_system * to_system * to_precision (optional) */ public function convert_sref() { try { $wkt = spatial_ref::sref_to_internal_wkt($_GET['from_sref'], $_GET['from_system']); if (array_key_exists('precision', $_GET)) { $precision = $_GET['precision']; } else { $precision = null; } if (array_key_exists('metresAccuracy', $_GET)) { $metresAccuracy = $_GET['metresAccuracy']; } else { $metresAccuracy = null; } echo spatial_ref::internal_wkt_to_sref($wkt, $_GET['to_system'], $precision, null, $metresAccuracy); } catch (Exception $e) { $this->handle_error($e); } }
/** * Define a form that is used to capture a set of predetermined values that apply to every record during an import. */ public function fixed_values_form() { $srefs = array(); $systems = spatial_ref::system_list(); foreach ($systems as $code => $title) { $srefs[] = "{$code}:{$title}"; } $sample_methods = array(":Defined in file"); $terms = $this->db->select('id, term')->from('list_termlists_terms')->where('termlist_external_key', 'indicia:sample_methods')->orderby('term', 'asc')->get()->result(); foreach ($terms as $term) { $sample_methods[] = $term->id . ":" . $term->term; } $location_types = array(":No filter"); $terms = $this->db->select('id, term')->from('list_termlists_terms')->where('termlist_external_key', 'indicia:location_types')->orderby('term', 'asc')->get()->result(); foreach ($terms as $term) { $location_types[] = $term->id . ':' . $term->term; } return array('website_id' => array('display' => 'Website', 'description' => 'Select the website to import records into.', 'datatype' => 'lookup', 'population_call' => 'direct:website:id:title'), 'survey_id' => array('display' => 'Survey', 'description' => 'Select the survey to import records into.', 'datatype' => 'lookup', 'population_call' => 'direct:survey:id:title', 'linked_to' => 'website_id', 'linked_filter_field' => 'website_id'), 'sample:entered_sref_system' => array('display' => 'Spatial Ref. System', 'description' => 'Select the spatial reference system used in this import file. Note, if you have a file with a mix of spatial reference systems then you need a ' . 'column in the import file which is mapped to the Sample Spatial Reference System field containing the spatial reference system code.', 'datatype' => 'lookup', 'lookup_values' => implode(',', $srefs)), 'sample:sample_method_id' => array('display' => 'Sample Method', 'description' => 'Select the sample method used for records in this import file. Note, if you have a file with a mix of sample methods then you need a ' . 'column in the import file which is mapped to the Sample Sample Method field, containing the sample method.', 'datatype' => 'lookup', 'lookup_values' => implode(',', $sample_methods)), 'fkFilter:location:location_type_id' => array('display' => 'Location Type', 'description' => 'If this import file includes samples which reference locations records, you can restrict the type of locations looked ' . 'up by setting this location type. It is not currently possible to use a column in the file to do this on a sample by sample basis.', 'datatype' => 'lookup', 'lookup_values' => implode(',', $location_types))); }
/** * Before submission, map vague dates to their underlying database fields. */ protected function preSubmit() { if (array_key_exists('date', $this->submission['fields'])) { $vague_date = vague_date::string_to_vague_date($this->submission['fields']['date']['value']); $this->submission['fields']['date_start']['value'] = $vague_date[0]; $this->submission['fields']['date_end']['value'] = $vague_date[1]; $this->submission['fields']['date_type']['value'] = $vague_date[2]; } // Allow a sample to be submitted with a spatial ref and system but no Geom. If so we // can work out the Geom if (array_key_exists('entered_sref', $this->submission['fields']) && array_key_exists('entered_sref_system', $this->submission['fields']) && !(array_key_exists('geom', $this->submission['fields']) && $this->submission['fields']['geom']['value']) && $this->submission['fields']['entered_sref']['value'] && $this->submission['fields']['entered_sref_system']['value']) { try { $this->submission['fields']['geom']['value'] = spatial_ref::sref_to_internal_wkt($this->submission['fields']['entered_sref']['value'], $this->submission['fields']['entered_sref_system']['value']); } catch (Exception $e) { $this->errors['entered_sref'] = $e->getMessage(); } } return parent::presubmit(); }
/** * Validate a spatial reference is a valid value for the system * * @param string sref * @param string system * @return boolean * $todo Should we consider caching the system? */ public static function sref($sref, $system) { $system = $system[0]; return spatial_ref::is_valid($sref, $system); }