preserveWhiteSpace = false;
// attach kml and Document tag
$e_kml = $doc->createElementNS("http://earth.google.com/kml/2.2", "kml");
$e_document = $doc->createElement("Document");
$e_kml->appendChild($e_document);
$doc->appendChild($e_kml);
// attach placemarks
$e = new mb_notice("to string: #placemarks: " . count($this->placemarkArray));
$lineStyleNode = $doc->createElement("Style");
$lineStyleNode->setAttribute("id", "linestyleExample");
$lineStyleColorNode = $doc->createElement("color", "7f0000ff");
$lineStyleWidthNode = $doc->createElement("width", 4);
$lineStyleNode->appendChild($lineStyleColorNode);
$lineStyleNode->appendChild($lineStyleWidthNode);
$e_document->appendChild($lineStyleNode);
//
// line segments first
//
$coordinates = "";
for ($i = 0; $i < count($this->placemarkArray); $i++) {
$currentPlacemark = $this->placemarkArray[$i];
$e = new mb_notice("now: " . $i . " of " . (count($this->placemarkArray)-1) . " (is a " . get_class($currentPlacemark) . ")");
switch ($currentPlacemark->getGeometryType()) {
case "KMLLine" :
$coordinatesArray = $currentPlacemark->getGeometry()->getPointArray();
for ($j = 0; $j < count($coordinatesArray); $j++) {
if (!($j == 0 && $i == 0)) {
$coordinates .= " ";
}
$coordinates .= $coordinatesArray[$j]["x"] . "," . $coordinatesArray[$j]["y"] . "," . $coordinatesArray[$j]["z"];
}
break;
}
}
// create a placemark tag with a geometry and add it to the document
$e_coordinates = $doc->createElement("coordinates", $coordinates);
$e_geometry = $doc->createElement("LineString");
$e_geometry->appendChild($e_coordinates);
$e_placemark = $doc->createElement("Placemark");
$e_placemark->appendChild($e_geometry);
$e_pl_name = $doc->createElement("name", "Route");
$e_placemark->appendChild($e_pl_name);
$e_pl_style = $doc->createElement("styleUrl", "#linestyleExample");
$e_placemark->appendChild($e_pl_style);
$e_document->appendChild($e_placemark);
/*
//
// now pois
//
// attach placemarks
$e = new mb_notice("to string: #placemarks: " . count($this->placemarkArray));
for ($i = 0; $i < count($this->placemarkArray); $i++) {
$currentPlacemark = $this->placemarkArray[$i];
$e = new mb_notice("now: " . $i . " of " . (count($this->placemarkArray)-1) . " (is a " . get_class($currentPlacemark) . ")");
$pl_instructions = $currentPlacemark->getProperty("instruction");
$pl_name_array = array();
$pl_name = false;
$pl_description = false;
if ($pl_instructions != null) {
$pl_name_array = explode("|", $pl_instructions);
}
switch ($currentPlacemark->getGeometryType()) {
case "KMLPoint" :
if (count($pl_name_array) > 2) {
$pl_name = $pl_name_array[0];
$pl_description = $pl_name_array[1];
}
$e_geometry = $doc->createElement("Point");
$point = $currentPlacemark->getGeometry()->getPoint();
$coordinates = $point["x"] . "," . $point["y"];
$e_coordinates = $doc->createElement("coordinates", $coordinates);
$e_geometry->appendChild($e_coordinates);
break;
}
// create a placemark tag with a geometry and add it to the document
if ($e_geometry) {
$e_placemark = $doc->createElement("Placemark");
$e_placemark->appendChild($e_geometry);
if ($pl_name) {
$e_pl_name = $doc->createElement("name", $pl_name);
$e_placemark->appendChild($e_pl_name);
}
if ($pl_description) {
$e_pl_description = $doc->createElement("description", $pl_description);
$e_placemark->appendChild($e_pl_description);
}
$e_document->appendChild($e_placemark);
}
}
*/
return $doc->saveXML();
}
/**
* @return string the merged KML document.
*/
public function mergeKMLDocuments($kmlArray) {
//parse XML Document elements from KML
//Merged KML 2.2 output
$mergedKMLDoc = new DOMDocument("1.0", CHARSET);
$mergedKMLDoc->preserveWhiteSpace = false;
$mergedKML = $mergedKMLDoc->createElementNS("http://earth.google.com/kml/2.2", "kml");
foreach ($kmlArray as $kml) {
$kmlDomObject = new DOMDocument();
$kmlDomObject->loadXML($kml);
$xpathKml = new DOMXpath($kmlDomObject);
$defaultNamespace = $kmlDomObject->lookupNamespaceURI($kmlDomObject->namespaceURI);
$xpathKml->registerNamespace('kml', $defaultNamespace);
$documentNodeList = $xpathKml->query('/kml:kml/kml:Document');
for ($i = ($documentNodeList->length)-1; $i >= 0; $i--) {
$mergedKML->appendChild($mergedKMLDoc->importNode($documentNodeList->item($i), true));
}
}
$mergedKMLDoc->appendChild($mergedKML);
return $mergedKMLDoc->saveXML();
}
/**
* @return string the KML document.
*/
public function __toString() {
//read configuration for geojson simple style from conf folder - to handle style information from geojson if available
$geoJsonStyleInfo = $this->getGeoJsonSimpleStyleInfo();
if (!$this->kml) {
//KML 2.2 output
$doc = new DOMDocument("1.0", CHARSET);
$doc->preserveWhiteSpace = false;
//attach kml and Document tag
$e_kml = $doc->createElementNS("http://earth.google.com/kml/2.2", "kml");
$e_document = $doc->createElement("Document");
$e_kml->appendChild($e_document);
$doc->appendChild($e_kml);
$styleHashArray = array();
$styleArray = array();
$placemarkArray = array();
//attach placemarks
$e = new mb_notice("to string: #placemarks: " . count($this->placemarkArray));
for ($i = 0; $i < count($this->placemarkArray); $i++) {
$currentPlacemark = $this->placemarkArray[$i];
$e = new mb_notice("now: " . $i . " of " . (count($this->placemarkArray)-1) . " (is a " . get_class($currentPlacemark) . ")");
$pl_instructions = $currentPlacemark->getProperty("instruction");
$pl_name_array = array();
$pl_name = false;
$pl_description = false;
if ($pl_instructions != null) {
$pl_name_array = explode("|", $pl_instructions);
}
switch ($currentPlacemark->getGeometryType()) {
case "KMLPoint" :
if (count($pl_name_array) > 2) {
$pl_name = $pl_name_array[0];
$pl_description = $pl_name_array[1];
}
$e_geometry = $doc->createElement("Point");
$point = $currentPlacemark->getGeometry()->getPoint();
$coordinates = $point["x"] . "," . $point["y"];
$e_coordinates = $doc->createElement("coordinates", $coordinates);
$e_geometry->appendChild($e_coordinates);
break;
case "KMLPolygon" :
//100,0 101,0 101,1 100,1 100,0
$e_geometry = $doc->createElement("Polygon");
$e_outer = $doc->createElement("outerBoundaryIs");
$e_outer_lr = $doc->createElement("LinearRing");
$coordinatesArray = $currentPlacemark->getGeometry()->getOuterBoundary()->getPointArray();
$coordinates = "";
for ($j = 0; $j < count($coordinatesArray); $j++) {
if ($j > 0) {
$coordinates .= " ";
}
$coordinates .= $coordinatesArray[$j]["x"] . "," . $coordinatesArray[$j]["y"] . "," . $coordinatesArray[$j]["z"];
}
$e_coordinates = $doc->createElement("coordinates", $coordinates);
$e_outer_lr->appendChild($e_coordinates);
$e_outer->appendChild($e_outer_lr);
$e_geometry->appendChild($e_outer);
//TODO - fill out inner rings as holes
break;
case "KMLLine" :
if (count($pl_name_array) > 2) {
$pl_description = $pl_name_array[1];
}
$e_geometry = $doc->createElement("LineString");
$coordinatesArray = $currentPlacemark->getGeometry()->getPointArray();
$coordinates = "";
for ($j = 0; $j < count($coordinatesArray); $j++) {
if ($j > 0) {
$coordinates .= " ";
}
$coordinates .= $coordinatesArray[$j]["x"] . "," . $coordinatesArray[$j]["y"] . "," . $coordinatesArray[$j]["z"];
}
$e_coordinates = $doc->createElement("coordinates", $coordinates);
$e_geometry->appendChild($e_coordinates);
break;
/* TODO: Multigeometries
case "KMLMultiGeometry" :
break;
*/
}
//check for properties
$currentProperties = $currentPlacemark->getProperties();
if (count($currentProperties) > 0) {
$e_ExtendedData = $doc->createElement("ExtendedData");
}
//read out attribute information
//initial geojson style handling
$currentPropertiesSimpleStyle = array();
foreach($currentProperties as $key => $value){
$e_Data = $doc->createElement("Data");
$e_value = $doc->createElement("value");
$e_Data->setAttribute("name", $key);
if (isset($value)) {
$e_DataValue = $doc->createTextNode($value);
} else {
$e_DataValue = $doc->createTextNode('null');
}
$e_value->appendChild($e_DataValue);
$e_Data->appendChild($e_value);
$e_ExtendedData->appendChild($e_Data);
//
}
//parse styling information from simplestyle spec to define it in header of kml
//switch for geometry type
switch ($currentPlacemark->getGeometryType()) {
case "KMLPoint" :
foreach($geoJsonStyleInfo->point->simple_style_spec_attributes as $attributeKey => $attributeValue) {
//if (array_key_exists($attributeValue, $currentProperties)) {
if (isset($currentProperties[$attributeValue])) {
$value = $currentProperties[$attributeValue];
} else {
//set default value!
$value = $geoJsonStyleInfo->point->simple_style_spec_defaults[$attributeKey];
}
//}
$currentPropertiesSimpleStyle[$attributeValue] = $value;
}
//build style part
//points don't have a color, cause the color is part of the icon in simplestyle-spec
$hash = md5('point'.$currentPropertiesSimpleStyle['marker-size'].$currentPropertiesSimpleStyle['marker-symbol'].$currentPropertiesSimpleStyle['marker-color']);
if (!in_array($hash, $styleHashArray)) {
//generate style part
$e_Style = $doc->createElement("Style");
$e_Style->setAttribute("id", $hash);
$e_IconStyle = $doc->createElement("IconStyle");
$e_Icon = $doc->createElement("Icon");
$e_href = $doc->createElement("href");
$makiUrl = "https://raw.githubusercontent.com/mapbox/maki/master/icons/";
switch($currentPropertiesSimpleStyle['marker-size']) {
case "medium":
$symbol = $makiUrl.$currentPropertiesSimpleStyle['marker-symbol']."-15.svg";
break;
case "small":
$symbol = $makiUrl.$currentPropertiesSimpleStyle['marker-symbol']."-15.svg";
break;
case "large":
$symbol = $makiUrl.$currentPropertiesSimpleStyle['marker-symbol']."-15.svg";
break;
default :
$symbol = $makiUrl.$currentPropertiesSimpleStyle['marker-symbol']."-15.svg";
break;
}
//test for marker-size as integer - map it to discrete values
$sizeInt = (integer)$currentPropertiesSimpleStyle['marker-size'];
if (is_int($sizeInt) && $sizeInt > 0) {
if ($sizeInt >= 15 && $sizeInt < 25) {
$currentPropertiesSimpleStyle['marker-size'] = "small";
} elseif ($sizeInt >= 25 && $sizeInt < 35) {
$currentPropertiesSimpleStyle['marker-size'] = "medium";
} else {
$currentPropertiesSimpleStyle['marker-size'] = "large";
}
}
//alternative for local maki icons
$symbolUrl = MAPBENDER_PATH."/php/mod_getSymbolFromRepository.php?";
$symbolUrl .= "marker-symbol=".$currentPropertiesSimpleStyle['marker-symbol']."&";
$symbolUrl .= "marker-size=".$currentPropertiesSimpleStyle['marker-size']."&";
$symbolUrl .= "marker-color=".$currentPropertiesSimpleStyle['marker-color'];
//with mod_rewrite
$symbolUrl = MAPBENDER_PATH."/../icons/maki/".ltrim($currentPropertiesSimpleStyle['marker-color'],'#')."/".$currentPropertiesSimpleStyle['marker-size']."/".$currentPropertiesSimpleStyle['marker-symbol'].".png";
$e_hrefText = $doc->createTextNode($symbolUrl);
$e_href->appendChild($e_hrefText);
$e_Icon->appendChild($e_href);
$e_IconStyle->appendChild($e_Icon);
$e_hotSpot = $doc->createElement("hotSpot");
$e_hotSpot->setAttribute("xunits", "fraction");
$e_hotSpot->setAttribute("yunits", "fraction");
$e_hotSpot->setAttribute("x", "0.5");
$e_hotSpot->setAttribute("y", "0.5");
/*$e_width = $doc->createElement("width");
$e_widthText = $doc->createTextNode($currentPropertiesSimpleStyle['stroke-width']);
$e_width->appendChild($e_widthText);
$e_LineStyle->appendChild($e_width);*/
$e_Style->appendChild($e_IconStyle);
$e_Style->appendChild($e_hotSpot);
//$e_document->appendChild($e_Style);
$styleArray[] = $e_Style;
$styleHashArray[] = $hash;
}
$e_styleUrl = $doc->createElement("styleUrl");
$e_styleUrlText = $doc->createTextNode("#".$hash);
$e_styleUrl->appendChild($e_styleUrlText);
break;
case "KMLLine" :
foreach($geoJsonStyleInfo->linestring->simple_style_spec_attributes as $attributeKey => $attributeValue) {
//if (array_key_exists($attributeValue, $currentProperties)) {
if (isset($currentProperties[$attributeValue])) {
$value = $currentProperties[$attributeValue];
} else {
//set default value!
$value = $geoJsonStyleInfo->linestring->simple_style_spec_defaults[$attributeKey];
}
//}
$currentPropertiesSimpleStyle[$attributeValue] = $value;
}
//build style part
$hash = md5('linestring'.$currentPropertiesSimpleStyle['stroke'].$currentPropertiesSimpleStyle['stroke-opacity'].$currentPropertiesSimpleStyle['stroke-width']);
//map html hex color to kml color code
$colorKml = $this->htmlColor2kmlColor($currentPropertiesSimpleStyle['stroke'], $currentPropertiesSimpleStyle['stroke-opacity']);
if (!in_array($hash, $styleHashArray)) {
//generate style part
$e_Style = $doc->createElement("Style");
$e_Style->setAttribute("id", $hash);
$e_LineStyle = $doc->createElement("LineStyle");
$e_color = $doc->createElement("color");
$e_colorText = $doc->createTextNode($colorKml);
$e_color->appendChild($e_colorText);
$e_LineStyle->appendChild($e_color);
$e_width = $doc->createElement("width");
$e_widthText = $doc->createTextNode($currentPropertiesSimpleStyle['stroke-width']);
$e_width->appendChild($e_widthText);
$e_LineStyle->appendChild($e_width);
$e_Style->appendChild($e_LineStyle);
//$e_document->appendChild($e_Style);
$styleArray[] = $e_Style;
$styleHashArray[] = $hash;
}
$e_styleUrl = $doc->createElement("styleUrl");
$e_styleUrlText = $doc->createTextNode("#".$hash);
$e_styleUrl->appendChild($e_styleUrlText);
break;
case "KMLPolygon":
foreach($geoJsonStyleInfo->polygon->simple_style_spec_attributes as $attributeKey => $attributeValue) {
//if (array_key_exists($attributeValue, $currentProperties)) {
if (isset($currentProperties[$attributeValue])) {
$value = $currentProperties[$attributeValue];
} else {
//set default value!
$value = $geoJsonStyleInfo->polygon->simple_style_spec_defaults[$attributeKey];
}
//}
$currentPropertiesSimpleStyle[$attributeValue] = $value;
}
//build style part
$hash = md5('polygon'.$currentPropertiesSimpleStyle['stroke'].$currentPropertiesSimpleStyle['stroke-opacity'].$currentPropertiesSimpleStyle['stroke-width']);
$colorKml = $this->htmlColor2kmlColor($currentPropertiesSimpleStyle['stroke'], $currentPropertiesSimpleStyle['stroke-opacity']);
$colorKmlFill = $this->htmlColor2kmlColor($currentPropertiesSimpleStyle['fill'], $currentPropertiesSimpleStyle['fill-opacity']);
if (!in_array($hash, $styleHashArray)) {
//generate style part
$e_Style = $doc->createElement("Style");
$e_Style->setAttribute("id", $hash);
$e_LineStyle = $doc->createElement("LineStyle");
$e_color = $doc->createElement("color");
$e_colorText = $doc->createTextNode($colorKml);
$e_color->appendChild($e_colorText);
$e_LineStyle->appendChild($e_color);
$e_width = $doc->createElement("width");
$e_widthText = $doc->createTextNode($currentPropertiesSimpleStyle['stroke-width']);
$e_width->appendChild($e_widthText);
$e_LineStyle->appendChild($e_width);
$e_Style->appendChild($e_LineStyle);
//polystyle
//7fff44ff
$e_PolyStyle = $doc->createElement("PolyStyle");
$e_color = $doc->createElement("color");
$e_colorText = $doc->createTextNode($colorKmlFill);
$e_color->appendChild($e_colorText);
$e_PolyStyle->appendChild($e_color);
$e_Style->appendChild($e_PolyStyle);
//$e_document->appendChild($e_Style);
$styleArray[] = $e_Style;
$styleHashArray[] = $hash;
}
$e_styleUrl = $doc->createElement("styleUrl");
$e_styleUrlText = $doc->createTextNode("#".$hash);
$e_styleUrl->appendChild($e_styleUrlText);
break;
}
//overwrite name and description with info from geojson simplestyle spec
//if (!isset($pl_name)) {
$pl_name = $currentPropertiesSimpleStyle['title'];
//}
//if (!isset($pl_description)) {
$pl_description = $currentPropertiesSimpleStyle['description'];
//}
// create a placemark tag with a geometry and add it to the document
if ($e_geometry) {
$e_placemark = $doc->createElement("Placemark");
if ($pl_name) {
$e_pl_name = $doc->createElement("name", $pl_name);
$e_placemark->appendChild($e_pl_name);
}
/*if ($pl_description) {
$e_pl_description = $doc->createElement("description", $pl_description);
$e_placemark->appendChild($e_pl_description);
}*/
if ($e_ExtendedData) {
$e_placemark->appendChild($e_ExtendedData);
}
$e_placemark->appendChild($e_geometry);
if ($e_styleUrl) {
$e_placemark->appendChild($e_styleUrl);
}
$placemarkArray[] = $e_placemark;
}
}
foreach($styleArray as $style) {
$e_document->appendChild($style);
}
foreach($placemarkArray as $placemark) {
$e_document->appendChild($placemark);
}
$this->kml = $doc->saveXML();
}
return $this->kml;
}
/**
* @return KML color code from HTML color code and opacity values.
* https://stackoverflow.com/questions/15202079/convert-hex-color-to-rgb-values-in-php
* https://stackoverflow.com/questions/13034702/google-maps-kml-8-digit-hex-code
* https://developers.google.com/kml/documentation/kmlreference#color
*/
private function htmlColor2kmlColor($hex, $alpha) {
$hex = str_replace('#', '', $hex);
$length = strlen($hex);
$rgb['r'] = hexdec($length == 6 ? substr($hex, 0, 2) : ($length == 3 ? str_repeat(substr($hex, 0, 1), 2) : 0));
$rgb['g'] = hexdec($length == 6 ? substr($hex, 2, 2) : ($length == 3 ? str_repeat(substr($hex, 1, 1), 2) : 0));
$rgb['b'] = hexdec($length == 6 ? substr($hex, 4, 2) : ($length == 3 ? str_repeat(substr($hex, 2, 1), 2) : 0));
if ( $alpha ) {
$rgb['a'] = ceil($alpha * 255);
}
/*$e = new mb_exception("alpha: ".$rgb['a']."hex: ".dechex($rgb['a']));
$e = new mb_exception("r: ".$rgb['r']."hex: ".dechex($rgb['r']));
$e = new mb_exception("g: ".$rgb['g']."hex: ".dechex($rgb['g']));
$e = new mb_exception("b: ".$rgb['b']."hex: ".dechex($rgb['b']));*/
//encode to kml:
return dechex($rgb['a']).dechex($rgb['b']).dechex($rgb['g']).dechex($rgb['r']);
}
/**
* @return string the ID of this KML.
*/
public function getId () {
return $this->id;
}
/**
* parses an incoming KML, creates the object,
* stores the kml in the object and in the database.
*
* @param string a KML document.
* @return boolean true if the parsing succeded, else false.
*/
public function parseKml ($kml) {
$this->kml = $kml;
if (!$this->storeInDb()) {
return false;
}
$parser = new KmlOwsParser();
$parser->parseKML($kml, $this->id);
$this->placemarkArray = $parser->placemarkArray;
$this->featureCollectionMD = $parser->featureCollectionMD;
return true;
}
public function transform($targetEpsg){
$numberOfPlacemarks = count($this->placemarkArray);
if ($numberOfPlacemarks > 0) {
for ($i=0; $i < $numberOfPlacemarks; $i++) {
$this->placemarkArray[$i]->transform($targetEpsg);
}
}
else {
$e = new mb_exception("KML: toGeoJSON: this placemarkArray is empty!");
}
return true;
}
/**
* parses an incoming GeoJSON, creates the object,
* stores the kml in the object and in the database.
*
* @param string a geoJSON.
* @return boolean true if the parsing succeded, else false.
*/
public function parseGeoJSON ($geoJSON) {
$this->kml = "";
if (!$this->storeInDb()) {
return false;
}
$parser = new KmlOwsParser();
$parser->parseGeoJSON($geoJSON, $this->id);
$e = new mb_notice("parsing finished...#placemarks: " . count($this->placemarkArray) . " (" . count($parser->placemarkArray) . ")");
$this->placemarkArray = $parser->placemarkArray;
return true;
}
/**
* @return string the geoJSON representation of the KML.
*/
public function toGeoJSON($str) {
$numberOfPlacemarks = count($this->placemarkArray);
if ($numberOfPlacemarks > 0) {
$str .= "\"features\": [";
for ($i=0; $i < $numberOfPlacemarks; $i++) {
if ($i > 0) {
$str .= ",";
}
$str .= $this->placemarkArray[$i]->toGeoJSON();
}
$str .= "]}";
}
else {
$e = new mb_exception("KML: toGeoJSON: this placemarkArray is empty!");
}
return $str;
}
public function createGeoJSON(){
$str = "{";
$str.= "\"type\": \"FeatureCollection\",";
if (sizeof($this->featureCollectionMD) > 0) {
foreach ($this->featureCollectionMD as $key => $value) {
$str.= "\"".$key."\": \"".$value."\",";
}
}
$completeString = $this->toGeoJSON($str);
return $completeString;
}
private function updateInDb($kmlDoc, $kmlId) {
$sql = "UPDATE gui_kml SET kml_doc = $1 WHERE kml_id = $2";
$v = array($kmlDoc, $kmlId);
$t = array("s", "i");
$result = db_prep_query($sql, $v, $t);
if (!$result) {
$e = new mb_exception("class_kml: kml update failed! " . db_error());
return false;
}
}
public function updateKml ($kmlId, $placemarkId, $geoJSON) {
$kmlFromDb = $this->getKmlDocumentFromDB($kmlId);
if ($kmlFromDb !== NULL) {
// load the KML from the database in the DOM object
$kmlDoc_DOM = new DOMDocument("1.0");
$kmlDoc_DOM->encoding = CHARSET;
$kmlDoc_DOM->preserveWhiteSpace = false;
$kmlDoc_DOM->loadXML($kmlFromDb);
//load the geoJSON
$json = new Mapbender_JSON();
$geoObj = $json->decode($geoJSON);
// construct an array that holds all metadata of the placemark
$metadataObj = $geoObj->properties;
// construct an array that holds all geometries of the placemark
$geometryObj = $geoObj->geometry;
$geometryType = $geometryObj->type;
if ($geometryType == "GeometryCollection") {
$geometryArray = $geometryObj->geometries;
}
else if ($geometryType == "Point" || $geometryType == "LineString" || $geometryType == "Polygon") {
$geometryArray = array($geometryObj);
}
else {
$e = new mb_exception("class_kml: Invalid geometry type " . $geometryType);
return false;
}
//
// apply the changes
//
$currentPlacemarkArray = $kmlDoc_DOM->getElementsByTagName("Placemark");
$currentPlacemark = $currentPlacemarkArray->item($placemarkId);
if ($currentPlacemark) {
$metadataUpdateSuccessful = $this->updateMetadata($currentPlacemark, $metadataObj);
$geometryUpdateSuccessful = $this->updateGeometries($currentPlacemark, $geometryArray);
}
else {
$e = new mb_exception("class_kml.php: updateKml: placemark " . $placemarkId . " not found in KML " . $kmlId . ".");
return false;
}
if ($metadataUpdateSuccessful && $geometryUpdateSuccessful) {
$updatedKml = $kmlDoc_DOM->saveXML();
$this->updateInDb($updatedKml, $kmlId);
}
else {
if (!$metadataUpdateSuccessful) {
$e = new mb_exception("class_kml: Updating the metadata failed, no database update.");
}
if (!$geometryUpdateSuccessful) {
$e = new mb_exception("class_kml: Updating the geometries failed, no database update.");
}
return false;
}
}
else {
$e = new mb_exception("class_kml: No KML found in database, no database update. " . db_error());
return false;
}
return true;
}
//
//
// ------------------------------- private -----------------------------------------------
//
//
/**
* Store this KML in the database, and sets the ID.
*
* @return boolean true, if the KML could be stored in the database; else false.
*/
private function storeInDb () {
if (Mapbender::session()->get("mb_user_id") && Mapbender::session()->get("mb_user_gui")) {
$con = db_connect(DBSERVER,OWNER,PW);
db_select_db(DB,$con);
$sql = "INSERT INTO gui_kml ";
$sql .= "(fkey_mb_user_id, fkey_gui_id, kml_doc, kml_name, kml_description, kml_timestamp) ";
$sql .= "VALUES ";
$sql .= "($1, $2, $3, $4, $5, $6)";
$v = array (Mapbender::session()->get("mb_user_id"), Mapbender::session()->get("mb_user_gui"), $this->kml, "name", "description", time());
$t = array ("i", "s", "s", "s", "s", "s");
$res = db_prep_query($sql, $v, $t);
if (!$res) {
$e = new mb_exception("class_kml.php: storeInDb: failed to store KML in database: " . db_error());
return false;
}
$this->id = db_insert_id($con, "gui_kml", "kml_id");
return true;
}
else {
// should be false, but code in caller has to be changed first.
return true;
}
}
/**
* @param integer the ID of the KML.
* @return string the KML document with the given ID.
*/
public function getKmlDocumentFromDB ($kmlId) {
$con = db_connect(DBSERVER,OWNER,PW);
db_select_db(DB,$con);
//get KML from database (check if user is allowed to access)
# for now, do not restrict access
# $sql = "SELECT kml_doc FROM gui_kml WHERE kml_id = $1 AND fkey_mb_user_id = $2 AND fkey_gui_id = $3 LIMIT 1";
# $v = array($kmlId, Mapbender::session()->get("mb_user_id"), Mapbender::session()->get("mb_user_gui"));
# $t = array("i", "i", "s");
$sql = "SELECT kml_doc FROM gui_kml WHERE kml_id = $1 LIMIT 1";
$v = array($kmlId);
$t = array("i");
$result = db_prep_query($sql, $v, $t);
$row = db_fetch_array($result);
if ($row) {
return $row["kml_doc"];
}
else {
$e = new mb_exception("class_kml.php: getKMLDocumentFromDB: no KML found for ID " . $kmlId);
}
return "";
}
/**
* @param string the tag name.
* @return string the tag name without its namespace.
*/
private function sepNameSpace($s){
$c = mb_strpos($s, ":");
if ($c > 0) {
$s = mb_substr($s, $c+1);
}
return $s;
}
private function updateGeometries($currentPlacemark, $geometryArray) {
$cnt = 0;
$childNodes = $currentPlacemark->childNodes;
foreach ($childNodes as $childNode) {
$name = $childNode->nodeName;
if ( in_array($name, array("Point","LineString","Polygon"))) {
$returnValue = $this->updateGeometry($childNode, $geometryArray[$cnt]);
if (!$returnValue) {
return false;
}
$cnt ++;
}
else if ($name == "MultiGeometry") {
return $this->updateGeometries($childNode, $geometryArray);
}
}
return true;
}
private function updateGeometry ($currentNode, $geometry) {
$json = new Mapbender_JSON();
$currentNode_SimpleXML = simplexml_import_dom($currentNode);
$currentTypeXml = mb_strtoupper($currentNode->nodeName);
$currentTypeGeoJson = mb_strtoupper($geometry->type);
if ($currentTypeGeoJson != $currentTypeXml) {
$e = new mb_exception("class_kml: geometry type mismatch: geoJSON: " . $currentTypeGeoJson . "; XML: " . $currentTypeXml);
return false;
}
if ($currentTypeXml == "POLYGON") {
// GML 3
$gmlNode = $currentNode_SimpleXML->{"exterior"}->{"LinearRing"}->{"posList"};
$kmlNode = $currentNode_SimpleXML->{"outerBoundaryIs"}->{"LinearRing"}->{"coordinates"};
if ($gmlNode && $gmlNode->asXML()) {
$currentNode_SimpleXML->{"exterior"}->{"LinearRing"}->{"posList"} = preg_replace("/,/", " ", preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates)));
}
// KML 2.2
else if ($kmlNode && $kmlNode->asXML()) {
$currentNode_SimpleXML->{"outerBoundaryIs"}->{"LinearRing"}->{"coordinates"} = preg_replace("/\],/", " ", preg_replace("/\][^,]|\[/", "", $json->encode($geometry->coordinates)));
}
}
elseif ($currentTypeXml == "POINT") {
$gmlNode = $currentNode_SimpleXML->{"pos"};
$kmlNode = $currentNode_SimpleXML->{"coordinates"};
// GML 3
if ($gmlNode && $gmlNode->asXML()) {
$currentNode_SimpleXML->{"pos"} = preg_replace("/,/", " ", preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates)));
}
// KML 2.2
else if ($kmlNode && $kmlNode->asXML()) {
$currentNode_SimpleXML->{"coordinates"} = preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates));
}
}
elseif ($currentTypeXml == "LINESTRING") {
$gmlNode = $currentNode_SimpleXML->{"posList"};
$kmlNode = $currentNode_SimpleXML->{"coordinates"};
// GML 3
if ($gmlNode && $gmlNode->asXML()) {
$currentNode_SimpleXML->{"posList"} = preg_replace("/,/", " ", preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates)));
}
// KML 2.2
else if ($kmlNode && $kmlNode->asXML()) {
$currentNode_SimpleXML->{"coordinates"} = preg_replace("/\[|\]/", "", $json->encode($geometry->coordinates));
}
}
return true;
}
private function updateMetadata($currentPlacemark, $metadataObj) {
$metadataExistsAndUpdateSucceeded = true;
$currentPlacemark_SimpleXML = simplexml_import_dom($currentPlacemark);
$extendedDataNode = $currentPlacemark_SimpleXML->{"ExtendedData"};
if ($extendedDataNode) {
$metadataExistsAndUpdateSucceeded = false;
// Either, data is within a SCHEMADATA tag...
$simpleDataNodes = $extendedDataNode->{"SchemaData"}->{"SimpleData"};
if ($simpleDataNodes) {
foreach ($simpleDataNodes as $simpleDataNode) {
$tmp = dom_import_simplexml($simpleDataNode);
$name = $tmp->getAttribute("name");
// if there is a metadata entry, update it
if (isset($metadataObj->$name)) {
$tmp->nodeValue = $metadataObj->$name;
}
}
$metadataExistsAndUpdateSucceeded = true;
}
// ...or within a DATA tag
$dataNodes = $extendedDataNode->{"Data"};
if ($dataNodes && !$metadataExistsAndUpdateSucceeded) {
foreach ($dataNodes as $dataNode) {
$tmp = dom_import_simplexml($dataNode);
$name = $tmp->getAttribute("name");
// if there is a metadata entry, update it
if (isset($metadataObj->$name)) {
$tmp->nodeValue = $metadataObj->$name;
}
}
$metadataExistsAndUpdateSucceeded = true;
}
}
return $metadataExistsAndUpdateSucceeded;
}
/**
* The KML document.
*/
private $kml;
/**
* The ID of this KML in the database.
*/
private $id;
/**
* An array of {@link KMLPlacemark}
*/
private $placemarkArray = array();
}
?>