Value pairs. // For each database field, the type is stored under the key _postgres_quotation private $expeditionMappingArray; private $itineraryMappingArray; private $sectionMappingArray; private $eventMappingArray; private $georeferenceMappingArray; // fillingArrays : database field names and their value, stored as Name => Value pairs, // for constructing the SQL statements. // After every store operation, the fillingArray for that should be reset. private $expeditionFillingArray; private $itineraryFillingArray; private $sectionFillingArray; private $eventFillingArray; private $georeferenceFillingArray; //**************************************************************************************** // constructor // with a lot of initialisations, and a database connection as well //**************************************************************************************** function __construct() { // database connection parameters initialisation $this->databaseHost = "localhost"; $this->databaseName = "synthesys"; $this->databaseUser = "postgres"; $this->databasePassword = "postgres"; $this->databaseConnect=''; $this->databaseQuery = ""; $this->class_field_name = ""; $this->class_field_value = ""; $this->return_string = ""; // mappingArray initialisations // maps all the class variable names to their database field names. // under _postgres_quotation, we indicate whether PostGreSQL // wants the value quoted or not. $this->expeditionMappingArray= array( "expeditionID" => "expedition_key", "expeditionID_postgres_quotation" => "noquotes", "expeditionStart_YYYYMMDD" => "expedition_start", "expeditionStart_YYYYMMDD_postgres_quotation" => "quotes", "expeditionEnd_YYYYMMDD" => "expedition_end", "expeditionEnd_YYYYMMDD_postgres_quotation" => "quotes"); $this->itineraryMappingArray= array( "itineraryID" => "itinerary_key", "itineraryID_postgres_quotation" => "noquotes", "itineraryExpeditionID" => "itinerary_expedition_fkey", "itineraryExpeditionID_postgres_quotation" => "noquotes", "itinerarySequenceNumber" => "itinerary_sequence_number", "itinerarySequenceNumber_postgres_quotation" => "noquotes", "itineraryPossibilityNumber" => "itinerary_possibility_number", "itineraryPossibilityNumber_postgres_quotation" => "noquotes"); $this->sectionMappingArray= array( "sectionID" => "section_key", "sectionID_postgres_quotation" => "noquotes", "sectionItineraryID" => "section_itinerary_fkey", "sectionItinerary_postgres_quotation" => "noquotes", "sectionBeginEventID" => "section_begin_event_fkey", "sectionBeginEventID_postgres_quotation" => "noquotes", "sectionEndEventID" => "section_end_event_fkey", "sectionEndEventID_postgres_quotation" => "noquotes"); $this->eventMappingArray= array( "eventID" => "expedition_event_key", "eventID_postgres_quotation" => "noquotes", "eventGeoreferenceID" => "expedition_event_georeference_fkey", "eventGeoreferenceID_postgres_quotation" => "noquotes", "eventSequenceNumber" => "expedition_event_sequence_number", "eventSequenceNumber_postgres_quotation" => "noquotes"); $this->georeferenceMappingArray= array( "georeferenceID" => "georeference_key", "georeferenceID_postgres_quotation" => "noquotes", "georeferenceDecimalLatitude" =>"georeference_decimal_latitude", "georeferenceDecimalLatitude_postgres_quotation" => "noquotes", "georeferenceDecimalLongitude" =>"georeference_decimal_longitude", "georeferenceDecimalLongitude_postgres_quotation" => "noquotes", "georeferenceUncertainty" => "georeference_net_uncertainty", "georeferenceUncertainty_postgres_quotation" => "noquotes", "georeferencePointGeometry" => "georeference_geom_point", "georeferencePointGeometry_postgres_quotation" => "quotes", "georeferenceOutlineGeometry" => "georeference_geom_outline", "georeferenceOutlineGeometry_postgres_quotation" => "quotes", "georeferenceCircleGeometry" => "georeference_geom_circle", "georeferenceCircleGeometry_postgres_quotation" => "quotes"); //setGeoreferencePointLatitude : controles inbouwen ! // check minima and maxima for latitude and longitude // we do this because PostGIS doesn't give any problems for out-of-range // coordinates like (-246,-93) /* if ( ($pointLongitude<=180 && $pointLongitude >= -180) && ($pointLatitude<=90 && $pointLatitude >= -90) ) { */ // resetFillingArray functions : define the arrays and // set them to their default values. $this->resetExpeditionFillingArray(); $this->resetItineraryFillingArray(); $this->resetSectionFillingArray(); $this->resetEventFillingArray(); $this->resetGeoreferenceFillingArray(); // Connecting to PostGreSQL, selecting database $this->databaseConnect = pg_connect( "host = $this->databaseHost dbname = $this->databaseName user = $this->databaseUser password = $this->databasePassword" ) or die('** Could not connect to PostGreSQL database ** ' ."host: ". $this->databaseHost ."\n" ." database: ".$this->databaseName ."\n" ." user: ".$this->databaseUser ."\n" ." last PostgreSQL error: ".pg_last_error() ); // echo ($this->makeSingleQuotedString("'amehoela'")); } // here endeth the constructor ! //**************************************************************************************** // destructor //**************************************************************************************** function __destruct() { } public function writePointsToDatabase($points_array) { // make a new database connection //$myDatabase = new Database(); //clear the whole table REMOVE ?????????????????????????? $this->clearDatabaseGeoreferenceTable(); $this->point_count=0; foreach ($points_array ["unique_id_array"] as $dummy) { $this->fillDatabaseGeoreferenceTable('georeferenceID',$this->point_count); $this->fillDatabaseGeoreferenceTable('georeferenceDecimalLatitude', $points_array ["latitude_array"][$this->point_count]) ; $this->fillDatabaseGeoreferenceTable('georeferenceDecimalLongitude', $points_array ["longitude_array"][$this->point_count]) ; // TODO : set the default accuracy in a better spot, not here if ($points_array ["coord_accuracy_array"][$this->point_count]) { $this->fillDatabaseGeoreferenceTable('georeferenceUncertainty', $points_array ["coord_accuracy_array"][$this->point_count]) ; } else { $this->fillDatabaseGeoreferenceTable('georeferenceUncertainty',0.002) ; } $this->storeDatabaseGeoreferenceTable(); $this->point_count++; } //foreach $this->return_string = "Points are stored in database"; return ($this->return_string); } // function writePointsToDatabase //**************************************************************************************** // fillDatabasetTable functions // maps the class variable's name and value to the database field, in preparation of an // SQL store operation. //**************************************************************************************** public function fillDatabaseExpeditionTable($class_field_name,$class_field_value) { // given class variable name is not found as a key in the mapping table if (array_key_exists($class_field_name, $this->expeditionMappingArray)) { // no problems. Field value is stored in the fillingArray, at the key of the // database field name. The mappingArray is used to make the conversion // from class variable name to database field name. $this->expeditionFillingArray [$this->expeditionMappingArray[$class_field_name]] = $class_field_value; $this->return_string = "$class_field_name" . " is set to " . $this->expeditionFillingArray [$this->expeditionMappingArray[$class_field_name]]; } else { $this->return_string = 'ERROR : ' . $class_field_name . ' is not recognised as a valid name for a class member (field, variable) AND/OR is not mapped to a valid database field within the "Expedition" mapping. Check 1/ the spelling of the class member name 2/ whether you are using the correct database table function 3/ whether or not the class member is defined in the mapping table in the Database class.'; } return ($this->return_string ); } public function fillDatabaseItineraryTable($class_field_name,$class_field_value) { // given class variable name is not found as a key in the mapping table if (array_key_exists($class_field_name, $this->itineraryMappingArray)) { // no problems. Field value is stored in the fillingArray, at the key of the // database field name. The mappingArray is used to make the conversion // from class variable name to database field name. $this-> itineraryFillingArray [$this->itineraryMappingArray[$class_field_name] ] = $this->class_field_value; $this->return_string = "$class_field_name" . " is set to " . $this->itineraryFillingArray [$this->itineraryMappingArray[$class_field_name] ] ; } else { $this->return_string = 'ERROR : ' . $class_field_name . ' is not recognised as a valid name for a class member (field, variable) AND/OR is not mapped to a valid database field within the "Itinerary" mapping. Check 1/ the spelling of the class member name 2/ whether you are using the correct database table function 3/ whether or not the class member is defined in the mapping table in the Database class.'; } return ($this->return_string ); } public function fillDatabaseSectionTable($class_field_name,$class_field_value) { // check whether given class variable name exists as a key in the mapping table if (array_key_exists($class_field_name, $this->sectionMappingArray)) { // given class variable name is valid. // Field value is now stored in the fillingArray, at the key of the database field name. // note that the mappingArray is used to make the conversion from class variable // name to database field name. $this-> sectionFillingArray [$this->sectionMappingArray[$class_field_name] ] = $class_field_value; $this->return_string = "$class_field_name" . " is set to " . $this->sectionFillingArray [$this->sectionMappingArray[$class_field_name] ] ; } else { $this->return_string = 'ERROR : ' . $class_field_name . ' is not recognised as a valid name for a class member (field, variable) AND/OR is not mapped to a valid database field within the "Section" mapping. Check (1) the spelling of the class member name. (2) whether you are using the correct database table function. (3) whether or not the class member is defined in the mapping table in the Database class.'; } return ($this->return_string); } public function fillDatabaseEventTable($class_field_name,$class_field_value) { // check whether given class variable name existsas a key in the mapping table if (array_key_exists($class_field_name, $this->eventMappingArray)) { // given class variable name is valid. // Field value is now stored in the fillingArray, at the key of the database field name. // note that the mappingArray is used to make the conversion from class variable // name to database field name. $this-> eventFillingArray [$this->eventMappingArray[$class_field_name] ] = $class_field_value; $this->return_string = "$class_field_value" . " is set to " . $this->eventFillingArray[$this->eventMappingArray[$class_field_name] ] ; } else { $this->return_string = 'ERROR : ' . $class_field_name . ' is not recognised as a valid name for a class member (field, variable) AND/OR is not mapped to a valid database field within the "Event" mapping. Check (1) the spelling of the class member name (2) whether you are using the correct database table function (3) whether or not the class member is defined in the mapping table in the Database class.'; } return ($this->return_string ); } public function fillDatabaseGeoreferenceTable($class_field_name,$class_field_value) { // check whether given class variable name existsas a key in the mapping table if (array_key_exists($class_field_name, $this->georeferenceMappingArray)) { // given class variable name is valid. // Field value is now stored in the fillingArray, at the key of the database field name. // note that the mappingArray is used to make the conversion from class variable // name to database field name. $this-> georeferenceFillingArray [$this->georeferenceMappingArray[ $class_field_name] ] = $class_field_value; $this->return_string = "$class_field_name" . " is set to " . $this->georeferenceFillingArray[$this->georeferenceMappingArray[$class_field_name] ] ; } else { $this->return_string = 'ERROR : ' . $class_field_name . ' is not recognised as a valid name for a class member (field, variable) AND/OR is not mapped to a valid database field within the "Georeference" mapping. Check 1/ the spelling of the class member name 2/ whether you are using the correct database table function 3/ whether or not the class member is defined in the mapping table in the Database class.'; } return ($this->return_string ); } //**************************************************************************************** // storeDatabaseTable functions // store the database fields filled with the fillDatabaseTable functions in the database. // Note that these functions are stritcly limited to first-time store commands, they cannot // be used for updates. //**************************************************************************************** public function storeDatabaseExpeditionTable() { $this->databaseQuery = "INSERT INTO expedition(" . $this->arrayKeysAsCommaSeparatedString($this->expeditionFillingArray) . ") values (" . $this->arrayValuesAsCommaSeparatedString($this->expeditionFillingArray) . ") ;"; $this->databaseResult = pg_query($this->databaseQuery) or die('** Query failed ** ' . "query: " . " $this->databaseQuery " . " last error: " . pg_last_error()); // clean up after store $this->resetExpeditionFillingArray() ; } public function storeDatabaseItineraryTable() { // clean up after store $this->resetItineraryFillingArray() ; } public function storeDatabaseSectionTable() { // clean up after store $this->resetSectionFillingArray() ; } public function storeDatabaseEventTable() { $this->databaseQuery = "INSERT INTO event(" . $this->arrayKeysAsCommaSeparatedString($this->eventFillingArray) . ") values (" . $this->arrayValuesAsCommaSeparatedString($this->eventFillingArray) . ") ;"; $this->databaseResult = pg_query($this->databaseQuery) or die('** Query failed ** ' . "query: " . " $this->databaseQuery " . " last error: " . pg_last_error()); // clean up after store $this->resetEventFillingArray() ; } // for testing purposes, REMOVE BEFORE FLIGHT !!!!!!!!!!!!!!!!!!!!!! public function clearDatabaseGeoreferenceTable() { // REMOVE $this->databaseQuery = "DELETE FROM georeference"; // REMOVE //add "where" clause on userID $this->databaseResult = pg_query($this->databaseQuery) // REMOVE or die('** Query failed ** ' // REMOVE . "query: " // REMOVE . $this->databaseQuery // REMOVE . " last error: " // REMOVE . pg_last_error()); // REMOVE return(0); // REMOVE } // clear db georeference REMOVE public function storeDatabaseGeoreferenceTable() { if ( ($this->georeferenceFillingArray["georeference_decimal_latitude"] <-90) or ($this->georeferenceFillingArray["georeference_decimal_latitude"] >90) or ($this->georeferenceFillingArray["georeference_decimal_longitude"] <-180) or ($this->georeferenceFillingArray["georeference_decimal_longitude"] >180) ){ $this->return_string = 'ERROR : coordinate values for georeference do not lie within the valid range (-90 < latitude < 90 / -180 < longitude < 180)'; } else { // ******* Construction of PostGIS well-known text (WKT) for POINT ******** // We know we have valid lat/long values here // so point geometry can safely be constructed. $this->pointGeometry = "GeomFromText('POINT(" . $this->georeferenceFillingArray["georeference_decimal_longitude"] . ' ' . $this->georeferenceFillingArray["georeference_decimal_latitude"] . ")',4326)" ; // put point geometry PostGIS WKT in database filling table $this->fillDatabaseGeoreferenceTable('georeferencePointGeometry', $this->pointGeometry); // ******* Construction of PostGIS well-known text (WKT) for CIRCLE ******** // circle geometry just adds the uncertainty range to the point geometry. // If uncertainty range is not provided, there is a good default value. // So, circle geometry can safely be constructed. $this->circleGeometry = "BUFFER('POINT(" . $this->georeferenceFillingArray["georeference_decimal_longitude"] . ' ' . $this->georeferenceFillingArray["georeference_decimal_latitude"] . ")'," .$this->georeferenceFillingArray["georeference_net_uncertainty"] .",16)" ; // put circle geometry PostGIS WKT in database filling table $this->fillDatabaseGeoreferenceTable('georeferenceCircleGeometry', $this->circleGeometry); // ******* Construction of PostGIS well-known text (WKT) for OUTLINE ******** // Outline cannot be calculated, has to be present in the data. // if not, we make it the same as the circle geometry if ($this->georeferenceFillingArray["georeference_geom_outline" ] == ' ') { // put outline geometry PostGIS WKT in database filling table $this->fillDatabaseGeoreferenceTable('georeferenceOutlineGeometry', $this->circleGeometry); } // construct and submit database storage statement $this->databaseQuery = "INSERT INTO georeference(" . $this->arrayKeysAsCommaSeparatedString($this->georeferenceFillingArray) . ") values (" . $this->arrayValuesAsCommaSeparatedString($this->georeferenceFillingArray) . ") ;"; $this->databaseResult = pg_query($this->databaseQuery) or die('** Query failed ** ' . "query: " . $this->databaseQuery . " last error: " . pg_last_error()); $this->return_string = 'Georeference record stored in database.'; // clean up after store $this->resetGeoreferenceFillingArray() ; } return($this->return_string); } //**************************************************************************************** // resetFillingArray functions : used for (re)setting the fillingArrays to the default values. //**************************************************************************************** private function resetExpeditionFillingArray() { $this->expeditionFillingArray= array( "expedition_key" => 0, "expedition_start" => "'99991231'", "expedition_end" => "'99991231'"); } private function resetItineraryFillingArray() { $this->itineraryFillingArray= array( "itinerary_key" => 0, "itinerary_expedition_fkey" => 0, "itinerary_sequence_number" =>0, "itinerary_possibility_number" => 0); } private function resetSectionFillingArray() { $this->sectionFillingArray= array( "section_key" => 0, "section_itinerary_fkey" => 0, "section_begin_event_fkey" => 0, "section_end_event_fkey" =>0); } private function resetEventFillingArray() { $this->eventFillingArray= array( "expedition_event_key" => 0, "expedition_event_georeference_fkey" => 0, "expedition_event_sequence_number" =>0); } private function resetGeoreferenceFillingArray() { // latitude and longitude should not have valid default values : // if they are not provided by the user, nothing should be stored to database. // otherwise, all unfilled georeferences would be plotted on the same default spot. $this->georeferenceFillingArray= array( "georeference_key" => 0, "georeference_decimal_latitude" => 999, "georeference_decimal_longitude" => 999, "georeference_net_uncertainty" => 0.02, "georeference_geom_point" => ' ', "georeference_geom_outline" => ' ', "georeference_geom_circle" => ' '); } //**************************************************************************************** // arrayKeysAsCommaSeparatedString // delivers the keys of the filling array (i.e. the database field names) as a comma-separated // string ready for inclusion in the SQL query. //**************************************************************************************** private function arrayKeysAsCommaSeparatedString($arrayName) { foreach ($arrayName as $key => $value) { $tempArray []= $key; } return implode(',',$tempArray); } //**************************************************************************************** // arrayValuesAsCommaSeparatedString // delivers the keys of the filling array (i.e. the database field values) as a comma-separated // string ready for inclusion in the SQL query. //**************************************************************************************** private function arrayValuesAsCommaSeparatedString($arrayName) { foreach ($arrayName as $key => $value) { $tempArray []= $value; } return implode(',',$tempArray); } //**************************************************************************************** // checkquoteposition //**************************************************************************************** private function checkQuotePosition($stringToCheck,$quoteString) { // quotes are only expected in the first and last position if ( (substr($stringToCheck,0,1)==$quoteString) && (substr($stringToCheck, strlen($stringToCheck)-1,1) == $quoteString) ) { // string is ok as it is $this->return_string = 'Quote position ok.'; } else { // quotes are in the wrong places !! $this->return_string = 'ERROR : Quotes are only expected in first and last position of string.'; } return ($this->return_string); } //**************************************************************************************** //makeSingleQuotedString // makes sure that a string has the correct (i.e. single) quotes for a PostGreSQL statement. // Double quotes are replaced, unquoted strings are quoted. Other cases are flagged as errors // (more or less than 2 quotes, or quotes in the wrong positions). //**************************************************************************************** private function makeSingleQuotedString($stringToCheck) { if((substr_count($stringToCheck,'"')==0) && (substr_count($stringToCheck,"'")==0)) { //no quotes present : we add sinlge quotes $this->return_string = "'". $stringToCheck ."'" ; } else { if (substr_count($stringToCheck,"'") == 2) { // two single quotes // if position of single quotes is ok, the string can be passed on as it is. if ( substr ($this->checkQuotePosition($stringToCheck,"'"),0,5) <> 'ERROR') { $this->return_string = $stringToCheck ; } } elseif (substr_count($stringToCheck,'"') == 2) { // two double quotes // if position of double quotes is ok, replace them with single quotes. if ( substr ($this->checkQuotePosition($stringToCheck,'"'),0,5) <> 'ERROR') { $this->return_string = str_replace ($stringToCheck,'"',"'"); } } else { //quotes found, but faulty by numbers (i.e. not 2) $this->return_string = "ERROR : wrong number of quotes in string."; } } return ($this->return_string); } //**************************************************************************************** // calculatePointGeometry //**************************************************************************************** private function calculatePointGeometry($pointLongitude,$pointLatitude) { // calculations are done through the PostGIS function POINT $this->databaseQuery = "SELECT GeomFromText('POINT(" . $pointLongitude . ' ' . $pointLatitude . ")',4326);" ; $this->databaseResult = pg_query($this->databaseQuery) or die('** Query failed ** ' . "query: " . " $this->databaseQuery " . " last error: " . pg_last_error()); return (pg_fetch_result($this->databaseResult,0,0)); } //**************************************************************************************** // calculateUncertaintyCircleGeometry //**************************************************************************************** private function calculateUncertaintyCircleGeometry($pointLongitude,$pointLatitude, $pointUncertainty) { // calculations are done through the PostGIS functions BUFFER and POINT $this->databaseQuery = "SELECT BUFFER('POINT(" . $pointLongitude . ' ' . $pointLatitude . ")'," . $pointUncertainty . ",16);" ; $this->databaseResult = pg_query($this->databaseQuery) or die('** Query failed ** ' . "query: " . " $this->databaseQuery " . " last error: " . pg_last_error()); return (pg_fetch_result($this->databaseResult,0,0)); } //**************************************************************************************** // calculateSectionLineGeometry //**************************************************************************************** private function calculateSectionLineGeometry() { } //**************************************************************************************** // calculateSectionPolygonGeometry //**************************************************************************************** private function calculateSectionPolygonGeometry() { } } // class Database ?>