[Mapbender-commits] r10195 - in trunk/mapbender/http: classes php

svn_mapbender at osgeo.org svn_mapbender at osgeo.org
Tue Aug 6 04:38:18 PDT 2019


Author: armin11
Date: 2019-08-06 04:38:18 -0700 (Tue, 06 Aug 2019)
New Revision: 10195

Removed:
   trunk/mapbender/http/php/mod_linkedDataProxy_2.php
Modified:
   trunk/mapbender/http/classes/class_wfs.php
   trunk/mapbender/http/php/mod_linkedDataProxy.php
Log:
Some enhancements for better wfs 3.0 linked open data proxy

Modified: trunk/mapbender/http/classes/class_wfs.php
===================================================================
--- trunk/mapbender/http/classes/class_wfs.php	2019-08-02 12:11:42 UTC (rev 10194)
+++ trunk/mapbender/http/classes/class_wfs.php	2019-08-06 11:38:18 UTC (rev 10195)
@@ -249,7 +249,7 @@
 //		return $this->getFeatureGet($featureTypeName, $filter);
 	}
 
-	public function getFeaturePaging ($featureTypeName, $filter, $destSrs=null, $storedQueryId=null, $storedQueryParams=null,  $maxFeatures=null, $startIndex=null, $version=false) {
+	public function getFeaturePaging ($featureTypeName, $filter, $destSrs=null, $storedQueryId=null, $storedQueryParams=null,  $maxFeatures=null, $startIndex=null, $version=false, $outputFormat=false) {
 
 // FOR NOW, WE ONLY DO POST REQUESTS!
 // THE FILTERS ARE CONSTRUCTED ON THE CLIENT SIDE,
@@ -257,7 +257,7 @@
 // WOULD BE TOO MUCH FOR NOW
 //
 //		if (strpos($this->getFeature, "?") === false) {
-			return $this->getFeaturePostPaging($featureTypeName, $filter, $destSrs, $storedQueryId, $storedQueryParams, $maxFeatures, $startIndex, $version);
+			return $this->getFeaturePostPaging($featureTypeName, $filter, $destSrs, $storedQueryId, $storedQueryParams, $maxFeatures, $startIndex, $version, $outputFormat);
 //		}
 //		return $this->getFeatureGet($featureTypeName, $filter);
 	}
@@ -438,7 +438,12 @@
 					"xmlns:gml=\"http://www.opengis.net/gml/3.2\" " .
 					"xmlns:fes=\"http://www.opengis.net/fes/2.0\" " .
 					"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " .
-					"xsi:schemaLocation=\"http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd\">";
+					"xsi:schemaLocation=\"http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd\" ";
+			if (isset($outputFormat) && $outputFormat != '') {
+				$postData .= "outputFormat=\"".$outputFormat."\">";
+			} else {
+				$postData .= ">";
+			}
 			$postData .= "<wfs:StoredQuery id=\"" . $storedQueryId . "\">";
 			$postData .= $storedQueryParams;
 			$postData .= "</wfs:StoredQuery>";
@@ -452,7 +457,12 @@
 					"xmlns:ogc=\"http://www.opengis.net/ogc\" " .
 					"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " .
 					"xsi:schemaLocation=\"http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd\" ".
-					"startIndex=\"".$startIndex."\" count=\"".$maxFeatures."\" >";
+					"startIndex=\"".$startIndex."\" count=\"".$maxFeatures."\" ";
+				if (isset($outputFormat) && $outputFormat != '') {
+					$postData .= "outputFormat=\"".$outputFormat."\">";
+				} else {
+					$postData .= ">";
+				}
 			}//TODO: not already implemented - maybe usefull for older geoserver/mapserver implementations
 			else if($version == "1.1.0") {
 				$postData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
@@ -461,7 +471,12 @@
 						"xmlns:gml=\"http://www.opengis.net/gml\" " .
 						"xmlns:ogc=\"http://www.opengis.net/ogc\" " .
 						"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " .
-						"xsi:schemaLocation=\"http://www.opengis.net/wfs ../wfs/1.1.0/WFS.xsd\">";
+						"xsi:schemaLocation=\"http://www.opengis.net/wfs ../wfs/1.1.0/WFS.xsd\" ";
+				if (isset($outputFormat) && $outputFormat != '') {
+					$postData .= "outputFormat=\"".$outputFormat."\">";
+				} else {
+					$postData .= ">";
+				}
 			}
 			else {
 				$postData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
@@ -470,7 +485,12 @@
 						"xmlns:gml=\"http://www.opengis.net/gml\" " .
 						"xmlns:ogc=\"http://www.opengis.net/ogc\" " .
 						"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " .
-						"xsi:schemaLocation=\"http://www.opengis.net/wfs ../wfs/1.0.0/WFS-basic.xsd\">";
+						"xsi:schemaLocation=\"http://www.opengis.net/wfs ../wfs/1.0.0/WFS-basic.xsd\" ";
+				if (isset($outputFormat) && $outputFormat != '') {
+					$postData .= "outputFormat=\"".$outputFormat."\">";
+				} else {
+					$postData .= ">";
+				}
 			}
 			$postData .="<wfs:Query ";
 			if($destSrs) {
@@ -489,8 +509,9 @@
 				$filter = str_replace("/ogc", "/fes", $filter);
 			        $filter = str_replace("PropertyName", "ValueReference", $filter);*/
 			}
-			$postData .= $typeNameParameterName."=\"" . $featureTypeName . "\">" .
-					$filter .
+			$postData .= $typeNameParameterName."=\"" . $featureTypeName . "\"  >";
+
+			$postData .= $filter .
 					"</wfs:Query>";
 		}
 		$postData .= "</wfs:GetFeature>";	

Modified: trunk/mapbender/http/php/mod_linkedDataProxy.php
===================================================================
--- trunk/mapbender/http/php/mod_linkedDataProxy.php	2019-08-02 12:11:42 UTC (rev 10194)
+++ trunk/mapbender/http/php/mod_linkedDataProxy.php	2019-08-06 11:38:18 UTC (rev 10195)
@@ -3,21 +3,38 @@
 require_once(dirname(__FILE__)."/../classes/class_cache.php");
 require_once(dirname(__FILE__)."/../classes/class_universal_wfs_factory.php");
 require_once(dirname(__FILE__)."/../classes/class_gml_3_factory.php");
+require_once(dirname(__FILE__)."/../classes/class_owsConstraints.php");
 //http://localhost/mapbender/devel_tests/wfsClientTest.php?wfsid=16&ft=vermkv:fluren_rlp&bbox=7.9,50.8,8.0,52
 //initialize some parameter
+$limit = 10;
 //objects per page
 $maxObjectsPerPage = 10;
 //default page
 $page = 0;
-//default outputFormat:
+//default format f
+$f = "json";
+//parameter to control if the native json should be requested from the server, if support for geojson is available!
+$nativeJson = false;
+//default outputFormat for wfs objects:
 $outputFormat = "text/xml";
+$outputFormat = "text/xml; subtype=gml/3.1.1";
 //outputFormat whitelist
 $allowedOutputFormats = array("text/xml; subtype=gml/3.1.1","text/xml; subtype=gml/3.2","text/xml; subtype=gml/2.1.2","text/xml; subtype=gml/3.2.1","SHAPEZIP","application/json; subtype=geojson","text/csv","application/zip");
-
+//outputFormat for pages - parameter f=...
+$allowedFormats = array("html","xml","json");
+//initial extent for leaflet client
 $minxFC = 48;
 $minyFC = 6;
 $maxxFC = 51;
 $maxyFC = 9;
+//	
+$newline = "\n";
+$allowedLimits = array("1","5","10","20");
+function microtime_float() {
+    	list($usec, $sec) = explode(" ", microtime());
+    	return ((float)$usec + (float)$sec);
+}
+//outputFormatter for attribute values - urls, ...
 function string2html($string) {
 	if (filter_var($string, FILTER_VALIDATE_URL)) {
 		return "<a href='".$string."' target='_blank'>".$string."</a>";
@@ -24,6 +41,20 @@
 	}
 	return $string;
 }
+function delTotalFromQuery($paramName, $url) {
+	$query = explode("?", $url);
+	parse_str($query[1], $vars);
+	if (is_array($paramName)) {
+	    foreach($paramName as $param) {
+		unset($vars[$param]);
+	    }
+	} else {
+            unset($vars[$paramName]);
+	}
+	$urlNew = $query[0]."?".http_build_query($vars);
+	return $urlNew;
+}
+//handle http request parameters
 //parse request parameters
 if (isset($_REQUEST["wfsid"]) & $_REQUEST["wfsid"] != "") {
 	//validate to csv integer list
@@ -61,21 +92,74 @@
 	$page = $testMatch;
 	$testMatch = NULL;
 }
-
-if (isset($_REQUEST["ft"]) & $_REQUEST["ft"] != "") {
+//alternate for page - limit offset
+if (isset($_REQUEST["limit"]) & $_REQUEST["limit"] != "") {
 	//validate to csv integer list
-	$testMatch = $_REQUEST["ft"];
+	$testMatch = $_REQUEST["limit"];
+        if (!in_array($testMatch, $allowedLimits)){ 
+		echo 'Parameter <b>limit</b> is not valid - must be one of: '.implode(',', $allowedLimits).'<br/>'; 
+		die(); 		
+ 	}
+	$limit = (integer)$testMatch;
+	$testMatch = NULL;
+}
+if (isset($_REQUEST["offset"]) & $_REQUEST["offset"] != "") {
+	//validate to csv integer list
+	$testMatch = $_REQUEST["offset"];
+	$pattern = '/^[\d]*$/';		
+ 	if (!preg_match($pattern,$testMatch)){ 
+		//echo 'id: <b>'.$testMatch.'</b> is not valid.<br/>'; 
+		echo 'Parameter <b>offset</b> is not valid (integer).<br/>'; 
+		die(); 		
+ 	}
+	$offset = (integer)$testMatch;
+	$testMatch = NULL;
+}
+if (isset($_REQUEST["collection"]) & $_REQUEST["collection"] != "") {
+	//validate to csv integer list
+	$testMatch = $_REQUEST["collection"];
 	$pattern = '/^[0-9a-zA-Z\.\-
 _:]*$/';		
  	if (!preg_match($pattern,$testMatch)){ 
 		//echo 'id: <b>'.$testMatch.'</b> is not valid.<br/>'; 
-		echo 'Parameter <b>ft</b> is not valid (ogc resource name).<br/>'; 
+		echo 'Parameter <b>collection</b> is not valid (ogc resource name or id).<br/>'; 
 		die(); 		
  	}
-	$ft = $testMatch;
+	$collection = $testMatch;
 	$testMatch = NULL;
 }
-
+if (isset($_REQUEST["collections"]) & $_REQUEST["collections"] != "") {
+	//validate to csv integer list
+	$testMatch = $_REQUEST["collections"];
+	if (!in_array($testMatch, array("all"))){ 
+		echo 'Parameter <b>collections</b> is not valid (maybe all).<br/>'; 
+		die(); 		
+ 	}
+	$collections = $testMatch;
+	$testMatch = NULL;
+}
+if (isset($_REQUEST["items"]) & $_REQUEST["items"] != "") {
+	//validate to csv integer list
+	$testMatch = $_REQUEST["items"];
+	if (!in_array($testMatch, array("all"))){ 
+		echo 'Parameter <b>items</b> is not valid (maybe all).<br/>'; 
+		die(); 		
+ 	}
+	$items = $testMatch;
+	$testMatch = NULL;
+}
+if (isset($_REQUEST["item"]) & $_REQUEST["item"] != "") {
+	//validate to csv integer list
+	$testMatch = $_REQUEST["item"];
+	$pattern = '/^[0-9a-zA-Z\.\-_:]*$/';	
+ 	if (!preg_match($pattern,$testMatch)){ 
+		//echo 'id: <b>'.$testMatch.'</b> is not valid.<br/>'; 
+		echo 'Parameter <b>item</b> is not valid (/^[0-9a-zA-Z\.\-_:]*$/).<br/>'; 
+		die(); 		
+ 	}
+	$item = $testMatch;
+	$testMatch = NULL;
+}
 if (isset($_REQUEST["outputFormat"]) & $_REQUEST["outputFormat"] != "") {
 	//validate to csv integer list
 	$testMatch = $_REQUEST["outputFormat"];
@@ -87,7 +171,16 @@
 	$outputFormat = $testMatch;
 	$testMatch = NULL;
 }
-
+if (isset($_REQUEST["f"]) & $_REQUEST["f"] != "") {
+	//validate to csv integer list
+	$testMatch = $_REQUEST["f"];	
+ 	if (!in_array($testMatch, $allowedFormats)){ 
+		echo 'Parameter <b>f</b> is not valid - must be one of: '.implode(',', $allowedFormats).'<br/>'; 
+		die(); 		
+ 	}
+	$f = $testMatch;
+	$testMatch = NULL;
+}
 if (isset($_REQUEST["bbox"]) & $_REQUEST["bbox"] != "") {
 	//validate to float/integer
 	$testMatch = $_REQUEST["bbox"];
@@ -107,561 +200,952 @@
 	$bbox = $testMatch;
 	$testMatch = NULL;
 }
-//instantiate needed classes
+if (isset($_REQUEST["nativeJson"]) & $_REQUEST["nativeJson"] != "") {
+	//validate to csv integer list
+	$testMatch = $_REQUEST["nativeJson"];	
+ 	if (!in_array($testMatch, array("true","false"))){ 
+		echo 'Parameter <b>nativeJson</b> is not valid - must be one of: '.implode(',', array("true","false")).'<br/>'; 
+		die(); 		
+ 	}
+        if ($testMatch == "true") {
+	    $nativeJson = true;
+	}
+	$testMatch = NULL;
+}
+$proxyStartTime = microtime_float();
+//instantiate needed classes 
 $cache = new Cache();
-//do the html things
-$html = '';
-$html .= '<!DOCTYPE html>';
-$html .= '<html>';
-$html .= '<head>';
-$html .= '<title>Mapbender WFS OpenLinkedData Proxy</title>';
-$html .= '<meta http-equiv="X-UA-Compatible" content="IE=edge">';
-$html .= '<meta charset="utf-8" />';
-$html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';	
-//$html .= '<link rel="shortcut icon" type="image/x-icon" href="" />';
-$html .= '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>';
-$html .= '<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" crossorigin=""></script>';
-//bootstrap
-$html .= '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">';
-//own styles - mapviewer ...
-$html .= '<style>
-		html, body {
-			height: 100%;
-			margin: 0;
-		}
-		#map {
-			width: 600px;
-			height: 400px;
-		}
-	</style>';	
-$html .= '</head>';	
-$html .= '<body>';
-//navigation bar
-$html .= '<nav class="navbar navbar-light bg-light navbar-expand-sm">   ';
-$html .= '    <div class="container">';
-$html .= '        <div id="navbar" class="navbar-collapse collapse d-flex justify-content-between align-items-center">';
-$html .= '            <ol class="breadcrumb bg-light my-0 pl-0">';
-//if (!isset($wfsid)) {
-	$html .= '                            <li class="breadcrumb-item active">Datasets</li>';
-//} else {
-	//$html .= '                            <li class="breadcrumb-item active">'..'</li>';			
-//}
-//$html .= '                            <li class="breadcrumb-item active">Datasets</li>';
-$html .= '            </ol>';
-$html .= '            <ul class="list-separated m-0 p-0 text-muted">';
-$html .= '            </ul>    ';        
-$html .= '        </div>';
-
-$html .= '                    <!--button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">';
-$html .= '                <span class="navbar-toggler-icon"></span>';
-$html .= '            </button-->';
-
-$html .= '    </div>';
-$html .= '</nav>';
-$html .= '<script>';
-//https://stackoverflow.com/questions/5997450/append-to-url-and-refresh-page
-
-$html .= "	function URL_add_parameter(url, param, value){";
-$html .= "	    var hash       = {};";
-$html .= "	    var parser     = document.createElement('a');";
-
-$html .= "	    parser.href    = url;";
-
-$html .= "	    var parameters = parser.search.split(/\?|&/);";
-
-$html .= "	    for(var i=0; i < parameters.length; i++) {";
-$html .= "	        if(!parameters[i])";
-$html .= "	            continue;";
-
-$html .= "	        var ary      = parameters[i].split('=');";
-$html .= "	        hash[ary[0]] = ary[1];";
-$html .= "	    }";
-
-$html .= "	    hash[param] = value;";
-
-$html .= "	    var list = [];  ";
-$html .= "	    Object.keys(hash).forEach(function (key) {";
-$html .= "	        list.push(key + '=' + hash[key]);";
-$html .= "	    });";
-
-$html .= "	    parser.search = '?' + list.join('&');";
-$html .= "	    return parser.href;";
-$html .= "	}";
-
-$html .= "	function URL_remove_parameter(url, param){";
-$html .= "	    var hash       = {};";
-$html .= "	    var parser     = document.createElement('a');";
-
-$html .= "	    parser.href    = url;";
-
-$html .= "	    var parameters = parser.search.split(/\?|&/);";
-
-$html .= "	    for(var i=0; i < parameters.length; i++) {";
-$html .= "	        if(!parameters[i])";
-$html .= "	            continue;";
-
-$html .= "	        var ary      = parameters[i].split('=');";
-$html .= "	        hash[ary[0]] = ary[1];";
-$html .= "	    }";
-
-$html .= "	    hash[param] = 0;";
-
-$html .= "	    var list = [];  ";
-$html .= "	    Object.keys(hash).forEach(function (key) {";
-$html .= "		if (key != param) {";
-$html .= "	        	list.push(key + '=' + hash[key]);";
-$html .= "		}";
-$html .= "	    });";
-
-$html .= "	    parser.search = '?' + list.join('&');";
-$html .= "	    return parser.href;";
-$html .= "	}";
-
-
-$html .= '</script>';
-//only show map if wfsid is selected
-$html .= "<div id='map'></div>";
-$html .= "<div id='bboxButtons'><input type='button' onclick='location.href = URL_add_parameter(URL_remove_parameter(location.href, \"p\"), \"bbox\", map.getBounds().getWest()+\",\"+map.getBounds().getSouth()+\",\"+map.getBounds().getEast()+\",\"+map.getBounds().getNorth());return false;' value='Set Bbox Filter'><input type='button' onclick='location.href = URL_remove_parameter(URL_remove_parameter(location.href, \"bbox\"), \"p\");return false;' value='Delete Bbox Filter'><input type='button' onclick='location.href = location.href.split(\"?\")[0]';return false;' value='WFS List'></div>";
-
-//div elements
-/*$html .= '<div id="wfs_info"></div>';
-$html .= '<div id="wfs_table"></div>';
-$html .= '<div id="map"></div>';
-$html .= '<div id="featuretype_table"></div>';	
-$html .= '<div id="feature_table"></div>';
-$html .= '<div id="counter"></div>';*/
-//javascripts
-//$html .= '<script src="sample-geojson.js" type="text/javascript"></script>';	
-$html .= '<script>';	
-$html .= "	var map = L.map('map').setView([50, 7.44], 7);";
-
-$html .= "	L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?";
-$html .= "access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {";
-$html .= "		maxZoom: 18,";
-$html .= "		attribution: 'Map data © <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, ' +";
-$html .= "			'<a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +";
-$html .= "			'Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>',";
-$html .= "		id: 'mapbox.light'";
-$html .= "	}).addTo(map);";
-if (!isset($wfsid) || !isset($ft)) {
-	$html .= 'document.getElementById("map").style.display = "none"; ';
-	$html .= 'document.getElementById("bboxButtons").style.display = "none"; ';
-}
-$html .= '</script>';
-
-$htmlFooter = '</body></html>';
-$htmlFooter = '<footer class="footer bg-light py-4 d-flex flex-column justify-content-around align-items-center">';
-$htmlFooter .= '<div class="container d-flex flex-row justify-content-between align-items-center w-100">';
-$htmlFooter .= '<span><span class="text-muted small mr-2">powered by</span><a class="navbar-brand" href="https://git.osgeo.org/gitea/armin11/GeoPortal.rlp" target="_blank">GeoPortal.rlp</a></span>';
-$htmlFooter .= '<span>';
-$htmlFooter .= '</span>';
-$htmlFooter .= '</div>';
-$htmlFooter .= '</footer>';
-
-//php logic	
-//generate list of allowed wfs_ids!
-//TODO
-/*
-*/
-	if (!isset($wfsid) || $wfsid == "") {
-		//list all public available wfs which are classified as opendata!
-		$openWfs = new stdClass();
-		$openWfs->list = array();
-		$sql = "SELECT * FROM (SELECT wfs_id, wfs_version, wfs_abstract, wfs_title, wfs_owsproxy, fkey_termsofuse_id FROM wfs INNER JOIN wfs_termsofuse ON wfs_id = fkey_wfs_id) AS wfs_tou INNER JOIN termsofuse ON fkey_termsofuse_id = termsofuse_id WHERE isopen = 1";
-		//all wfs - without open filter!
-		//$sql = "SELECT wfs_id, wfs_abstract, wfs_version, wfs_title, wfs_owsproxy FROM wfs";
-		$v = array();
-		$t = array();
-		$res = db_prep_query($sql, $v, $t);	
-		$i = 0;	
-		while($row = db_fetch_array($res)){
-			$openWfs->list[$i]->id = $row['wfs_id'];
-			$openWfs->list[$i]->title = $row['wfs_title'];
-			$openWfs->list[$i]->version = $row['wfs_version'];
-			$openWfs->list[$i]->description = $row['wfs_abstract'];
-			$i++;
-		}
-		$html .= '<div id="wfs_info">';	
-		$html .= '<ul class="list-unstyled space-after">';
-		//$html .= "Available WFS:";			
-		//$html .= "<br>";
-		foreach ($openWfs->list as $openWfs) {
-			$html .= '<li itemscope itemtype="http://schema.org/Dataset">';
-			$html .= '<h1>';
-			$html .= '<a itemprop="url" href="'.$_SERVER['REQUEST_URI']."?wfsid=".$openWfs->id.'">';
-			$html .= '<span itemprop="name">'.$openWfs->title.' (WFS '.$openWfs->version.')</span>';
-			$html .= '</a>';
-			$html .= '</h1>';
-			$html .= '<span itemprop="description">'.$openWfs->description.'</span>';
-			$html .= '</li>';	
-			
-		}
-		$html .= '</ul>';
-		$html .= $htmlFooter.'</body></html>';
-		echo $html;
-		die();
+//generate json return object - after this build up html if wished!!!!****************************************************************
+// returnObject differs for service / collection / item
+$returnObject = new stdClass();
+//************************************************************************************************************************************
+//service list part 
+//************************************************************************************************************************************
+if (!isset($wfsid) || $wfsid == "") {
+    //list all public available wfs which are classified as opendata!
+    $returnObject->service = array();
+    $sql = "SELECT * FROM (SELECT wfs_id, wfs_version, wfs_abstract, wfs_title, wfs_owsproxy, fkey_termsofuse_id, wfs_getcapabilities, providername, fees FROM wfs INNER JOIN wfs_termsofuse ON wfs_id = fkey_wfs_id) AS wfs_tou INNER JOIN termsofuse ON fkey_termsofuse_id = termsofuse_id WHERE isopen = 1";
+    //all wfs - without open filter!
+    //$sql = "SELECT wfs_id, wfs_abstract, wfs_version, wfs_title, wfs_owsproxy, wfs_getcapabilities, providername, fees FROM wfs";
+    $v = array();
+    $t = array();
+    $res = db_prep_query($sql, $v, $t);	
+    $i = 0;	
+    while($row = db_fetch_array($res)){
+        $returnObject->service[$i]->id = $row['wfs_id'];
+        $returnObject->service[$i]->title = $row['wfs_title'];
+        $returnObject->service[$i]->version = $row['wfs_version'];
+        $returnObject->service[$i]->description = $row['wfs_abstract'];
+        $returnObject->service[$i]->provider = $row['providername'];
+        $returnObject->service[$i]->license = $row['fees'];
+	$returnObject->service[$i]->accessUrl = $row['wfs_getcapabilities'];
+        //get contraints
+        $constraints = new OwsConstraints();
+        $constraints->languageCode = "de";
+        $constraints->asTable = true;
+        $constraints->id = $returnObject->service[$i]->id;
+        $constraints->type = "wfs";
+        $constraints->returnDirect = false;
+        //$returnObject->service[$i]->tou = json_encode($constraints->getDisclaimer());//TODO encoding problems occur!
+        $i++;
+    } 
+    if ($i == 0) {
+        $returnObject->success = false;
+        $returnObject->message = "No services found in registry";
+    } else {
+        $returnObject->success = true;
+    	$returnObject->message = "Services found in registry!";
+    }
+} else {
+    //************************************************************************************************************************************
+    //service part 
+    //************************************************************************************************************************************
+    //try to instantiate wfs object
+    $myWfsFactory = new UniversalWfsFactory();
+    $wfs = $myWfsFactory->createFromDb($wfsid);
+    if ($wfs == null) {
+	$returnObject->success = false;
+    	$returnObject->message = "Wfs object could not be created from db!";
+    } else {
+	//create service part if no collection is requested		
+	if (!isset($collection) || $collection == "" || $collections == "all") {
+            //************************************************************************************************************************************
+            //service only part 
+            //************************************************************************************************************************************
+	    //add from rlp!
+	    $returnObject->id = $wfsid;
+            $returnObject->title = $wfs->title;
+	    $returnObject->description = $wfs->summary;
+	    $returnObject->provider = $wfs->providerName;
+	    $returnObject->providerEmail = $wfs->electronicMailAddress;
+	    //$returnObject->providerHomepage = $wfs->homepage; //TODO add to ows class!
+            $returnObject->providerHomepage = "http://www.geoportal.rlp.de/";
+	    $returnObject->license = $wfs->fees;
+	    $returnObject->accessUrl = $wfs->getCapabilities;
+	    //
+	    $returnObject->links = array();
+	    $returnObject->crs = array();
+	    $returnObject->collections = array();
+	    $returnObject->links[0]->rel = "self";
+	    $returnObject->links[0]->type = "application/json";
+	    $returnObject->links[0]->title = "this document";
+	    $returnObject->links[0]->href = $_SERVER['REQUEST_URI']."&f=json";
+	    $returnObject->links[1]->rel = "alternate";
+	    $returnObject->links[1]->type = "text/html";
+	    $returnObject->links[1]->title = "this document as HTML";
+	    $returnObject->links[1]->href = $_SERVER['REQUEST_URI']."&f=html";
+	    //TODO service api
+	    //TODO conformance
+	    //TODO data
+	    $returnObject->links[2]->rel = "data";
+	    $returnObject->links[2]->type = "application/json";
+	    $returnObject->links[2]->title = "Metadata about the feature collections";
+	    $returnObject->links[2]->href = $_SERVER['REQUEST_URI']."&collections=all";
+	    //available crs? - howto get from capabilities
+	    
+            //************************************************************************************************************************************
+	    //collection / featuretype list
+            //************************************************************************************************************************************
+	    $collectionArray = array();
+	    $collectionCount = 0;				
+	    foreach ($wfs->featureTypeArray as $featureType) {
+                $returnObject->collections[$collectionCount]->name = $featureType->name;
+		$returnObject->collections[$collectionCount]->title = $featureType->title;
+		$returnObject->collections[$collectionCount]->description = $featureType->description;
+		$returnObject->collections[$collectionCount]->extent->spatial = array();
+		$returnObject->collections[$collectionCount]->links[0]->rel = "item";
+		$returnObject->collections[$collectionCount]->links[0]->type = "application/json";
+                $returnObject->collections[$collectionCount]->links[0]->title = $featureType->title." as GeoJSON";
+		$returnObject->collections[$collectionCount]->links[0]->href = $_SERVER['REQUEST_URI']."&collection=".$featureType->name."&items=all";
+		//one item entry for each format!
+		//self
+		$returnObject->collections[$collectionCount]->links[1]->rel = "self";
+		$returnObject->collections[$collectionCount]->links[1]->type = "application/json";
+                $returnObject->collections[$collectionCount]->links[1]->title = "Information about the ".$featureType->title." data";
+		$returnObject->collections[$collectionCount]->links[1]->href = $_SERVER['REQUEST_URI']."&collection=".$featureType->name;
+		//alternate
+		//TODO
+		$returnObject->collections[$collectionCount]->extent->crs = array();
+		$collectionCount++;
+            }
 	} else {
-		//try to instantiate wfs object
-		$myWfsFactory = new UniversalWfsFactory();
-		$wfs = $myWfsFactory->createFromDb($wfsid);
-
-		if ($wfs == null) {
-			$html .=  "wfs could not be instantiated!";
-			$html .= '</div>';
-		} else {
-			$html .= '</div>';
-			if (isset($ft) && $ft != "") {
-				if (isset($fid) && $fid != "") {		
-					//$html .= '<div id="feature_table">';
-					//header("Content-Type: application/gml+xml;version=3.1");
-					header("Content-Type: ".$outputFormat);
-					
-					echo $wfs->getFeatureById($ft, $outputFormat, $fid, "2.0.0", "EPSG:4326");
-					//$html .= '</div>';
-					//$html .= '</body>';
-					//$html .= '</html>';
-					die();
-				} else {		
-
-					$html .= '<div id="featuretype_info">';
-					$html .= "wfs successfully instantiated! ft is set!";
-					$html .= "<br>";
-					$html .= "wfs title: ".$wfs->title." - version: ".$wfs->getVersion();
-					$html .= "<br>";
-					//$ftNameArray = array();
-					$ftNameInWfs = false;
-					foreach ($wfs->featureTypeArray as $featureType) {
-						//$ftNameArray[] = $featureType->name;
-						if ($featureType->name == $ft) {
-							$ftNameInWfs = true;
-							$ftTitle = $featureType->title;
-							$ftName = $featureType->name;
-							$ftDbId = $featureType->id;
-		//output formats
-							$ftOutputFormats = implode(',', array_unique($featureType->featuretypeOutputFormatArray));
-							//get other relevant ft information
-							break;
-						} 
-					}
-					if ($ftNameInWfs) {
-						//TODO: cache counted features to allow faster access !!!!!
-					
-						$myFeatureType = $wfs->findFeatureTypeByName($ftName);
-						//get geom column name
-//TODO						
-						$geomColumnName = $wfs->findGeomColumnNameByFeaturetypeId($myFeatureType->id);
-
-//get bbox filter if defined!
-						//check for given spatialFilter (bbox)
-						if (isset($bbox) && $bbox != '') {
-							$filter = $wfs->bbox2spatialFilter($bbox, $geomColumnName, $srs="EPSG:4326", $version='2.0.0');
-							//$page = 0;
-						} else { 
-							$filter = null;
-						}
-						//$numberOfObjects = $wfs->countFeatures($ft);
-						//write to cache:
-						if ($cache->isActive) {
-							if ($cache->cachedVariableExists(md5("count_".$wfsid."_".$ft."_".(string)$filter)) == false) {
-								$numberOfObjects = $wfs->countFeatures($ft, $filter);
-								$cache->cachedVariableAdd(md5("count_".$wfsid."_".$ft."_".(string)$filter), $numberOfObjects);
-				
-							} else {
+	    //special collection selected
+	    //is collection one of the featuretypes of this wfs?
+	    //************************************************************************************************************************************
+	    //collection part 
+	    //************************************************************************************************************************************
+	    //test if collection is available in service
+            $ftNameInWfs = false;
+	    foreach ($wfs->featureTypeArray as $featureType) {
+		if ($featureType->name == $collection) {
+		    $ftNameInWfs = true;
+		    $ftTitle = $featureType->title;
+		    $ftName = $featureType->name;
+		    $ftDbId = $featureType->id;
+		    //output formats
+		    $ftOutputFormats = implode(',', array_unique($featureType->featuretypeOutputFormatArray));
+		    //get other relevant ft information
+		    break;
+		} 
+	    }
+	    if ($ftNameInWfs) {
+	        if (!isset($item) || $item == "") {
+		    $myFeatureType = $wfs->findFeatureTypeByName($ftName);			
+		    $geomColumnName = $wfs->findGeomColumnNameByFeaturetypeId($myFeatureType->id);
+		    //generate description of collection in json
+		    $returnObject->name = $myFeatureType->name;
+		    $returnObject->title = $myFeatureType->title;
+		    $returnObject->description = $myFeatureType->abstract;
+		    $returnObject->extent->spatial = array();
+		    $returnObject->extent->temporal = array();
+		    $returnObject->links =array();
+		    $returnObject->links[0]->rel = "item";
+		    $returnObject->links[0]->type = "application/geo+json";
+ 		    $returnObject->links[0]->title = $myFeatureType->title." as GeoJSON";
+                    $returnObject->links[0]->href = $_SERVER['REQUEST_URI']."&collection=".$featureType->name."&items=all&f=json";
+		    //TODO: items in other formats, self, alternate
+		    if ($items == "all") { //show items in list!
+			//reinitialize object!
+			$returnObject = new stdClass();
+			//for rlp:
+			$returnObject->serviceTitle = $wfs->title;
+			$returnObject->collectionId = $myFeatureType->id;
+			$returnObject->collectionName = $ftName;
+			$returnObject->collectionTitle = $myFeatureType->title;
+			//
+			$returnObject->type = "FeatureCollection";
+			$returnObject->links = array();
+			$returnObject->links[0]->rel = "self";
+			$returnObject->links[0]->type = "application/geo+json";			
+			$returnObject->links[0]->title = "this document";
+			$returnObject->links[0]->href = $_SERVER['REQUEST_URI'];
+			//TODO  alternate
+		        //check for given spatialFilter (bbox)
+		        if (isset($bbox) && $bbox != '') {
+		            $filter = $wfs->bbox2spatialFilter($bbox, $geomColumnName, $srs="EPSG:4326", $version='2.0.0');
+		        } else { 
+		            $filter = null;
+		        }
+		        //write number of features to ram cache:
+		        if ($cache->isActive) {
+		            if ($cache->cachedVariableExists(md5("count_".$wfsid."_".$collection."_".(string)$filter)) == false) {
+		                $numberOfObjects = $wfs->countFeatures($collection, $filter);
+		                $cache->cachedVariableAdd(md5("count_".$wfsid."_".$collection."_".(string)$filter), $numberOfObjects);
+		            } else {
 //$e = new mb_exception("read count from cache!");
-								$numberOfObjects = $cache->cachedVariableFetch(md5("count_".$wfsid."_".$ft."_".(string)$filter));
-							}
-							//$e = new mb_notice("http/classes/class_crs.php - store crs info to cache!");
-							//return true;
-						} else {
-							$numberOfObjects = $wfs->countFeatures($ft, $filter);
-			
-						}
-$e = new mb_exception("number of objects: ".$numberOfObjects);
-						//request first object and metadata
-						//count objects
-						$html .= "wfs max features: ".$wfs->wfs_max_features."<br>";
-						$html .=  $ftTitle." (".$numberOfObjects.") - id: " .$ftDbId. " - output formats: ".$ftOutputFormats."<br>";
-						//get first page
-						//calculate pages
-						$numberOfPages = ceil($numberOfObjects / $maxObjectsPerPage);
-						//decide which page should be requested
-						//$page = 0;
-						//calculate offset for requested page
-						if ($page >= $numberOfPages) {
-							echo "requested page exeeds number of max pages!";
-							die();
-						} else {
-							$startIndex = $page * $maxObjectsPerPage;
-						}
-						$html .= '</div>';
-						//get more info for featuretype
-
-//$e = new mb_exception("bbox: ".$bbox);
-
-//$e = new mb_exception("filter: ".$filter);
-						//force version to be 2.0.0!!!!! - hope the server will support it
-						$features = $wfs->getFeaturePaging($ftName, $filter, "EPSG:4326", null, null, $maxObjectsPerPage, $startIndex, "2.0.0");
-						//transform to geojson to allow rendering !
-						$gml3Class = new Gml_3_Factory();
-						//create featuretype object
-//TODO
-
-//$e = new mb_exception("geom column type: ".$geomColumnName);
-						
-						$gml3Object = $gml3Class->createFromXml($features, null, $wfs, $myFeatureType, $geomColumnName);
-//$e = new mb_exception("geojson from mb class: ".json_encode($gml3Object));
-						$geojsonList = new stdClass();
-						$geojsonList->type = "FeatureCollection";
-						$geojsonList->features = array();
-						$geojsonBbox = array();
-						$geojsonIndex = 0;
-						$minxFC = 90;
-						$minyFC = 180;
-						$maxxFC = -90;
-						$maxyFC = -180;
-						$html .= "<script>";
-						foreach($gml3Object->featureCollection->featureArray as $mbFeature) {
-							//$e = new mb_exception("geojson from mb feature exporthandler: ".$mbFeature->toGeoJSON());
-							//bbox
-							$geojsonBbox[$geojsonIndex]->mbBbox = $mbFeature->getBbox();
-							//transform to simple bbox object for leaflet
-							$bbox_new = explode(' ',str_replace(']','',str_replace('[','',$geojsonBbox[$geojsonIndex]->mbBbox)));
-							$bbox_new = explode('|',str_replace(')','',str_replace('(','',str_replace(')(','|',$bbox_new[0]))));
-							$bbox_min = explode(',',$bbox_new[0]);
-							$bbox_max = explode(',',$bbox_new[1]);
-
-							$geojsonBbox[$geojsonIndex]->minx = $bbox_min[0];
-							$geojsonBbox[$geojsonIndex]->miny = $bbox_min[1];
-							$geojsonBbox[$geojsonIndex]->maxx = $bbox_max[0];
-							$geojsonBbox[$geojsonIndex]->maxy = $bbox_max[1];
-							if ($minxFC > $geojsonBbox[$geojsonIndex]->minx) {
-								$minxFC = $geojsonBbox[$geojsonIndex]->minx;
-							}
-							if ($minyFC > $geojsonBbox[$geojsonIndex]->miny) {
-								$minyFC = $geojsonBbox[$geojsonIndex]->miny;
-							}
-							if ($maxxFC < $geojsonBbox[$geojsonIndex]->maxx) {
-								$maxxFC = $geojsonBbox[$geojsonIndex]->maxx;
-							}
-							if ($maxyFC < $geojsonBbox[$geojsonIndex]->maxy){
-								$maxyFC = $geojsonBbox[$geojsonIndex]->maxy;
-							}
-
-							//get geomtype
-							$geomType = json_decode($mbFeature->toGeoJSON())->geometry->type;
-							$geojsonList->features[] = json_decode($mbFeature->toGeoJSON());
-							//$html .= "var feature_".$geomType."=".json_encode($geojsonList->features).";";
-							$geojsonIndex++;
-						}
-						$html .= "var feature_".$geomType."=".json_encode($geojsonList).";";
-						$html .= "</script>";
-						//get number of features returned:
-						//parse hits
-		//$e = new mb_exception($features);
-						try {
-							$featureCollectionObject =  new SimpleXMLElement($features);
-							if ($featureCollectionObject == false) {
-								throw new Exception('Cannot parse WFS features request!');
-							}
-						}
-						catch (Exception $e) {
-				    			$e = new mb_exception($e->getMessage());
-						}
-						//hardcode wfs 2.0.0!
-						switch ("2.0.0") {
-							case "2.0.0":
-								$hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberReturned');
-								break;
-							case "2.0.2":
-								$hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberReturned');
-								break;
-							/*case "1.1.0":
-								$hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberOfFeatures');
-								break;*/
-						}
-						$html .= (integer)$hits[0]." results found for page ".$page."<br>";
-						$html .= "<br>";
-//$e = new mb_exception("ft name: ".$ftName);
-//pagination ****************************************************************************************************************
-						$html .= '<nav id="pagination">';
-    						$html .= '<ul class="pagination mb-4">';
-						//page backward
-						if (($page - 1) >= 0) {
-							 $html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page - 1) ."' target='_self'>". ($page - 1) . "</a><li>";
-						}
-						//page current
-						$html .=  "<li class=\"page-item active\"><a class=\"page-link\" href=\"\">".$page." (".($numberOfPages - 1).")</a><li>";
-						//page forward
-
-						if (($page + 1) < $numberOfPages) {
-							$html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page + 1) ."' target='_self'>". ($page + 1) ."</a></li>";
-						}
-						//depends on the gml version!
-    						$html .= '</ul>';
-						$html .= '</nav>';
-//pagination ****************************************************************************************************************
-						//problem with id: maybe wfs is not configured in the right way!
-						$gmlIds = $featureCollectionObject->xpath('/wfs:FeatureCollection/wfs:member/'.$ftName.'/@gml:id');
-						//$html .= '<div id="feature_table">';
-						$html .= '<ul class="list-unstyled">';
-						$html .= '<li>';
-						$objIndex = 0;
-						foreach ($gmlIds as $gmlId) {
-$html .= '<div  itemscope itemtype="http://schema.org/Place">';
-							//link getfeaturebyid 
-							//echo "gml_id: ".$gmlId."<br>";
-							//echo $gmlId."<br>";
-							//<h4 class="mt-3 mb-1"><a href="https://www.ldproxy.nrw.de/kataster/collections/flurstueck/items/DENW19AL0000geMFFL?f=html&relations=bahnstrecken,gewaesser&resolve=true"><span itemprop="name">Bad Wünnenberg, Wünnenberg, 016 </span></a></h4>
-							//$html .= "<a  href='#' onclick='zoomToExtent(".$geojsonBbox[$objIndex]->minx.",".$geojsonBbox[$objIndex]->miny.",".$geojsonBbox[$objIndex]->maxx.",".$geojsonBbox[$objIndex]->maxy.");return false;'>".$gmlId."</a><br>";
-							//title
-							$html .= "<h4 class=\"mt-3 mb-1\"><a href=\"#\" onclick='zoomToExtent(".$geojsonBbox[$objIndex]->minx.",".$geojsonBbox[$objIndex]->miny.",".$geojsonBbox[$objIndex]->maxx.",".$geojsonBbox[$objIndex]->maxy.");return false;'><span itemprop=\"name\">".$gmlId."</span></a></h4>";
-							//$gmlIds = $featureCollectionObject->xpath('/wfs:FeatureCollection/wfs:member/'.$ftName.'/@gml:id');
-							//$geojsonList->features[$objIndex];
-							foreach(explode(",", $ftOutputFormats) as $outputFormat) {
-								$html .= "<a href='".$_SERVER['REQUEST_URI']."&fid=".$gmlId."&outputFormat=".$outputFormat."' target='_blank'>".$outputFormat."</a><br>";
-							}
-							foreach($geojsonList->features[$objIndex]->properties as $key=>$value) {
-								$html .= '<div class="row my-1">';
-								$html .= '<div class="col-md-6 font-weight-bold text-truncate" title="'.$key.'">'.$key.'</div>';
-								$html .= '<div class="col-md-6" >'.string2html($value).'</div>';
-								//$html .= $key.":".$value."<br>";
-								$html .= '</div>';
-							}
-							$html .= "<br>";
-							$objIndex++;
-$html .= '</div>';
-						}
-						$html .=  "</li>";
-						//$html .= '</div>';
-						$html .= '</ul>';
-//pagination ****************************************************************************************************************
-						$html .= '<nav id="pagination">';
-    						$html .= '<ul class="pagination mb-4">';
-						//page backward
-						if (($page - 1) >= 0) {
-							 $html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page - 1) ."' target='_self'>". ($page - 1) . "</a><li>";
-						}
-						//page current
-						$html .=  "<li class=\"page-item\"><a class=\"page-link\" href=\"\">".$page." (".($numberOfPages - 1).")</a><li>";
-						//page forward
-
-						if (($page + 1) < $numberOfPages) {
-							$html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page + 1) ."' target='_self'>". ($page + 1) ."</a></li>";
-						}
-									//depends on the gml version!
-    						$html .= '</ul>';
-						$html .= '</nav>';
-//pagination ****************************************************************************************************************
-						//$e = new mb_exception($features);
-			
-					} else {
-						$html .=  "ft not in wfs - operation not possible!";
-						//request first object and metadata
-						//count objects
+		                $numberOfObjects = $cache->cachedVariableFetch(md5("count_".$wfsid."_".$collection."_".(string)$filter));
+		            }
+		            //$e = new mb_notice("http/classes/class_crs.php - store crs info to cache!");
+		            //return true;
+		        } else {
+		            $numberOfObjects = $wfs->countFeatures($collection, $filter);
+		        }
+			//$e = new mb_exception("number of objects: ".$numberOfObjects);
+		        //request first object and metadata
+		        //count objects
+		        //TODO - create json
+		        //$html .= "wfs max features: ".$wfs->wfs_max_features."<br>";
+		        //$html .=  $ftTitle." (".$numberOfObjects.") - id: " .$ftDbId. " - output formats: ".$ftOutputFormats."<br>";
+		        //get first page
+		        //calculate pages
+		        //$numberOfPages = ceil($numberOfObjects / $maxObjectsPerPage);
+			$numberOfPages = ceil($numberOfObjects / $limit);
+		        //decide which page should be requested
+		        //$page = 0;
+		        //calculate offset for requested page
+		        if ($page >= $numberOfPages) {
+			    $returnObject->success = false;
+    			    $returnObject->message = "Requested page exeeds number of max pages!";
+			    if ($f == "json") {
+			        header("application/json");
+			        echo json_encode($returnObject);
+			    }	
+		            die();
+		        } else {
+		            $startIndex = $page * $maxObjectsPerPage;
+		        }
+			if (!isset($offset)) {
+			    $offset = 0;
+			}
+			$lastOffset = ($numberOfPages - 1) * $limit ;
+			$startIndex = $offset;
+			//next page
+			$returnObject->links[1]->rel = "next";
+			$returnObject->links[1]->type = "application/geo+json";			
+			$returnObject->links[1]->title = "next page";
+			//$returnObject->links[1]->href = $_SERVER['REQUEST_URI']."&p=".($page + 1);
+			$returnObject->links[1]->href = $_SERVER['REQUEST_URI']."&offset=".($offset + 1 * $limit)."&limit=".$limit;
+			//for rlp
+			$returnObject->links[2]->rel = "last";
+			$returnObject->links[2]->type = "application/geo+json";			
+			$returnObject->links[2]->title = "last page";
+			//$returnObject->links[1]->href = $_SERVER['REQUEST_URI']."&p=".($page + 1);
+			$returnObject->links[2]->href = $_SERVER['REQUEST_URI']."&offset=".$lastOffset."&limit=".$limit;
+			//check if outputformat geojson is available - if - gml don't need to be parsed!!!!! TODO - where to become hits ????? - has to count in a special request!!!!!
+			if (in_array('application/json; subtype=geojson', explode(',', $ftOutputFormats)) && $nativeJson == true) {
+			//if (false) {
+			    $features = $wfs->getFeaturePaging($ftName, $filter, "EPSG:4326", null, null, $maxObjectsPerPage, $startIndex, "2.0.0", 'application/json; subtype=geojson');
+			    $geojsonList = json_decode($features);
+			    $geojsonBbox = array();
+			    $geojsonIndex = 0;
+			    $minxFC = 90;
+			    $minyFC = 180;
+			    $maxxFC = -90;
+			    $maxyFC = -180;
+			    $minxF = 90;
+			    $minyF = 180;
+			    $maxxF = -90;
+			    $maxyF = -180;
+ 			    if ($f == 'html'){
+				$geoJsonVariable = "";
+				$geoJsonVariable = '<script>'.$newline;
+			    }
+			    //read geojson to calculate bboxes
+			    foreach ($geojsonList->features as $feature) {
+				$minxF = 90;
+			    	$minyF = 180;
+			    	$maxxF = -90;
+			    	$maxyF = -180;
+				switch ($feature->geometry->type) {
+				    case "Polygon":
+					foreach ($feature->geometry->coordinates[0] as $lonLat){
+					    $lon = $lonLat[0];
+					    $lat = $lonLat[1];
+					    if ($minxF > $lat) {
+						$minxF = $lat;
+					    }
+					    if ($minyF > $lon) {
+						$minyF = $lon;
+					    }
+					    if ($maxxF < $lat) {
+					       $maxxF = $lat;
+					    }
+					    if ($maxyF < $lon){
+						$maxyF = $lon;
+					    }
 					}
+					break;
+				    case "Point":
+					$lon = $feature->geometry->coordinates[0];
+					$lat = $feature->geometry->coordinates[1];
+					if ($minxF > $lat) {
+					    $minxF = $lat;
+					}
+					if ($minyF > $lon) {
+					    $minyF = $lon;
+					}
+					if ($maxxF < $lat) {
+					    $maxxF = $lat;
+					}
+					if ($maxyF < $lon){
+					    $maxyF = $lon;
+					}
+					break;
+				    case "LineString":
+					foreach ($feature->geometry->coordinates as $lonLat){
+					    $lon = $lonLat[0];
+					    $lat = $lonLat[1];
+					    if ($minxF > $lat) {
+						$minxF = $lat;
+					    }
+					    if ($minyF > $lon) {
+						$minyF = $lon;
+					    }
+					    if ($maxxF < $lat) {
+					       $maxxF = $lat;
+					    }
+					    if ($maxyF < $lon){
+						$maxyF = $lon;
+					    }
+					}
+					break;
+				} 
+//$e = new mb_exception("bbox feature: minxF:".$minxF." minyF:".$minyF." maxxF:".$maxxF." maxyF:".$maxyF."");
+				if ($minxFC > $minxF) {
+				    $minxFC = $minxF;
 				}
-
+				if ($minyFC > $minyF) {
+				    $minyFC = $minyF;
+				}
+				if ($maxxFC < $maxxF) {
+				   $maxxFC = $maxxF;
+				}
+				if ($maxyFC < $maxyF){
+				    $maxyFC = $maxyF;
+				}
+				$geojsonBbox[$geojsonIndex]->minx = $minxF;
+				$geojsonBbox[$geojsonIndex]->miny = $minyF;
+				$geojsonBbox[$geojsonIndex]->maxx = $maxxF;
+				$geojsonBbox[$geojsonIndex]->maxy = $maxyF;
+				$geomType = $feature->geometry->type;
+			        $geojsonIndex++;
+//$e = new mb_exception("bbox featurecollection: minxFC:".$minxFC." minyFC:".$minyFC." maxxFC:".$maxxFC." maxyFC:".$maxyFC."");
+			    }
+			    /*header('application/json');
+			    echo $features;
+			    die();*/
 			} else {
-				$html .= '<div id="wfs_info">';
-				$html .= "wfs successfully instantiated!";
-				$html .= "<br>";
-				$html .= "wfs title: ".$wfs->title." - version: ".$wfs->getVersion();
-				$html .= "<br>";
-				$ftNameArray = array();					
-				$html .= '</div>';				
-				$html .= '<div id="featuretype_table">';
-				foreach ($wfs->featureTypeArray as $featureType) {
-					//$numberOfObjects = $wfs->countFeatures($featureType->name);
-					$html .= "<a href='".$_SERVER['REQUEST_URI']."&ft=".$featureType->name."' target='_self'>".$featureType->title." (".$featureType->name.")</a><br>";
-					//echo "featuretype: <a href='".$_SERVER['REQUEST_URI']."&ft=".$featureType->name."'".$featureType->name." - objects: ".$numberOfObjects."<br>";
-
-			
-			/*$ft = $wfs->findFeatureTypeByName($featureType->name);
-
-					foreach ($ft->featuretypeOutputFormatArray as $outputFormat) {
-						echo "		format: ".$outputFormat."<br>";
-					}*/
+			    $features = $wfs->getFeaturePaging($ftName, $filter, "EPSG:4326", null, null, $maxObjectsPerPage, $startIndex, "2.0.0");
+			    //transform to geojson to allow rendering !
+			    $gml3Class = new Gml_3_Factory();
+			    //create featuretype object
+			    //TODO
+	//$e = new mb_exception("geom column type: ".$geomColumnName);	
+			    $gml3Object = $gml3Class->createFromXml($features, null, $wfs, $myFeatureType, $geomColumnName);
+	//$e = new mb_exception("geojson from mb class: ".json_encode($gml3Object));
+			    $geojsonList = new stdClass();
+			    $geojsonList->type = "FeatureCollection";
+			    $geojsonList->features = array();
+			    $geojsonBbox = array();
+			    $geojsonIndex = 0;
+			    $minxFC = 90;
+			    $minyFC = 180;
+			    $maxxFC = -90;
+			    $maxyFC = -180;
+			    //TODO write javascript object if to var if html is requested
+			    if ($f == 'html'){
+				$geoJsonVariable = "";
+				$geoJsonVariable = '<script>'.$newline;
+			    }
+			    foreach($gml3Object->featureCollection->featureArray as $mbFeature) {
+	//$e = new mb_exception("geojson from mb feature exporthandler: ".$mbFeature->toGeoJSON());
+			        //bbox
+			        $geojsonBbox[$geojsonIndex]->mbBbox = $mbFeature->getBbox();
+			        //transform to simple bbox object for leaflet
+				$bbox_new = explode(' ',str_replace(']','',str_replace('[','',$geojsonBbox[$geojsonIndex]->mbBbox)));
+				$bbox_new = explode('|',str_replace(')','',str_replace('(','',str_replace(')(','|',$bbox_new[0]))));
+				$bbox_min = explode(',',$bbox_new[0]);
+				$bbox_max = explode(',',$bbox_new[1]);
+				$geojsonBbox[$geojsonIndex]->minx = $bbox_min[0];
+				$geojsonBbox[$geojsonIndex]->miny = $bbox_min[1];
+				$geojsonBbox[$geojsonIndex]->maxx = $bbox_max[0];
+				$geojsonBbox[$geojsonIndex]->maxy = $bbox_max[1];
+				if ($minxFC > $geojsonBbox[$geojsonIndex]->minx) {
+				    $minxFC = $geojsonBbox[$geojsonIndex]->minx;
 				}
-				$html .= '</div>';
+				if ($minyFC > $geojsonBbox[$geojsonIndex]->miny) {
+				    $minyFC = $geojsonBbox[$geojsonIndex]->miny;
+				}
+				if ($maxxFC < $geojsonBbox[$geojsonIndex]->maxx) {
+				    $maxxFC = $geojsonBbox[$geojsonIndex]->maxx;
+				}
+				if ($maxyFC < $geojsonBbox[$geojsonIndex]->maxy){
+				    $maxyFC = $geojsonBbox[$geojsonIndex]->maxy;
+				}
+				//get geomtype
+				$geomType = json_decode($mbFeature->toGeoJSON())->geometry->type;
+				$geojsonList->features[] = json_decode($mbFeature->toGeoJSON());
+				$geojsonIndex++;
+			    }
 			}
+			if ($f == 'html'){
+			    $geoJsonVariable .= "var feature_".$geomType."=".json_encode($geojsonList).";";
+			    $geoJsonVariable .= $newline."</script>".$newline;
+			}
+//$e = new mb_exception($geoJsonVariable);
+
+			$usedProxyTime = microtime_float() - $proxyStartTime;
+			$returnObject->numberMatched = $numberOfObjects;
+			$returnObject->numberReturned = $geojsonIndex;
+			$date = new DateTime();
+			$returnObject->timeStamp = date('Y-m-d\TH:i:s.Z\Z', $date->getTimestamp());
+			$returnObject->genTime = $usedProxyTime;
+			$returnObject->features = $geojsonList->features;
+		    }
+		} else {	            
+		    //************************************************************************************************************************************
+	            //item part 
+	            //************************************************************************************************************************************
+		}	
+	    } else {
+		$returnObject->success = false;
+    	        $returnObject->message = "Collection/Featuretype not available in service!";
+            }
 	}
-//add javascript things that have be done after !
-$html .= "<script>";
-$html .= "	function onEachFeature(feature, layer) {";
-$html .= "		var popupContent = \"<p>I started out as a GeoJSON \" +";
-$html .= "				feature.geometry.type + \", but now I'm a Leaflet vector!</p>\";";
+    }
+}
 
-$html .= "		if (feature.properties && feature.properties.popupContent) {";
-$html .= "			popupContent += feature.properties.popupContent;";
-$html .= "		}";
-$html .= "		for (var key in feature.properties){";
-$html .= "		    	var value = feature.properties[key];";
-$html .= "		   	popupContent += \"<br>\"+key+\": \"+value;";
-$html .= "		}";
+//************************************************************************************************************************************
+//item part 
+//************************************************************************************************************************************
 
-$html .= "		layer.bindPopup(popupContent);";
-$html .= "	}";
 
+switch ($f) {
+    case "json":
+	header("application/json");
+	echo json_encode($returnObject);
+	break;
+    case "html":
+	$js1 = '<script>'.$newline;
+	//https://stackoverflow.com/questions/5997450/append-to-url-and-refresh-page
+	$js1 .= "	function URL_add_parameter(url, param, value){"."\n";
+	$js1 .= "	    var hash       = {};";
+	$js1 .= "	    var parser     = document.createElement('a');";
+	$js1 .= "	    parser.href    = url;";
+	$js1 .= "	    var parameters = parser.search.split(/\?|&/);";
+	$js1 .= "	    for(var i=0; i < parameters.length; i++) {";
+	$js1 .= "	        if(!parameters[i])";
+	$js1 .= "	            continue;";
+	$js1 .= "	        var ary      = parameters[i].split('=');";
+	$js1 .= "	        hash[ary[0]] = ary[1];";
+	$js1 .= "	    }";
+	$js1 .= "	    hash[param] = value;";
+	$js1 .= "	    var list = [];  ";
+	$js1 .= "	    Object.keys(hash).forEach(function (key) {";
+	$js1 .= "	        list.push(key + '=' + hash[key]);";
+	$js1 .= "	    });";
+	$js1 .= "	    parser.search = '?' + list.join('&');";
+	$js1 .= "	    return parser.href;";
+	$js1 .= "	}";
+	$js1 .= "	function URL_remove_parameter(url, param){";
+	$js1 .= "	    var hash       = {};";
+	$js1 .= "	    var parser     = document.createElement('a');";
+	$js1 .= "	    parser.href    = url;";
+	$js1 .= "	    var parameters = parser.search.split(/\?|&/);";
+	$js1 .= "	    for(var i=0; i < parameters.length; i++) {";
+	$js1 .= "	        if(!parameters[i])";
+	$js1 .= "	            continue;";
+	$js1 .= "	        var ary      = parameters[i].split('=');";
+	$js1 .= "	        hash[ary[0]] = ary[1];";
+	$js1 .= "	    }";
+	$js1 .= "	    hash[param] = 0;";
+	$js1 .= "	    var list = [];  ";
+	$js1 .= "	    Object.keys(hash).forEach(function (key) {";
+	$js1 .= "		if (key != param) {";
+	$js1 .= "	        	list.push(key + '=' + hash[key]);";
+	$js1 .= "		}";
+	$js1 .= "	    });";
+	$js1 .= "	    parser.search = '?' + list.join('&');";
+	$js1 .= "	    return parser.href;";
+	$js1 .= "	}";
+	$js1 .= $newline.'</script>'.$newline;
 
-//zoom to featurecollection
-//$e = new mb_exception($minxFC.",".$minyFC.",".$maxxFC.",".$maxyFC);
+$js2 = '<script>'.$newline;	
+$js2 .= "	var map = L.map('map').setView([50, 7.44], 7);";
 
-$html .= "		map.fitBounds([";
-$html .= "   				[".$minxFC.",".$minyFC."],";
-$html .= "   				[".$maxxFC.",".$maxyFC."]";
-$html .= "			]);";	
-
-$html .= "	L.geoJSON([feature_".$geomType."], {";
-$html .= "		style: function (feature) {";
-$html .= "			return feature.properties && feature.properties.style;";
-$html .= "		},";
-$html .= "		onEachFeature: onEachFeature,";
-$html .= "		pointToLayer: function (feature, latlng) {";
-$html .= "			return L.circleMarker(latlng, {";
-$html .= "				radius: 8,";
-$html .= "				fillColor: \"#ff7800\",";
-$html .= "				color: \"#000\",";
-$html .= "				weight: 1,";
-$html .= "				opacity: 1,";
-$html .= "				fillOpacity: 0.8";
-$html .= "			});";
-$html .= "		}";
-$html .= "	}).addTo(map);";
-
-/*$html .= "	map.on('dragged', function() { ";
-$html .= "	     alert(map.getBounds());";
-$html .= "	});";*/
-
-
-$html .= "	function zoomToExtent(minx,miny,maxx,maxy) {";
-$html .= "		map.fitBounds([";
-$html .= "   				[minx, miny],";
-$html .= "   				[maxx, maxy]";
-$html .= "			]);";	
-$html .= "	}";
-
-/*map.fitBounds([
-    [40.712, -74.227],
-    [40.774, -74.125]
-]);*/
-
-
-
-
-$html .= "</script>";
-$html .= '</body></html>';
-echo $html;
+$js2 .= "	L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?";
+$js2 .= "access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {";
+$js2 .= "		maxZoom: 18,";
+$js2 .= "		attribution: 'Map data © <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, ' +";
+$js2 .= "			'<a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +";
+$js2 .= "			'Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>',";
+$js2 .= "		id: 'mapbox.light'";
+$js2 .= "	}).addTo(map);";
+if (!isset($wfsid) || !isset($ft)) {
+	$js2 .= 'document.getElementById("map").style.display = "none"; ';
+	//$js2 .= 'document.getElementById("bboxButtons").style.display = "none"; ';
 }
+$js2 .= $newline.'</script>'.$newline;
+	$newline = "\n";
+	//define header and navigation bar
+	$html = '';
+	$html .= '<!DOCTYPE html>'.$newline;
+	$html .= '<html>'.$newline;
+	$html .= '<head>'.$newline;
+	$html .= '<title>Mapbender WFS OpenLinkedData Proxy</title>'.$newline;
+	$html .= '<meta http-equiv="X-UA-Compatible" content="IE=edge">'.$newline;
+	$html .= '<meta charset="utf-8" />'.$newline;
+	$html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">'.$newline;	
+	//$html .= '<link rel="shortcut icon" type="image/x-icon" href="" />';
+	//leaflet css
+	$html .= '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>'.$newline;
+	//leaflet js
+	$html .= '<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" crossorigin=""></script>'.$newline;
+	//bootstrap
+	$html .= '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">'.$newline;
+    	$html .= '<link rel="stylesheet" href="../css/ldproxy_ia.css"/>'.$newline;
+	//own styles - mapviewer ...
+	$html .= '<style>
+	#map {
+		width: 600px;
+		height: 400px;
+	}
+</style>'.$newline;
+	//************************************************************************************************************************************
+	$html .= '<body>'.$newline;
+	//************************************************************************************************************************************
+	//navbar
+	$html .= '<nav class="navbar navbar-light bg-light navbar-expand-sm">'.$newline;
+	$html .= '<div class="container">'.$newline;
+	$html .= '<div id="navbar" class="navbar-collapse collapse d-flex justify-content-between align-items-center">'.$newline;
+	$html .= '<ol class="breadcrumb bg-light my-0 pl-0">'.$newline;
+	//
+	if (!isset($wfsid)){ // && (!isset($collection) || ($collections != 'all'))) {
+	    $html .= '<li class="breadcrumb-item active">Datasets</li>'.$newline;
+	} else {
+	    if (!isset($collection) || $collections == 'all') {
+	        $html .= '<li class="breadcrumb-item"><a href="'.delTotalFromQuery("wfsid", $_SERVER['REQUEST_URI']).'">Datasets</a></li>'.$newline; //TODO - use base uri
+                $html .= '<li class="breadcrumb-item active">'.$returnObject->title.'</li>'.$newline;
+	    } else {
+		if (!isset($item) || $items == 'all') {
+		    $html .= '<li class="breadcrumb-item"><a href="'.delTotalFromQuery(array("wfsid","collection","collections","item","items","limit","offset","bbox"), $_SERVER['REQUEST_URI']).'">Datasets</a></li>'.$newline; //TODO - use base uri
+                    $html .= '<li class="breadcrumb-item"><a href="'.delTotalFromQuery(array("collection","collections","item","items","limit","offset","bbox"), $_SERVER['REQUEST_URI']).'">'.$returnObject->serviceTitle.'</a></li>'.$newline;
+                    $html .= '<li class="breadcrumb-item active">'.$returnObject->collectionTitle.'</li>'.$newline;
+		}
+	    }
+	    /* other formats ! for collection, item, ...
+            <ul class="list-separated m-0 p-0 text-muted">
+                        <li><a href="https://www.ldproxy.nrw.de/topographie/collections/ax_bergbaubetrieb/items?f=json" target="_blank">GeoJSON</a></li>
+                        <li><a href="https://www.ldproxy.nrw.de/topographie/collections/ax_bergbaubetrieb/items?f=xml" target="_blank">GML</a></li>
+            </ul> 
+            */
+	}
+	//
+	$html .= '</ol>'.$newline;
+	$html .= '<ul class="list-separated m-0 p-0 text-muted">'.$newline;
+	$html .= '</ul>'.$newline;        
+	$html .= '</div>'.$newline;
+	$html .= '<!--button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">'.$newline;
+	$html .= '<span class="navbar-toggler-icon"></span>'.$newline;
+	$html .= '</button-->'.$newline;
+	$html .= '</div>'.$newline;
+	$html .= '</nav>'.$newline;
+	//
+	//logic
+	if (!isset($wfsid)) {
+	//header for proxy
+	    $html .= "";
+	    $html .= '<div class="container py-4">'.$newline;
+	    $html .= '    <div itemscope itemtype="http://schema.org/DataCatalog">'.$newline;
+	    $html .= '        <h1 itemprop="name">Geodaten des Landes Rheinland-Pfalz</h1>'.$newline;
+	    $html .= '        <p itemprop="description">Unter einer offenen Lizenz publizierte Geodaten des Landes Rheinland-Pfalz als LinkedOpenData.</p>'.$newline;
+	    $html .= '        <p itemprop="url" class="d-none">https://www.opendata.geoportal.rlp.de/</p>'.$newline;
+	    $html .= '        <br/>'.$newline;
+	    $html .= '        <br/>'.$newline;
+	    $html .= '        <br/>'.$newline;
+    	    $html .= '        <ul class="list-unstyled space-after">'.$newline;
+	    foreach ($returnObject->service as $service) {
+	        $html .= '            <li itemprop="dataset" itemscope itemtype="http://schema.org/Dataset">'.$newline;
+                $html .= '                <h2>'.$newline;
+                $html .= '                    <a itemprop="url" href="'.$_SERVER['REQUEST_URI'].'&wfsid='.$service->id.'">'.$newline;
+                $html .= '                        <span itemprop="name">'.$service->title.'</span>'.$newline;
+                $html .= '                    </a>'.$newline;
+                $html .= '                </h2>'.$newline;
+                $html .= '                <span itemprop="description">'.$service->description.'</span>'.$newline;
+                $html .= '                <span itemprop="sameAs" class="d-none">/ad-links</span>'.$newline;
+                $html .= '            </li>'.$newline;						
+	    }
+	    $html .= '        </ul>'.$newline;
+	} else {
+	    if (!isset($collection) || $collections == 'all') {
+//$e = new mb_exception(json_encode($returnObject));
+		//show service and collection info
+		//service	    
+		$html .= "";
+		$html .= '<div class="container py-4">'.$newline;
+                $html .= '    <div itemscope itemtype="http://schema.org/Dataset">'.$newline;
+        	$html .= '        <h1 itemprop="name">'.$returnObject->title.'</h1>'.$newline;
+       	 	$html .= '        <span itemprop="description">'.$returnObject->description.'</span>'.$newline;
+        	$html .= '        <p itemprop="url" class="d-none">'.$_SERVER['REQUEST_URI'].'</p>'.$newline;//TODO canonical url
+            	$html .= '        <div itemprop="includedInDataCatalog" itemscope itemtype="http://schema.org/Datacatalog" class="d-none">'.$newline;
+                $html .= '            <div itemprop="url">https://www.ldproxy.nrw.de/'.$_SERVER['REQUEST_URI'].'</div>'.$newline;//TODO canonical url
+            	$html .= '        </div>'.$newline;
+//ul 0 for keywords ...
+//ul 1..n for distribution - each a download url to a wfs featuretype in different formats!
+//new div for collections:
+//collection
+        	$html .= '        <div class="row my-3">'.$newline;
+            	$html .= '            <div class="col-md-2 font-weight-bold">Collections</div>'.$newline;
+            	$html .= '            <div class="col-md-10">'.$newline;
+                $html .= '                <ul class="list-unstyled">'.$newline;
+		foreach($returnObject->collections as $collection) {
+		    //get url to further page
+		    foreach ($collection->links as $link) {
+			if ($link->rel == 'item') {
+			        $collectionHtmlUrl = delTotalFromQuery("f", $link->href)."&f=html";
+			    break;
+			}
+		    }
+                    $html .= '                    <li>'.$newline;
+                    $html .= '                        <a href="'.$collectionHtmlUrl.'">'.$collection->title.'</a>'.$newline;
+                    $html .= '                    </li>'.$newline;
+		}
+                $html .= '            </div>'.$newline;
+                $html .= '        </div>'.$newline;
+//further information about the service API TODO
+                $html .= '        <div class="row my-3">'.$newline;
+                $html .= '            <div class="col-md-2 font-weight-bold">API Definition</div>'.$newline;
+                $html .= '            <div class="col-md-10">'.$newline;
+                $html .= '                <a href="https://www.geoportal.rlp.de/registry/wfs/1/collection/1/api?f=html">TODO!</a>'.$newline;
+                $html .= '            </div>'.$newline;
+                $html .= '        </div>'.$newline;
+//further information about the service DATASOURCE TODO
+                $html .= '        <div class="row my-3">'.$newline;
+                $html .= '            <div class="col-md-2 font-weight-bold">Data source</div>'.$newline;
+                $html .= '            <div class="col-md-10">'.$newline;
+                $html .= '                <a itemprop="isBasedOn" href="'.$returnObject->accessUrl.'" target="_blank">'.$returnObject->accessUrl.'</a>'.$newline;
+                $html .= '            </div>'.$newline;
+                $html .= '        </div>'.$newline;
+//further information about the service PROVIDER TODO
+                $html .= '        <div class="row my-3">'.$newline;
+                $html .= '            <div class="col-md-2 font-weight-bold">Provider</div>'.$newline;
+                $html .= '            <div class="col-md-10">'.$newline;
+                $html .= '                <ul class="list-unstyled" itemprop="creator" itemscope itemtype="http://schema.org/Organization">'.$newline;
+                $html .= '                    <li itemprop="name">'.$returnObject->provider.'</li>'.$newline;
+                $html .= '                    <li itemprop="url"><a href="'.$returnObject->providerHomepage.'" target="_blank">'.$returnObject->providerHomepage.'</a></li>'.$newline;
+                $html .= '                    <li itemprop="contactPoint" itemscope itemtype="http://schema.org/ContactPoint">'.$newline;
+                $html .= '                        <span class="d-none" itemprop="contactType">technical support</span>'.$newline;
+                $html .= '                        <ul class="list-unstyled">'.$newline;
+                $html .= '                            <li itemprop="email">'.$returnObject->providerEmail.'</li>'.$newline;
+                $html .= '                            <li itemprop="url" class="d-none">'.$returnObject->providerHomepage.'</li>'.$newline;
+                $html .= '                        </ul>'.$newline;
+                $html .= '                    </li>'.$newline;
+                $html .= '                </ul>'.$newline;
+                $html .= '            </div>'.$newline;
+                $html .= '        </div>'.$newline;
+//further information about the service LICENSE TODO
+                $html .= '        <div class="row my-3">'.$newline;
+                $html .= '        <div class="col-md-2 font-weight-bold">License</div>'.$newline;
+                $html .= '         <div class="col-md-10">'.$newline;
+                $html .= '        <div itemprop="license">'.$returnObject->license.'</div>'.$newline;
+                $html .= '        </div>'.$newline;
+                $html .= '        </div>'.$newline;
+                $html .= '        <div itemprop="temporalCoverage" class="d-none">2018-05-18T14:45:11.573Z/2019-08-05T06:27:56.536Z</div>'.$newline; //TODO
+                $html .= '        <div itemprop="spatialCoverage" itemscope itemtype="http://schema.org/Place" class="d-none"><div itemprop="geo" itemscope itemtype="http://schema.org/GeoShape"><div itemprop="box">50.237351 5.612726 52.528630 9.589634</div>'.$newline; //TODO
+                $html .= '        </div>'.$newline;
+                $html .= '        </div>'.$newline;
+		$html .= '    </div>'.$newline;
+		$html .= '</div>'.$newline;		
+	    } else {
+		//collection is selected - show items 
+		if (!isset($item) || $items == 'all') {
+		    $html .= '<div class="container py-4">'.$newline;	
+		    $html .= '    <div>'.$newline;
+		    $html .= '        <h1>'.$returnObject->collectionTitle.' ('.$numberOfObjects.')'.'</h1>'.$newline;
+		    $html .= '        <span></span>'.$newline;
+		    $html .= '        <br/>'.$newline;
+		    $html .= '        <br/>'.$newline;
+		    $html .= '    </div>'.$newline;
+		    //TODO - further filter options
+		    $html .= '<div id="app-wrapper" class="mb-5">'.$newline;
+		    $html .= '<div class="row mb-3">'.$newline;
+		    $html .= '<div class=" flex-row justify-content-start align-items-center flex-wrap col-md-3">'.$newline;
+		    $html .= '<span class="mr-2 font-weight-bold">Filter</span>';
+		    if (isset($bbox) && $bbox != "") {
+		        $html .= '<div class="mr-1 my-1 btn-group"><button disabled="" style="opacity: 1;" class="py-0 btn btn-primary btn-sm disabled">bbox≈'.$bbox.'</button><button type="button" aria-haspopup="true" aria-expanded="false" class="py-0 btn btn-danger btn-sm" onclick="location.href = URL_remove_parameter(URL_remove_parameter(location.href, \'bbox\'), \'offset\');return false;">×</button></div>'.$newline;
+		    }
+		    $html .= '<button type="button" id="edit_filter_button" class="py-0 btn btn-outline-secondary btn-sm collapse show" onclick="var elements = [\'edit_filter_button\',  \'cancel_filter_button\', \'filter_div\']; elements.forEach(myFunction); function myFunction(item) { var element = document.getElementById(item);element.classList.toggle(\'show\'); };">Edit</button>';
+		    //$html .= '<button type="button" id="apply_filter_button" class="py-0 btn btn-outline-secondary btn-sm collapse" onclick="">Apply</button>';
+		    $html .= '<button type="button" id="cancel_filter_button" class="py-0 btn btn-outline-secondary btn-sm collapse" onclick="var elements = [\'edit_filter_button\', \'cancel_filter_button\', \'filter_div\']; elements.forEach(myFunction); function myFunction(item) { var element = document.getElementById(item);element.classList.toggle(\'show\'); };">Cancel</button>'.$newline;
+		    //bbox filter part from ldproxy
+		    $html .= '<div id="filter_div" class="collapse">'.$newline;
+		    $html .= '            <form class="">'.$newline;
+		    $html .= '		<p class="text-muted text-uppercase">bbox</p>'.$newline;
+		    $html .= '		<div class="row">'.$newline;
+		    $html .= '		    <div class="col-md-5">'.$newline;
+		    $html .= '		        <div class="form-group">'.$newline;
+		    $html .= '			    <input name="minLng" id="minLng" readonly="" class="mr-2 form-control-sm form-control" value="5.767822265625001" type="text">'.$newline;
+		    $html .= '			</div>'.$newline;
+		    $html .= '		    </div>'.$newline;
+		    $html .= '		    <div class="col-md-5">'.$newline;
+		    $html .= '		        <div class="form-group">'.$newline;
+		    $html .= '			    <input name="minLat" id="minLat" readonly="" class="mr-2 form-control-sm form-control" value="50.317408112618715" type="text">'.$newline;
+		    $html .= '		        </div>'.$newline;
+		    $html .= '		    </div>'.$newline;
+		    $html .= '	        </div>'.$newline;
+		    $html .= '	        <div class="row">'.$newline;
+		    $html .= '		    <div class="col-md-5">'.$newline;
+		    $html .= '		        <div class="form-group">'.$newline;
+		    $html .= '			    <input name="maxLng" id="maxLng" readonly="" class="mr-2 form-control-sm form-control" value="9.459228515625002" type="text">'.$newline;
+		    $html .= '		        </div>'.$newline;
+		    $html .= '		    </div>'.$newline;
+		    $html .= '		    <div class="col-md-5">'.$newline;
+		    $html .= '		        <div class="form-group">'.$newline;
+		    $html .= '  		            <input name="maxLat" id="maxLat" readonly="" class="mr-2 form-control-sm form-control" value="52.52958999943304" type="text">'.$newline;
+		    $html .= '		        </div>'.$newline;
+		    $html .= '		    </div>'.$newline;
+		    $html .= '		    <div class="col-md-2">'.$newline;
+		    $html .= '			<button type="button" class="btn btn-primary btn-sm" onclick="location.href = URL_add_parameter(URL_remove_parameter(location.href, \'p\'), \'bbox\', map.getBounds().getWest()+\',\'+map.getBounds().getSouth()+\',\'+map.getBounds().getEast()+\',\'+map.getBounds().getNorth());return false;">Add</button>'.$newline;
+		    $html .= '		    </div>'.$newline;
+		    $html .= '               </div>'.$newline;
+		    $html .= '	    </form>'.$newline;
+		    $html .= '</div>'.$newline;
+		    $html .= '</div>'.$newline;
+		    $html .= '</div>'.$newline;
+		    $html .= '</div>'.$newline;
+		    //Navigation elements
+		    $html .= '    <div class="row">'.$newline;
+		    $html .= '        <div class="col-md-6">'.$newline;
+		    //generate page navigation
+		    $nav = "";
+		    $nav .= '            <nav>'.$newline;
+		    $nav .= '                <ul class="pagination mb-4">'.$newline;
+		    //get next link from returned object
+		    foreach ($returnObject->links as $link) {
+		        if ($link->rel == 'next') {
+			    $nextItemsHtmlUrl = delTotalFromQuery("f", $link->href)."&f=html";
+		        }
+		        if ($link->rel == 'last') {
+			    $lastItemsHtmlUrl = delTotalFromQuery("f", $link->href)."&f=html";
+		        }
+		    }
+		    //calculate current page number from offset 	
+		    //
+	            $page = floor($offset / $limit);
+		    $nav .= '                    <li class="page-item"><a class="page-link" href="'.delTotalFromQuery(array('offset'), $nextItemsHtmlUrl).'&offset=0">first page</a></li>'.$newline;
+		    if ($offset > 0) {
+	                $nav .= '                    <li class="page-item">';
+		    } else {
+			$nav .= '                    <li class="page-item disabled">';
+		    }
+		    $nav .= '<a class="page-link" href="'.delTotalFromQuery(array('offset'), $nextItemsHtmlUrl).'&offset='.($offset - $limit).'">‹</a></li>'.$newline;
+		    $nav .= '                    <li class="page-item active"><a class="page-link" href="">'.($page + 1).' ('.($numberOfPages).')</a></li>'.$newline;
+		    //only activate next when page < numberOfPages
+		    if ($page < ($numberOfPages - 1)) {
+		        $nav .= '                    <li class="page-item"><a class="page-link" href="'.$nextItemsHtmlUrl.'">›</a></li>'.$newline;
+		    } else {
+			$nav .= '                    <li class="page-item disabled"><a class="page-link" href="'.$nextItemsHtmlUrl.'">›</a></li>'.$newline;
+                    }
+		    //last page
+		    $nav .= '                    <li class="page-item"><a class="page-link" href="'.$lastItemsHtmlUrl.'">last page</a></li>'.$newline;
+		    $nav .= '                </ul>'.$newline;
+		    $nav .= '            </nav>'.$newline;
+		    //end navigation elements
+		    $html .= $nav;
+		    $html .= '           <ul class="list-unstyled">'.$newline;
+		    $objIndex = 0;
+		    foreach($returnObject->features as $feature) {
+		        $html .= '                <li>'.$newline;
+		        $html .= '                    <div  itemscope itemtype="http://schema.org/Place">'.$newline;
+			$html .= '                        <h4 class="mt-3 mb-1"><a href="'.delTotalFromQuery(array('items','offset','limit','bbox'),$_SERVER['REQUEST_URI']).'&item='.$feature->id.'" target="_blank"><span itemprop="name">'.$feature->id.'</span></a></h4><a href=""  onclick="zoomToExtent('.$geojsonBbox[$objIndex]->minx.",".$geojsonBbox[$objIndex]->miny.",".$geojsonBbox[$objIndex]->maxx.",".$geojsonBbox[$objIndex]->maxy.');return false;">zoom to</a>'.$newline;
+        		$html .= '                        <span class="d-none" itemprop="sameAs">https://www.ldproxy.nrw.de/topographie/collections/ax_bergbaubetrieb/items/DENWAT01D000CcF0</span>'.$newline;
+			//foreach attribute
+			foreach($feature->properties as $key=>$value) {
+			    $html .= '                        <div class="row my-1">'.$newline;
+			    $html .= '                            <div class="col-md-6 font-weight-bold text-truncate" title="'.$key.'">'.$key.'</div>'.$newline;
+			    $html .= '                            <div class="col-md-6" >'.string2html($value).'</div>'.$newline;
+			    $html .= '                        </div>'.$newline;
+			}
+			$html .= '                    </div>'.$newline;
+			$html .= '                </li>'.$newline;
+			$objIndex++;
+		    }
+		    $html .= '            </ul>'.$newline;
+		    $html .= $nav;
+	            $html .= '    </div>'.$newline;
+	            $html .= '<!-- functions to handle url parameters -->'.$newline;
+		    $js1 = '    <script>'.$newline;
+		    //https://stackoverflow.com/questions/5997450/append-to-url-and-refresh-page
+		    $js1 .= "	function URL_add_parameter(url, param, value){";
+		    $js1 .= "	    var hash       = {};";
+		    $js1 .= "	    var parser     = document.createElement('a');";
+		    $js1 .= "	    parser.href    = url;";
+		    $js1 .= "	    var parameters = parser.search.split(/\?|&/);";
+		    $js1 .= "	    for(var i=0; i < parameters.length; i++) {";
+		    $js1 .= "	        if(!parameters[i])";
+		    $js1 .= "	            continue;";
+		    $js1 .= "	        var ary      = parameters[i].split('=');";
+		    $js1 .= "	        hash[ary[0]] = ary[1];";
+		    $js1 .= "	    }";
+		    $js1 .= "	    hash[param] = value;";
+		    $js1 .= "	    var list = [];  ";
+		    $js1 .= "	    Object.keys(hash).forEach(function (key) {";
+		    $js1 .= "	        list.push(key + '=' + hash[key]);";
+		    $js1 .= "	    });";
+		    $js1 .= "	    parser.search = '?' + list.join('&');";
+		    $js1 .= "	    return parser.href;";
+		    $js1 .= "	}";
+		    $js1 .= "	function URL_remove_parameter(url, param){";
+		    $js1 .= "	    var hash       = {};";
+		    $js1 .= "	    var parser     = document.createElement('a');";
+		    $js1 .= "	    parser.href    = url;";
+		    $js1 .= "	    var parameters = parser.search.split(/\?|&/);";
+		    $js1 .= "	    for(var i=0; i < parameters.length; i++) {";
+		    $js1 .= "	        if(!parameters[i])";
+		    $js1 .= "	            continue;";
+		    $js1 .= "	        var ary      = parameters[i].split('=');";
+		    $js1 .= "	        hash[ary[0]] = ary[1];";
+		    $js1 .= "	    }";
+		    $js1 .= "	    hash[param] = 0;";
+		    $js1 .= "	    var list = [];  ";
+		    $js1 .= "	    Object.keys(hash).forEach(function (key) {";
+		    $js1 .= "		if (key != param) {";
+		    $js1 .= "	        	list.push(key + '=' + hash[key]);";
+		    $js1 .= "		}";
+		    $js1 .= "	    });";
+		    $js1 .= "	    parser.search = '?' + list.join('&');";
+		    $js1 .= "	    return parser.href;";
+		    $js1 .= "	}";
+		    $js1 .= $newline.'    </script>'.$newline;
+	            $html .= '<!-- functions to initialize map -->'.$newline;
+		    $js2 = '    <script>'.$newline;	
+		    $js2 .= "	var map = L.map('map').setView([50, 7.44], 7);";
 
-$versionsWithPaging = array("2.0.0","2.0.2");
-//list outputFormats for featuretypes
-
-function delTotalFromQuery($paramName, $url) {
-	$query = explode("?", $url);
-	parse_str($query[1], $vars);
-	unset($vars[$paramName]);
-	$urlNew = $query[0]."?".http_build_query($vars);
-	return $urlNew;
+		    $js2 .= "	L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?";
+		    $js2 .= "access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {";
+		    $js2 .= "		maxZoom: 18,";
+		    $js2 .= "		attribution: 'Map data © <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, ' +";
+		    $js2 .= "			'<a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +";
+		    $js2 .= "			'Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>',";
+		    $js2 .= "		id: 'mapbox.light'";
+		    $js2 .= "	}).addTo(map);";
+		    if (!isset($wfsid) || !isset($collection)) {
+			$js2 .= 'document.getElementById("map").style.display = "none"; ';
+			//$js2 .= 'document.getElementById("bboxButtons").style.display = "none"; ';
+		    }
+		    $js2 .= $newline.'    </script>'.$newline;
+		    //add first scripts to html
+		    $html .= $js1;
+                    $html .= '    <div class="col-md-6">'.$newline;
+                    $html .= '        <div id="map"></div>  '.$newline;
+		    $html .= "<!-- add special function that require map after the mapframe div -->".$newline;
+		    $html .= $js2;
+		    $html .= "<!-- add geojson object -->".$newline;
+		    $html .= $geoJsonVariable;
+	            $html .= '<!-- functions to render vectors and extent managing -->'.$newline;
+		    $js3 = "    <script>".$newline;
+		    $js3 .= "	function onEachFeature(feature, layer) {";
+		    $js3 .= "		var popupContent = \"<p><b>\"+ feature.id + \"(\" +";
+		    $js3 .= "				feature.geometry.type + \")</b></p>\";";
+		    $js3 .= "		if (feature.properties && feature.properties.popupContent) {";
+		    $js3 .= "			popupContent += feature.properties.popupContent;";
+		    $js3 .= "		}";
+		    $js3 .= "		for (var key in feature.properties){";
+		    $js3 .= "		    	var value = feature.properties[key];";
+		    $js3 .= "		   	popupContent += \"<br>\"+key+\": \"+value;";
+		    $js3 .= "		}";
+		    $js3 .= "		layer.bindPopup(popupContent);";
+		    $js3 .= "	}";
+		    //zoom to featurecollection
+		    //$e = new mb_exception($minxFC.",".$minyFC.",".$maxxFC.",".$maxyFC);
+		    $js3 .= "		map.fitBounds([";
+		    $js3 .= "   				[".$minxFC.",".$minyFC."],";
+		    $js3 .= "   				[".$maxxFC.",".$maxyFC."]";
+		    $js3 .= "			]);";	
+		    $js3 .= "	L.geoJSON([feature_".$geomType."], {";
+		    $js3 .= "		style: function (feature) {";
+		    $js3 .= "			return feature.properties && feature.properties.style;";
+		    $js3 .= "		},";
+		    $js3 .= "		onEachFeature: onEachFeature,";
+		    $js3 .= "		pointToLayer: function (feature, latlng) {";
+		    $js3 .= "			return L.circleMarker(latlng, {";
+		    $js3 .= "				radius: 8,";
+		    $js3 .= "				fillColor: \"#ff7800\",";
+		    $js3 .= "				color: \"#000\",";
+		    $js3 .= "				weight: 1,";
+		    $js3 .= "				opacity: 1,";
+		    $js3 .= "				fillOpacity: 0.8";
+		    $js3 .= "			});";
+		    $js3 .= "		}";
+		    $js3 .= "	}).addTo(map);";
+		    $js3 .= "	map.on('moveend', function() { ";
+		    $js3 .= "		var bounds = map.getBounds();";
+		    $js3 .= "		var minLng = document.getElementById('minLng');";
+		    $js3 .= "		minLng.value = bounds._southWest.lng;";	
+		    $js3 .= "		var minLat = document.getElementById('minLat');";
+		    $js3 .= "		minLat.value = bounds._southWest.lat;";	
+		    $js3 .= "		var maxLng = document.getElementById('maxLng');";
+		    $js3 .= "		maxLng.value = bounds._northEast.lng;";	
+		    $js3 .= "		var maxLat = document.getElementById('maxLat');";
+		    $js3 .= "		maxLat.value = bounds._northEast.lat;";	
+		    $js3 .= "	});";
+		    $js3 .= "	function zoomToExtent(minx,miny,maxx,maxy) {";
+		    $js3 .= "		map.fitBounds([";
+		    $js3 .= "   				[minx, miny],";
+		    $js3 .= "   				[maxx, maxy]";
+		    $js3 .= "			]);";	
+		    $js3 .= "	}";
+	    	    $js3 .= $newline."    </script>".$newline;
+		    //add geojson object from page
+		    //$html .= $geojsonVariable.$newline;
+		    $html .= $js3;
+		} else {
+		    //item is set !
+		    //$html .= '<div id="feature_table">';
+		    //header("Content-Type: application/gml+xml;version=3.1");
+		    header("Content-Type: ".$outputFormat);
+		    echo $wfs->getFeatureById($collection, $outputFormat, $item, "2.0.0", "EPSG:4326");
+		    die();
+		}
+	    }
+	}
+	//************************************************************************************************************************************	
+	$html .= '    </div>'.$newline;
+	$html .= '</div>'.$newline;
+	$html .= '</div>'.$newline;
+	//************************************************************************************************************************************	
+	//footer
+	$html .= '<footer class="footer bg-light py-4 d-flex flex-column justify-content-around align-items-center">'.$newline;
+	$html .= '    <div class="container d-flex flex-row justify-content-between align-items-center w-100">'.$newline;
+	$html .= '        <span>'.$newline;
+	$html .= '            <span class="text-muted small mr-2">powered by</span>'.$newline;
+	$html .= '            <a class="navbar-brand" href="https://git.osgeo.org/gitea/armin11/GeoPortal.rlp" target="_blank">GeoPortal.rlp</a>'.$newline;
+	$html .= '        </span>'.$newline;
+	$html .= '        <span>'.$newline;
+	if (!isset($collections) || $collection == 'all') {
+            $html .= '            <span><a class="small mr-2" href="https://opendata.geoportal.rlp.de/article/Impressum" target="_blank">Impressum</a></span>'.$newline;
+            $html .= '            <span><a class="small" href="https://opendata.geoportal.rlp.de/article/Datenschutz" target="_blank">Datenschutzerklärung</a></span>'.$newline;
+	}
+	$html .= '        </span>'.$newline;
+	$html .= '    </div>'.$newline;
+	$html .= '</footer>'.$newline;
+	//************************************************************************************************************************************
+	$html .= '</body>'.$newline;
+	$html .= '</html>'.$newline;
+	//
+	header("text/html");
+	echo $html;
+	die();
 }
-
+die();
 ?>

Deleted: trunk/mapbender/http/php/mod_linkedDataProxy_2.php
===================================================================
--- trunk/mapbender/http/php/mod_linkedDataProxy_2.php	2019-08-02 12:11:42 UTC (rev 10194)
+++ trunk/mapbender/http/php/mod_linkedDataProxy_2.php	2019-08-06 11:38:18 UTC (rev 10195)
@@ -1,1147 +0,0 @@
-<?php
-require_once(dirname(__FILE__)."/../../core/globalSettings.php");
-require_once(dirname(__FILE__)."/../classes/class_cache.php");
-require_once(dirname(__FILE__)."/../classes/class_universal_wfs_factory.php");
-require_once(dirname(__FILE__)."/../classes/class_gml_3_factory.php");
-require_once(dirname(__FILE__)."/../classes/class_owsConstraints.php");
-//http://localhost/mapbender/devel_tests/wfsClientTest.php?wfsid=16&ft=vermkv:fluren_rlp&bbox=7.9,50.8,8.0,52
-//initialize some parameter
-//objects per page
-$maxObjectsPerPage = 10;
-//default page
-$page = 0;
-//default format f
-$f = "json";
-//default outputFormat for wfs objects:
-$outputFormat = "text/xml";
-//outputFormat whitelist
-$allowedOutputFormats = array("text/xml; subtype=gml/3.1.1","text/xml; subtype=gml/3.2","text/xml; subtype=gml/2.1.2","text/xml; subtype=gml/3.2.1","SHAPEZIP","application/json; subtype=geojson","text/csv","application/zip");
-//outputFormat for pages - parameter f=...
-$allowedFormats = array("html","xml","json");
-//initial extent for leaflet client
-$minxFC = 48;
-$minyFC = 6;
-$maxxFC = 51;
-$maxyFC = 9;
-function microtime_float() {
-    	list($usec, $sec) = explode(" ", microtime());
-    	return ((float)$usec + (float)$sec);
-}
-//outputFormatter for attribute values - urls, ...
-function string2html($string) {
-	if (filter_var($string, FILTER_VALIDATE_URL)) {
-		return "<a href='".$string."' target='_blank'>".$string."</a>";
-	}
-	return $string;
-}
-//handle http request parameters
-//parse request parameters
-if (isset($_REQUEST["wfsid"]) & $_REQUEST["wfsid"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["wfsid"];
-	$pattern = '/^[\d,]*$/';		
- 	if (!preg_match($pattern,$testMatch)){ 
-		//echo 'id: <b>'.$testMatch.'</b> is not valid.<br/>'; 
-		echo 'Parameter <b>wfsid</b> is not valid (integer or cs integer list).<br/>'; 
-		die(); 		
- 	}
-	$wfsid = $testMatch;
-	$testMatch = NULL;
-}
-if (isset($_REQUEST["fid"]) & $_REQUEST["fid"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["fid"];
-	$pattern = '/^[0-9a-zA-Z\.\-_:]*$/';	
- 	if (!preg_match($pattern,$testMatch)){ 
-		//echo 'id: <b>'.$testMatch.'</b> is not valid.<br/>'; 
-		echo 'Parameter <b>id</b> is not valid (integer or cs integer list).<br/>'; 
-		die(); 		
- 	}
-	$fid = $testMatch;
-	$testMatch = NULL;
-}
-if (isset($_REQUEST["p"]) & $_REQUEST["p"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["p"];
-	$pattern = '/^[\d]*$/';		
- 	if (!preg_match($pattern,$testMatch)){ 
-		//echo 'id: <b>'.$testMatch.'</b> is not valid.<br/>'; 
-		echo 'Parameter <b>p</b> is not valid (integer).<br/>'; 
-		die(); 		
- 	}
-	$page = $testMatch;
-	$testMatch = NULL;
-}
-
-if (isset($_REQUEST["collection"]) & $_REQUEST["collection"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["collection"];
-	$pattern = '/^[0-9a-zA-Z\.\-
-_:]*$/';		
- 	if (!preg_match($pattern,$testMatch)){ 
-		//echo 'id: <b>'.$testMatch.'</b> is not valid.<br/>'; 
-		echo 'Parameter <b>collection</b> is not valid (ogc resource name or id).<br/>'; 
-		die(); 		
- 	}
-	$collection = $testMatch;
-	$testMatch = NULL;
-}
-if (isset($_REQUEST["collections"]) & $_REQUEST["collections"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["collections"];
-	if (!in_array($testMatch, array("all"))){ 
-		echo 'Parameter <b>collections</b> is not valid (maybe all).<br/>'; 
-		die(); 		
- 	}
-	$collections = $testMatch;
-	$testMatch = NULL;
-}
-if (isset($_REQUEST["items"]) & $_REQUEST["items"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["items"];
-	if (!in_array($testMatch, array("all"))){ 
-		echo 'Parameter <b>items</b> is not valid (maybe all).<br/>'; 
-		die(); 		
- 	}
-	$items = $testMatch;
-	$testMatch = NULL;
-}
-if (isset($_REQUEST["outputFormat"]) & $_REQUEST["outputFormat"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["outputFormat"];
-		
- 	if (!in_array($testMatch, $allowedOutputFormats)){ 
-		echo 'Parameter <b>outputFormat</b> is not valid - must be one of: '.implode(',', $allowedOutputFormats).'<br/>'; 
-		die(); 		
- 	}
-	$outputFormat = $testMatch;
-	$testMatch = NULL;
-}
-if (isset($_REQUEST["f"]) & $_REQUEST["f"] != "") {
-	//validate to csv integer list
-	$testMatch = $_REQUEST["f"];	
- 	if (!in_array($testMatch, $allowedFormats)){ 
-		echo 'Parameter <b>f</b> is not valid - must be one of: '.implode(',', $allowedFormats).'<br/>'; 
-		die(); 		
- 	}
-	$f = $testMatch;
-	$testMatch = NULL;
-}
-if (isset($_REQUEST["bbox"]) & $_REQUEST["bbox"] != "") {
-	//validate to float/integer
-	$testMatch = $_REQUEST["bbox"];
-	//$pattern = '/^[-\d,]*$/';
-	$pattern = '/^[-+]?([0-9]*\.[0-9]+|[0-9]+)*$/';
-	$testMatchArray = explode(',',$testMatch);
- 	if (count($testMatchArray) != 4) {
-		echo 'Parameter <b>bbox</b> has a wrong amount of entries.<br/>';
-		die();
-	}
-	for($i=0; $i<count($testMatchArray);$i++){
-		if (!preg_match($pattern,$testMatchArray[$i])){
-			echo 'Parameter <b>bbox</b> is not a valid coordinate value.<br/>';
-			die();
- 		}
-	}
-	$bbox = $testMatch;
-	$testMatch = NULL;
-}
-$proxyStartTime = microtime_float();
-//instantiate needed classes 
-$cache = new Cache();
-//generate json return object - after this build up html if wished!!!!****************************************************************
-// returnObject differs for service / collection / item
-$returnObject = new stdClass();
-//************************************************************************************************************************************
-//service list part 
-//************************************************************************************************************************************
-if (!isset($wfsid) || $wfsid == "") {
-    //list all public available wfs which are classified as opendata!
-    $returnObject->service = array();
-    //$sql = "SELECT * FROM (SELECT wfs_id, wfs_version, wfs_abstract, wfs_title, wfs_owsproxy, fkey_termsofuse_id FROM wfs INNER JOIN wfs_termsofuse ON wfs_id = fkey_wfs_id) AS wfs_tou INNER JOIN termsofuse ON fkey_termsofuse_id = termsofuse_id WHERE isopen = 1";
-    //all wfs - without open filter!
-    $sql = "SELECT wfs_id, wfs_abstract, wfs_version, wfs_title, wfs_owsproxy FROM wfs";
-    $v = array();
-    $t = array();
-    $res = db_prep_query($sql, $v, $t);	
-    $i = 0;	
-    while($row = db_fetch_array($res)){
-        $returnObject->service[$i]->id = $row['wfs_id'];
-        $returnObject->service[$i]->title = $row['wfs_title'];
-        $returnObject->service[$i]->version = $row['wfs_version'];
-        $returnObject->service[$i]->description = $row['wfs_abstract'];
-        //get contraints
-        $constraints = new OwsConstraints();
-        $constraints->languageCode = "de";
-        $constraints->asTable = true;
-        $constraints->id = $returnObject->service[$i]->id;
-        $constraints->type = "wfs";
-        $constraints->returnDirect = false;
-        //$returnObject->service[$i]->tou = json_encode($constraints->getDisclaimer());//TODO encoding problems occur!
-        $i++;
-    } 
-    if ($i == 0) {
-        $returnObject->success = false;
-        $returnObject->message = "No services found in registry";
-    } else {
-        $returnObject->success = true;
-    	$returnObject->message = "Services found in registry!";
-    }
-} else {
-    //************************************************************************************************************************************
-    //service part 
-    //************************************************************************************************************************************
-    //try to instantiate wfs object
-    $myWfsFactory = new UniversalWfsFactory();
-    $wfs = $myWfsFactory->createFromDb($wfsid);
-    if ($wfs == null) {
-	$returnObject->success = false;
-    	$returnObject->message = "Wfs object could not be created from db!";
-    } else {
-	//create service part if no collection is requested		
-	if (!isset($collection) || $collection == "" || $collections == "all") {
-            //************************************************************************************************************************************
-            //service only part 
-            //************************************************************************************************************************************
-	    //add from rlp!
-	    $returnObject->id = $wfsid;
-            $returnObject->title = $wfs->title;
-	    $returnObject->description = $wfs->summary;
-	    //
-	    $returnObject->links = array();
-	    $returnObject->crs = array();
-	    $returnObject->collections = array();
-	    $returnObject->links[0]->rel = "self";
-	    $returnObject->links[0]->type = "application/json";
-	    $returnObject->links[0]->title = "this document";
-	    $returnObject->links[0]->href = $_SERVER['REQUEST_URI']."&f=json";
-	    $returnObject->links[1]->rel = "alternate";
-	    $returnObject->links[1]->type = "text/html";
-	    $returnObject->links[1]->title = "this document as HTML";
-	    $returnObject->links[1]->href = $_SERVER['REQUEST_URI']."&f=html";
-	    //TODO service api
-	    //TODO conformance
-	    //TODO data
-	    $returnObject->links[2]->rel = "data";
-	    $returnObject->links[2]->type = "application/json";
-	    $returnObject->links[2]->title = "Metadata about the feature collections";
-	    $returnObject->links[2]->href = $_SERVER['REQUEST_URI']."?wfsid=".$wfsid."&collections=all&f=json";
-	    //available crs? - howto get from capabilities
-	    
-            //************************************************************************************************************************************
-	    //collection / featuretype list
-            //************************************************************************************************************************************
-	    $collectionArray = array();
-	    $collectionCount = 0;				
-	    foreach ($wfs->featureTypeArray as $featureType) {
-                $returnObject->collections[$collectionCount]->name = $featureType->name;
-		$returnObject->collections[$collectionCount]->title = $featureType->title;
-		$returnObject->collections[$collectionCount]->description = $featureType->description;
-		$returnObject->collections[$collectionCount]->extent->spatial = array();
-		$returnObject->collections[$collectionCount]->links[0]->rel = "item";
-		$returnObject->collections[$collectionCount]->links[0]->type = "application/json";
-                $returnObject->collections[$collectionCount]->links[0]->title = $featureType->title." as GeoJSON";
-		$returnObject->collections[$collectionCount]->links[0]->href = $_SERVER['REQUEST_URI']."?wfsid=".$wfsid."&collection=".$featureType->name."&items=all&f=json";
-		//one item entry for each format!
-		//self
-		$returnObject->collections[$collectionCount]->links[1]->rel = "self";
-		$returnObject->collections[$collectionCount]->links[1]->type = "application/json";
-                $returnObject->collections[$collectionCount]->links[1]->title = "Information about the ".$featureType->title." data";
-		$returnObject->collections[$collectionCount]->links[1]->href = $_SERVER['REQUEST_URI']."?wfsid=".$wfsid."&collection=".$featureType->name."&f=json";
-		//alternate
-		//TODO
-		$returnObject->collections[$collectionCount]->extent->crs = array();
-		$collectionCount++;
-            }
-	} else {
-	    //special collection selected
-	    //is collection one of the featuretypes of this wfs?
-	    //************************************************************************************************************************************
-	    //collection part 
-	    //************************************************************************************************************************************
-	    //test if collection is available in service
-            $ftNameInWfs = false;
-	    foreach ($wfs->featureTypeArray as $featureType) {
-		if ($featureType->name == $collection) {
-		    $ftNameInWfs = true;
-		    $ftTitle = $featureType->title;
-		    $ftName = $featureType->name;
-		    $ftDbId = $featureType->id;
-		    //output formats
-		    $ftOutputFormats = implode(',', array_unique($featureType->featuretypeOutputFormatArray));
-		    //get other relevant ft information
-		    break;
-		} 
-	    }
-	    if ($ftNameInWfs) {
-	        if (!isset($item) || $item == "") {
-		    $myFeatureType = $wfs->findFeatureTypeByName($ftName);			
-		    $geomColumnName = $wfs->findGeomColumnNameByFeaturetypeId($myFeatureType->id);
-		    //generate description of collection in json
-		    $returnObject->name = $myFeatureType->name;
-		    $returnObject->title = $myFeatureType->title;
-		    $returnObject->description = $myFeatureType->abstract;
-		    $returnObject->extent->spatial = array();
-		    $returnObject->extent->temporal = array();
-		    $returnObject->links =array();
-		    $returnObject->links[0]->rel = "item";
-		    $returnObject->links[0]->type = "application/geo+json";
- 		    $returnObject->links[0]->title = $myFeatureType->title." as GeoJSON";
-                    $returnObject->links[0]->href = $_SERVER['REQUEST_URI']."?wfsid=".$wfsid."&collection=".$featureType->name."&items=all&f=json";
-		    //TODO: items in other formats, self, alternate
-		    if ($items == "all") { //show items in list!
-			//reinitialize object!
-			$returnObject = new stdClass();
-			$returnObject->type = "FeatureCollection";
-			$returnObject->links = array();
-			$returnObject->links[0]->rel = "self";
-			$returnObject->links[0]->type = "application/geo+json";			
-			$returnObject->links[0]->title = "this document";
-			$returnObject->links[0]->href = $_SERVER['REQUEST_URI'];
-			//TODO  alternate
-		        //check for given spatialFilter (bbox)
-		        if (isset($bbox) && $bbox != '') {
-		            $filter = $wfs->bbox2spatialFilter($bbox, $geomColumnName, $srs="EPSG:4326", $version='2.0.0');
-		        } else { 
-		            $filter = null;
-		        }
-		        //write number of features to ram cache:
-		        if ($cache->isActive) {
-		            if ($cache->cachedVariableExists(md5("count_".$wfsid."_".$collection."_".(string)$filter)) == false) {
-		                $numberOfObjects = $wfs->countFeatures($collection, $filter);
-		                $cache->cachedVariableAdd(md5("count_".$wfsid."_".$collection."_".(string)$filter), $numberOfObjects);
-		            } else {
-//$e = new mb_exception("read count from cache!");
-		                $numberOfObjects = $cache->cachedVariableFetch(md5("count_".$wfsid."_".$collection."_".(string)$filter));
-		            }
-		            //$e = new mb_notice("http/classes/class_crs.php - store crs info to cache!");
-		            //return true;
-		        } else {
-		            $numberOfObjects = $wfs->countFeatures($collection, $filter);
-		        }
-			//$e = new mb_exception("number of objects: ".$numberOfObjects);
-		        //request first object and metadata
-		        //count objects
-		        //TODO - create json
-		        //$html .= "wfs max features: ".$wfs->wfs_max_features."<br>";
-		        //$html .=  $ftTitle." (".$numberOfObjects.") - id: " .$ftDbId. " - output formats: ".$ftOutputFormats."<br>";
-		        //get first page
-		        //calculate pages
-		        $numberOfPages = ceil($numberOfObjects / $maxObjectsPerPage);
-		        //decide which page should be requested
-		        //$page = 0;
-		        //calculate offset for requested page
-		        if ($page >= $numberOfPages) {
-			    $returnObject->success = false;
-    			    $returnObject->message = "Requested page exeeds number of max pages!";
-			    if ($f == "json") {
-			        header("application/json");
-			        echo json_encode($returnObject);
-			    }	
-		            die();
-		        } else {
-		            $startIndex = $page * $maxObjectsPerPage;
-		        }
-			//next page
-			$returnObject->links[1]->rel = "next";
-			$returnObject->links[1]->type = "application/geo+json";			
-			$returnObject->links[1]->title = "next page";
-			$returnObject->links[1]->href = $_SERVER['REQUEST_URI']."&p=".($page + 1);
-		        //$html .= '</div>';
-		        //get more info for featuretype
-//$e = new mb_exception("bbox: ".$bbox);
-//$e = new mb_exception("filter: ".$filter);
-		        //force version to be 2.0.0!!!!! - hope the server will support it
-		        $features = $wfs->getFeaturePaging($ftName, $filter, "EPSG:4326", null, null, $maxObjectsPerPage, $startIndex, "2.0.0");
-		        //transform to geojson to allow rendering !
-		        $gml3Class = new Gml_3_Factory();
-		        //create featuretype object
-		        //TODO
-//$e = new mb_exception("geom column type: ".$geomColumnName);	
-		        $gml3Object = $gml3Class->createFromXml($features, null, $wfs, $myFeatureType, $geomColumnName);
-//$e = new mb_exception("geojson from mb class: ".json_encode($gml3Object));
-		        $geojsonList = new stdClass();
-		        $geojsonList->type = "FeatureCollection";
-		        $geojsonList->features = array();
-		        $geojsonBbox = array();
-		        $geojsonIndex = 0;
-		        $minxFC = 90;
-		        $minyFC = 180;
-		        $maxxFC = -90;
-		        $maxyFC = -180;
-		        //TODO write javascript object if to var if html is requested
-		        //$html .= "<script>";
-		        foreach($gml3Object->featureCollection->featureArray as $mbFeature) {
-//$e = new mb_exception("geojson from mb feature exporthandler: ".$mbFeature->toGeoJSON());
-		            //bbox
-		            $geojsonBbox[$geojsonIndex]->mbBbox = $mbFeature->getBbox();
-		            //transform to simple bbox object for leaflet
-		            $bbox_new = explode(' ',str_replace(']','',str_replace('[','',$geojsonBbox[$geojsonIndex]->mbBbox)));
-		            $bbox_new = explode('|',str_replace(')','',str_replace('(','',str_replace(')(','|',$bbox_new[0]))));
-		            $bbox_min = explode(',',$bbox_new[0]);
-		            $bbox_max = explode(',',$bbox_new[1]);
-		            $geojsonBbox[$geojsonIndex]->minx = $bbox_min[0];
-		            $geojsonBbox[$geojsonIndex]->miny = $bbox_min[1];
-		            $geojsonBbox[$geojsonIndex]->maxx = $bbox_max[0];
-		            $geojsonBbox[$geojsonIndex]->maxy = $bbox_max[1];
-		            if ($minxFC > $geojsonBbox[$geojsonIndex]->minx) {
-		                $minxFC = $geojsonBbox[$geojsonIndex]->minx;
-		            }
-		            if ($minyFC > $geojsonBbox[$geojsonIndex]->miny) {
-		                $minyFC = $geojsonBbox[$geojsonIndex]->miny;
-		            }
-		            if ($maxxFC < $geojsonBbox[$geojsonIndex]->maxx) {
-		                $maxxFC = $geojsonBbox[$geojsonIndex]->maxx;
-		            }
-		            if ($maxyFC < $geojsonBbox[$geojsonIndex]->maxy){
-		                $maxyFC = $geojsonBbox[$geojsonIndex]->maxy;
-		            }
-		            //get geomtype
-		            $geomType = json_decode($mbFeature->toGeoJSON())->geometry->type;
-		            $geojsonList->features[] = json_decode($mbFeature->toGeoJSON());
-		            //$html .= "var feature_".$geomType."=".json_encode($geojsonList->features).";";
-		            $geojsonIndex++;
-		        }
-			$usedProxyTime = microtime_float() - $proxyStartTime;
-			$returnObject->numberMatched = $numberOfObjects;
-			$returnObject->numberReturned = $geojsonIndex;
-			$date = new DateTime();
-			$returnObject->timeStamp = date('Y-m-d\TH:i:s.Z\Z', $date->getTimestamp());
-			$returnObject->genTime = $usedProxyTime;
-			$returnObject->features = $geojsonList->features;
-			
-			
-		        //TODO write javascript object if to var if html is requested
-		        //$html .= "var feature_".$geomType."=".json_encode($geojsonList).";";
-		        //$html .= "</script>";
-		        //get number of features returned:
-		        //parse hits
-		        //$e = new mb_exception($features);
-		        try {
-		            $featureCollectionObject =  new SimpleXMLElement($features);
-		            if ($featureCollectionObject == false) {
-		                throw new Exception('Cannot parse WFS features request!');
-		            }
-		        }
-		        catch (Exception $e) {
-		            $e = new mb_exception($e->getMessage());
-		        }
-		        //TODO: hardcode wfs 2.0.0!
-		        switch ("2.0.0") {
-		            case "2.0.0":
-		                $hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberReturned');
-			        break;
-		            case "2.0.2":
-			        $hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberReturned');
-			        break;
-		            /*case "1.1.0":
-			        $hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberOfFeatures');
-			        break;*/
-		        }
-		    }
-		    //TODO - print to json
-		    //$html .= (integer)$hits[0]." results found for page ".$page."<br>";
-		    //$html .= "<br>";
-		} else {	            
-		    //************************************************************************************************************************************
-	            //item part 
-	            //************************************************************************************************************************************
-		}	
-	    } else {
-		$returnObject->success = false;
-    	        $returnObject->message = "Collection/Featuretype not available in service!";
-            }
-	}
-    }
-}
-
-//************************************************************************************************************************************
-//item part 
-//************************************************************************************************************************************
-
-
-switch ($f) {
-    case "json":
-	header("application/json");
-	echo json_encode($returnObject);
-	break;
-    case "html":
-	$newline = "\n";
-	//define header and navigation bar
-	$html = '';
-	$html .= '<!DOCTYPE html>'.$newline;
-	$html .= '<html>'.$newline;
-	$html .= '<head>'.$newline;
-	$html .= '<title>Mapbender WFS OpenLinkedData Proxy</title>'.$newline;
-	$html .= '<meta http-equiv="X-UA-Compatible" content="IE=edge">'.$newline;
-	$html .= '<meta charset="utf-8" />'.$newline;
-	$html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">'.$newline;	
-	//$html .= '<link rel="shortcut icon" type="image/x-icon" href="" />';
-	//leaflet css
-	$html .= '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>'.$newline;
-	//leaflet js
-	$html .= '<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" crossorigin=""></script>'.$newline;
-	//bootstrap
-	$html .= '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">'.$newline;
-    	$html .= '<link rel="stylesheet" href="../css/ldproxy_ia.css"/>'.$newline;
-	//own styles - mapviewer ...
-	$html .= '<style>
-	#map {
-		width: 600px;
-		height: 400px;
-	}
-</style>'.$newline;
-	//************************************************************************************************************************************
-	$html .= '<body>'.$newline;
-	//************************************************************************************************************************************
-	//navbar
-	$html .= '<nav class="navbar navbar-light bg-light navbar-expand-sm">'.$newline;
-	$html .= '<div class="container">'.$newline;
-	$html .= '<div id="navbar" class="navbar-collapse collapse d-flex justify-content-between align-items-center">'.$newline;
-	$html .= '<ol class="breadcrumb bg-light my-0 pl-0">'.$newline;
-	//
-	if (!isset($wfsid)){ // && (!isset($collection) || ($collections != 'all'))) {
-	    $html .= '<li class="breadcrumb-item active">Datasets</li>'.$newline;
-	} else {
-	    if (!isset($collection) || $collections == 'all') {
-	        $html .= '<li class="breadcrumb-item"><a href="'.$_SERVER['REQUEST_URI'].'">Datasets</a></li>'.$newline; //TODO - use base uri
-                $html .= '<li class="breadcrumb-item active">'.$returnObject->title.'</li>'.$newline;
-	    }
-	}
-	//
-	$html .= '</ol>'.$newline;
-	$html .= '<ul class="list-separated m-0 p-0 text-muted">'.$newline;
-	$html .= '</ul>'.$newline;        
-	$html .= '</div>'.$newline;
-	$html .= '<!--button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">'.$newline;
-	$html .= '<span class="navbar-toggler-icon"></span>'.$newline;
-	$html .= '</button-->'.$newline;
-	$html .= '</div>'.$newline;
-	$html .= '</nav>'.$newline;
-	//
-	//logic
-	if (!isset($wfsid)) {
-	//header for proxy
-	    $html .= "";
-	    $html .= '<div class="container py-4">'.$newline;
-	    $html .= '    <div itemscope itemtype="http://schema.org/DataCatalog">'.$newline;
-	    $html .= '        <h1 itemprop="name">Geodaten des Landes Rheinland-Pfalz</h1>'.$newline;
-	    $html .= '        <p itemprop="description">Unter einer offenen Lizenz publizierte Geodaten des Landes Rheinland-Pfalz als LinkedOpenData.</p>'.$newline;
-	    $html .= '        <p itemprop="url" class="d-none">https://www.opendata.geoportal.rlp.de/</p>'.$newline;
-	    $html .= '        <br/>'.$newline;
-	    $html .= '        <br/>'.$newline;
-	    $html .= '        <br/>'.$newline;
-    	    $html .= '        <ul class="list-unstyled space-after">'.$newline;
-	    foreach ($returnObject->service as $service) {
-	        $html .= '            <li itemprop="dataset" itemscope itemtype="http://schema.org/Dataset">'.$newline;
-                $html .= '                <h2>'.$newline;
-                $html .= '                    <a itemprop="url" href="?wfsid='.$service->id.'">'.$newline;
-                $html .= '                        <span itemprop="name">'.$service->title.'</span>'.$newline;
-                $html .= '                    </a>'.$newline;
-                $html .= '                </h2>'.$newline;
-                $html .= '                <span itemprop="description">'.$service->description.'</span>'.$newline;
-                $html .= '                <span itemprop="sameAs" class="d-none">/ad-links</span>'.$newline;
-                $html .= '            </li>'.$newline;						
-	    }
-	    $html .= '        </ul>'.$newline;
-	} else {
-	    if (!isset($collection) || $collections == 'all') {
-		//show service and collection info	    
-		$html .= "";
-		$html .= '<div class="container py-4">'.$newline;
-                $html .= '    <div itemscope itemtype="http://schema.org/Dataset">'.$newline;
-        	$html .= '        <h1 itemprop="name">'.$returnObject->title.'</h1>'.$newline;
-       	 	$html .= '        <span itemprop="description">'.$returnObject->description.'</span>'.$newline;
-        	$html .= '        <p itemprop="url" class="d-none">'.$_SERVER['REQUEST_URI'].'</p>'.$newline;//TODO canonical url
-            	$html .= '        <div itemprop="includedInDataCatalog" itemscope itemtype="http://schema.org/Datacatalog" class="d-none">'.$newline;
-                $html .= '            <div itemprop="url">https://www.ldproxy.nrw.de/'.$_SERVER['REQUEST_URI'].'</div>'.$newline;//TODO canonical url
-            	$html .= '        </div>'.$newline;
-		$html .= '    </div>'.$newline;
-		$html .= '</div>'.$newline;
-	    }
-	}
-	//************************************************************************************************************************************	
-	$html .= '    </div>'.$newline;
-	$html .= '</div>'.$newline;
-	//footer
-
-	$html .= '<footer class="footer bg-light py-4 d-flex flex-column justify-content-around align-items-center">'.$newline;
-	$html .= '    <div class="container d-flex flex-row justify-content-between align-items-center w-100">'.$newline;
-	$html .= '        <span>'.$newline;
-	$html .= '            <span class="text-muted small mr-2">powered by</span>'.$newline;
-	$html .= '            <a class="navbar-brand" href="https://git.osgeo.org/gitea/armin11/GeoPortal.rlp" target="_blank">GeoPortal.rlp</a>'.$newline;
-	$html .= '        </span>'.$newline;
-	$html .= '        <span>'.$newline;
-	$html .= '        </span>'.$newline;
-	$html .= '    </div>'.$newline;
-	$html .= '</footer>'.$newline;
-	$html .= '</body>'.$newline;
-	$html .= '</html>'.$newline;
-	//
-	header("text/html");
-	echo $html;
-	die();
-}
-die();
-
-//************************************************************************************************************************************
-
-
-
-
-//do the html things
-$html = '';
-$html .= '<!DOCTYPE html>';
-$html .= '<html>';
-$html .= '<head>';
-$html .= '<title>Mapbender WFS OpenLinkedData Proxy</title>';
-$html .= '<meta http-equiv="X-UA-Compatible" content="IE=edge">';
-$html .= '<meta charset="utf-8" />';
-$html .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">';	
-//$html .= '<link rel="shortcut icon" type="image/x-icon" href="" />';
-$html .= '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>';
-$html .= '<script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js" integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" crossorigin=""></script>';
-//bootstrap
-$html .= '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">';
-//own styles - mapviewer ...
-$html .= '<style>
-		html, body {
-			height: 100%;
-			margin: 0;
-		}
-		#map {
-			width: 600px;
-			height: 400px;
-		}
-	</style>';	
-$html .= '</head>';	
-$html .= '<body>';
-//navigation bar
-$html .= '<nav class="navbar navbar-light bg-light navbar-expand-sm">   ';
-$html .= '    <div class="container">';
-$html .= '        <div id="navbar" class="navbar-collapse collapse d-flex justify-content-between align-items-center">';
-$html .= '            <ol class="breadcrumb bg-light my-0 pl-0">';
-//if (!isset($wfsid)) {
-	$html .= '                            <li class="breadcrumb-item active">Datasets</li>';
-//} else {
-	//$html .= '                            <li class="breadcrumb-item active">'..'</li>';			
-//}
-//$html .= '                            <li class="breadcrumb-item active">Datasets</li>';
-$html .= '            </ol>';
-$html .= '            <ul class="list-separated m-0 p-0 text-muted">';
-$html .= '            </ul>    ';        
-$html .= '        </div>';
-
-$html .= '                    <!--button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">';
-$html .= '                <span class="navbar-toggler-icon"></span>';
-$html .= '            </button-->';
-
-$html .= '    </div>';
-$html .= '</nav>';
-$html .= '<script>';
-//https://stackoverflow.com/questions/5997450/append-to-url-and-refresh-page
-
-$html .= "	function URL_add_parameter(url, param, value){";
-$html .= "	    var hash       = {};";
-$html .= "	    var parser     = document.createElement('a');";
-
-$html .= "	    parser.href    = url;";
-
-$html .= "	    var parameters = parser.search.split(/\?|&/);";
-
-$html .= "	    for(var i=0; i < parameters.length; i++) {";
-$html .= "	        if(!parameters[i])";
-$html .= "	            continue;";
-
-$html .= "	        var ary      = parameters[i].split('=');";
-$html .= "	        hash[ary[0]] = ary[1];";
-$html .= "	    }";
-
-$html .= "	    hash[param] = value;";
-
-$html .= "	    var list = [];  ";
-$html .= "	    Object.keys(hash).forEach(function (key) {";
-$html .= "	        list.push(key + '=' + hash[key]);";
-$html .= "	    });";
-
-$html .= "	    parser.search = '?' + list.join('&');";
-$html .= "	    return parser.href;";
-$html .= "	}";
-
-$html .= "	function URL_remove_parameter(url, param){";
-$html .= "	    var hash       = {};";
-$html .= "	    var parser     = document.createElement('a');";
-
-$html .= "	    parser.href    = url;";
-
-$html .= "	    var parameters = parser.search.split(/\?|&/);";
-
-$html .= "	    for(var i=0; i < parameters.length; i++) {";
-$html .= "	        if(!parameters[i])";
-$html .= "	            continue;";
-
-$html .= "	        var ary      = parameters[i].split('=');";
-$html .= "	        hash[ary[0]] = ary[1];";
-$html .= "	    }";
-
-$html .= "	    hash[param] = 0;";
-
-$html .= "	    var list = [];  ";
-$html .= "	    Object.keys(hash).forEach(function (key) {";
-$html .= "		if (key != param) {";
-$html .= "	        	list.push(key + '=' + hash[key]);";
-$html .= "		}";
-$html .= "	    });";
-
-$html .= "	    parser.search = '?' + list.join('&');";
-$html .= "	    return parser.href;";
-$html .= "	}";
-
-
-$html .= '</script>';
-//only show map if wfsid is selected
-$html .= "<div id='map'></div>";
-$html .= "<div id='bboxButtons'><input type='button' onclick='location.href = URL_add_parameter(URL_remove_parameter(location.href, \"p\"), \"bbox\", map.getBounds().getWest()+\",\"+map.getBounds().getSouth()+\",\"+map.getBounds().getEast()+\",\"+map.getBounds().getNorth());return false;' value='Set Bbox Filter'><input type='button' onclick='location.href = URL_remove_parameter(URL_remove_parameter(location.href, \"bbox\"), \"p\");return false;' value='Delete Bbox Filter'><input type='button' onclick='location.href = location.href.split(\"?\")[0]';return false;' value='WFS List'></div>";
-
-//div elements
-/*$html .= '<div id="wfs_info"></div>';
-$html .= '<div id="wfs_table"></div>';
-$html .= '<div id="map"></div>';
-$html .= '<div id="featuretype_table"></div>';	
-$html .= '<div id="feature_table"></div>';
-$html .= '<div id="counter"></div>';*/
-//javascripts
-//$html .= '<script src="sample-geojson.js" type="text/javascript"></script>';	
-$html .= '<script>';	
-$html .= "	var map = L.map('map').setView([50, 7.44], 7);";
-
-$html .= "	L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?";
-$html .= "access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {";
-$html .= "		maxZoom: 18,";
-$html .= "		attribution: 'Map data © <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, ' +";
-$html .= "			'<a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>, ' +";
-$html .= "			'Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>',";
-$html .= "		id: 'mapbox.light'";
-$html .= "	}).addTo(map);";
-if (!isset($wfsid) || !isset($ft)) {
-	$html .= 'document.getElementById("map").style.display = "none"; ';
-	$html .= 'document.getElementById("bboxButtons").style.display = "none"; ';
-}
-$html .= '</script>';
-
-$htmlFooter = '</body></html>';
-$htmlFooter = '<footer class="footer bg-light py-4 d-flex flex-column justify-content-around align-items-center">';
-$htmlFooter .= '<div class="container d-flex flex-row justify-content-between align-items-center w-100">';
-$htmlFooter .= '<span><span class="text-muted small mr-2">powered by</span><a class="navbar-brand" href="https://git.osgeo.org/gitea/armin11/GeoPortal.rlp" target="_blank">GeoPortal.rlp</a></span>';
-$htmlFooter .= '<span>';
-$htmlFooter .= '</span>';
-$htmlFooter .= '</div>';
-$htmlFooter .= '</footer>';
-
-//php logic	
-//generate list of allowed wfs_ids!
-//TODO
-/*
-*/
-	if (!isset($wfsid) || $wfsid == "") {
-		//list all public available wfs which are classified as opendata!
-		$openWfs = new stdClass();
-		$openWfs->list = array();
-		$sql = "SELECT * FROM (SELECT wfs_id, wfs_version, wfs_abstract, wfs_title, wfs_owsproxy, fkey_termsofuse_id FROM wfs INNER JOIN wfs_termsofuse ON wfs_id = fkey_wfs_id) AS wfs_tou INNER JOIN termsofuse ON fkey_termsofuse_id = termsofuse_id WHERE isopen = 1";
-		//all wfs - without open filter!
-		//$sql = "SELECT wfs_id, wfs_abstract, wfs_version, wfs_title, wfs_owsproxy FROM wfs";
-		$v = array();
-		$t = array();
-		$res = db_prep_query($sql, $v, $t);	
-		$i = 0;	
-		while($row = db_fetch_array($res)){
-			$openWfs->list[$i]->id = $row['wfs_id'];
-			$openWfs->list[$i]->title = $row['wfs_title'];
-			$openWfs->list[$i]->version = $row['wfs_version'];
-			$openWfs->list[$i]->description = $row['wfs_abstract'];
-			$i++;
-		}
-		$html .= '<div id="wfs_info">';	
-		$html .= '<ul class="list-unstyled space-after">';
-		//$html .= "Available WFS:";			
-		//$html .= "<br>";
-		foreach ($openWfs->list as $openWfs) {
-			$html .= '<li itemscope itemtype="http://schema.org/Dataset">';
-			$html .= '<h1>';
-			$html .= '<a itemprop="url" href="'.$_SERVER['REQUEST_URI']."?wfsid=".$openWfs->id.'">';
-			$html .= '<span itemprop="name">'.$openWfs->title.' (WFS '.$openWfs->version.')</span>';
-			$html .= '</a>';
-			$html .= '</h1>';
-			$html .= '<span itemprop="description">'.$openWfs->description.'</span>';
-			$html .= '</li>';	
-			
-		}
-		$html .= '</ul>';
-		$html .= $htmlFooter.'</body></html>';
-		echo $html;
-		die();
-	} else {
-		//try to instantiate wfs object
-		$myWfsFactory = new UniversalWfsFactory();
-		$wfs = $myWfsFactory->createFromDb($wfsid);
-
-		if ($wfs == null) {
-			$html .=  "wfs could not be instantiated!";
-			$html .= '</div>';
-		} else {
-			$html .= '</div>';
-			if (isset($ft) && $ft != "") {
-				if (isset($fid) && $fid != "") {		
-					//$html .= '<div id="feature_table">';
-					//header("Content-Type: application/gml+xml;version=3.1");
-					header("Content-Type: ".$outputFormat);
-					
-					echo $wfs->getFeatureById($ft, $outputFormat, $fid, "2.0.0", "EPSG:4326");
-					//$html .= '</div>';
-					//$html .= '</body>';
-					//$html .= '</html>';
-					die();
-				} else {		
-
-					$html .= '<div id="featuretype_info">';
-					$html .= "wfs successfully instantiated! ft is set!";
-					$html .= "<br>";
-					$html .= "wfs title: ".$wfs->title." - version: ".$wfs->getVersion();
-					$html .= "<br>";
-					//$ftNameArray = array();
-					$ftNameInWfs = false;
-					foreach ($wfs->featureTypeArray as $featureType) {
-						//$ftNameArray[] = $featureType->name;
-						if ($featureType->name == $ft) {
-							$ftNameInWfs = true;
-							$ftTitle = $featureType->title;
-							$ftName = $featureType->name;
-							$ftDbId = $featureType->id;
-		//output formats
-							$ftOutputFormats = implode(',', array_unique($featureType->featuretypeOutputFormatArray));
-							//get other relevant ft information
-							break;
-						} 
-					}
-					if ($ftNameInWfs) {
-						//TODO: cache counted features to allow faster access !!!!!
-					
-						$myFeatureType = $wfs->findFeatureTypeByName($ftName);
-						//get geom column name
-//TODO						
-						$geomColumnName = $wfs->findGeomColumnNameByFeaturetypeId($myFeatureType->id);
-
-//get bbox filter if defined!
-						//check for given spatialFilter (bbox)
-						if (isset($bbox) && $bbox != '') {
-							$filter = $wfs->bbox2spatialFilter($bbox, $geomColumnName, $srs="EPSG:4326", $version='2.0.0');
-							//$page = 0;
-						} else { 
-							$filter = null;
-						}
-						//$numberOfObjects = $wfs->countFeatures($ft);
-						//write to cache:
-						if ($cache->isActive) {
-							if ($cache->cachedVariableExists(md5("count_".$wfsid."_".$ft."_".(string)$filter)) == false) {
-								$numberOfObjects = $wfs->countFeatures($ft, $filter);
-								$cache->cachedVariableAdd(md5("count_".$wfsid."_".$ft."_".(string)$filter), $numberOfObjects);
-				
-							} else {
-//$e = new mb_exception("read count from cache!");
-								$numberOfObjects = $cache->cachedVariableFetch(md5("count_".$wfsid."_".$ft."_".(string)$filter));
-							}
-							//$e = new mb_notice("http/classes/class_crs.php - store crs info to cache!");
-							//return true;
-						} else {
-							$numberOfObjects = $wfs->countFeatures($ft, $filter);
-			
-						}
-$e = new mb_exception("number of objects: ".$numberOfObjects);
-						//request first object and metadata
-						//count objects
-						$html .= "wfs max features: ".$wfs->wfs_max_features."<br>";
-						$html .=  $ftTitle." (".$numberOfObjects.") - id: " .$ftDbId. " - output formats: ".$ftOutputFormats."<br>";
-						//get first page
-						//calculate pages
-						$numberOfPages = ceil($numberOfObjects / $maxObjectsPerPage);
-						//decide which page should be requested
-						//$page = 0;
-						//calculate offset for requested page
-						if ($page >= $numberOfPages) {
-							echo "requested page exeeds number of max pages!";
-							die();
-						} else {
-							$startIndex = $page * $maxObjectsPerPage;
-						}
-						$html .= '</div>';
-						//get more info for featuretype
-
-//$e = new mb_exception("bbox: ".$bbox);
-
-//$e = new mb_exception("filter: ".$filter);
-						//force version to be 2.0.0!!!!! - hope the server will support it
-						$features = $wfs->getFeaturePaging($ftName, $filter, "EPSG:4326", null, null, $maxObjectsPerPage, $startIndex, "2.0.0");
-						//transform to geojson to allow rendering !
-						$gml3Class = new Gml_3_Factory();
-						//create featuretype object
-//TODO
-
-//$e = new mb_exception("geom column type: ".$geomColumnName);
-						
-						$gml3Object = $gml3Class->createFromXml($features, null, $wfs, $myFeatureType, $geomColumnName);
-//$e = new mb_exception("geojson from mb class: ".json_encode($gml3Object));
-						$geojsonList = new stdClass();
-						$geojsonList->type = "FeatureCollection";
-						$geojsonList->features = array();
-						$geojsonBbox = array();
-						$geojsonIndex = 0;
-						$minxFC = 90;
-						$minyFC = 180;
-						$maxxFC = -90;
-						$maxyFC = -180;
-						$html .= "<script>";
-						foreach($gml3Object->featureCollection->featureArray as $mbFeature) {
-							//$e = new mb_exception("geojson from mb feature exporthandler: ".$mbFeature->toGeoJSON());
-							//bbox
-							$geojsonBbox[$geojsonIndex]->mbBbox = $mbFeature->getBbox();
-							//transform to simple bbox object for leaflet
-							$bbox_new = explode(' ',str_replace(']','',str_replace('[','',$geojsonBbox[$geojsonIndex]->mbBbox)));
-							$bbox_new = explode('|',str_replace(')','',str_replace('(','',str_replace(')(','|',$bbox_new[0]))));
-							$bbox_min = explode(',',$bbox_new[0]);
-							$bbox_max = explode(',',$bbox_new[1]);
-
-							$geojsonBbox[$geojsonIndex]->minx = $bbox_min[0];
-							$geojsonBbox[$geojsonIndex]->miny = $bbox_min[1];
-							$geojsonBbox[$geojsonIndex]->maxx = $bbox_max[0];
-							$geojsonBbox[$geojsonIndex]->maxy = $bbox_max[1];
-							if ($minxFC > $geojsonBbox[$geojsonIndex]->minx) {
-								$minxFC = $geojsonBbox[$geojsonIndex]->minx;
-							}
-							if ($minyFC > $geojsonBbox[$geojsonIndex]->miny) {
-								$minyFC = $geojsonBbox[$geojsonIndex]->miny;
-							}
-							if ($maxxFC < $geojsonBbox[$geojsonIndex]->maxx) {
-								$maxxFC = $geojsonBbox[$geojsonIndex]->maxx;
-							}
-							if ($maxyFC < $geojsonBbox[$geojsonIndex]->maxy){
-								$maxyFC = $geojsonBbox[$geojsonIndex]->maxy;
-							}
-
-							//get geomtype
-							$geomType = json_decode($mbFeature->toGeoJSON())->geometry->type;
-							$geojsonList->features[] = json_decode($mbFeature->toGeoJSON());
-							//$html .= "var feature_".$geomType."=".json_encode($geojsonList->features).";";
-							$geojsonIndex++;
-						}
-						$html .= "var feature_".$geomType."=".json_encode($geojsonList).";";
-						$html .= "</script>";
-						//get number of features returned:
-						//parse hits
-		//$e = new mb_exception($features);
-						try {
-							$featureCollectionObject =  new SimpleXMLElement($features);
-							if ($featureCollectionObject == false) {
-								throw new Exception('Cannot parse WFS features request!');
-							}
-						}
-						catch (Exception $e) {
-				    			$e = new mb_exception($e->getMessage());
-						}
-						//hardcode wfs 2.0.0!
-						switch ("2.0.0") {
-							case "2.0.0":
-								$hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberReturned');
-								break;
-							case "2.0.2":
-								$hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberReturned');
-								break;
-							/*case "1.1.0":
-								$hits = $featureCollectionObject->xpath('/wfs:FeatureCollection/@numberOfFeatures');
-								break;*/
-						}
-						$html .= (integer)$hits[0]." results found for page ".$page."<br>";
-						$html .= "<br>";
-//$e = new mb_exception("ft name: ".$ftName);
-//pagination ****************************************************************************************************************
-						$html .= '<nav id="pagination">';
-    						$html .= '<ul class="pagination mb-4">';
-						//page backward
-						if (($page - 1) >= 0) {
-							 $html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page - 1) ."' target='_self'>". ($page - 1) . "</a><li>";
-						}
-						//page current
-						$html .=  "<li class=\"page-item active\"><a class=\"page-link\" href=\"\">".$page." (".($numberOfPages - 1).")</a><li>";
-						//page forward
-
-						if (($page + 1) < $numberOfPages) {
-							$html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page + 1) ."' target='_self'>". ($page + 1) ."</a></li>";
-						}
-						//depends on the gml version!
-    						$html .= '</ul>';
-						$html .= '</nav>';
-//pagination ****************************************************************************************************************
-						//problem with id: maybe wfs is not configured in the right way!
-						$gmlIds = $featureCollectionObject->xpath('/wfs:FeatureCollection/wfs:member/'.$ftName.'/@gml:id');
-						//$html .= '<div id="feature_table">';
-						$html .= '<ul class="list-unstyled">';
-						$html .= '<li>';
-						$objIndex = 0;
-						foreach ($gmlIds as $gmlId) {
-$html .= '<div  itemscope itemtype="http://schema.org/Place">';
-							//link getfeaturebyid 
-							//echo "gml_id: ".$gmlId."<br>";
-							//echo $gmlId."<br>";
-							//<h4 class="mt-3 mb-1"><a href="https://www.ldproxy.nrw.de/kataster/collections/flurstueck/items/DENW19AL0000geMFFL?f=html&relations=bahnstrecken,gewaesser&resolve=true"><span itemprop="name">Bad Wünnenberg, Wünnenberg, 016 </span></a></h4>
-							//$html .= "<a  href='#' onclick='zoomToExtent(".$geojsonBbox[$objIndex]->minx.",".$geojsonBbox[$objIndex]->miny.",".$geojsonBbox[$objIndex]->maxx.",".$geojsonBbox[$objIndex]->maxy.");return false;'>".$gmlId."</a><br>";
-							//title
-							$html .= "<h4 class=\"mt-3 mb-1\"><a href=\"#\" onclick='zoomToExtent(".$geojsonBbox[$objIndex]->minx.",".$geojsonBbox[$objIndex]->miny.",".$geojsonBbox[$objIndex]->maxx.",".$geojsonBbox[$objIndex]->maxy.");return false;'><span itemprop=\"name\">".$gmlId."</span></a></h4>";
-							//$gmlIds = $featureCollectionObject->xpath('/wfs:FeatureCollection/wfs:member/'.$ftName.'/@gml:id');
-							//$geojsonList->features[$objIndex];
-							foreach(explode(",", $ftOutputFormats) as $outputFormat) {
-								$html .= "<a href='".$_SERVER['REQUEST_URI']."&fid=".$gmlId."&outputFormat=".$outputFormat."' target='_blank'>".$outputFormat."</a><br>";
-							}
-							foreach($geojsonList->features[$objIndex]->properties as $key=>$value) {
-								$html .= '<div class="row my-1">';
-								$html .= '<div class="col-md-6 font-weight-bold text-truncate" title="'.$key.'">'.$key.'</div>';
-								$html .= '<div class="col-md-6" >'.string2html($value).'</div>';
-								//$html .= $key.":".$value."<br>";
-								$html .= '</div>';
-							}
-							$html .= "<br>";
-							$objIndex++;
-$html .= '</div>';
-						}
-						$html .=  "</li>";
-						//$html .= '</div>';
-						$html .= '</ul>';
-//pagination ****************************************************************************************************************
-						$html .= '<nav id="pagination">';
-    						$html .= '<ul class="pagination mb-4">';
-						//page backward
-						if (($page - 1) >= 0) {
-							 $html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page - 1) ."' target='_self'>". ($page - 1) . "</a><li>";
-						}
-						//page current
-						$html .=  "<li class=\"page-item\"><a class=\"page-link\" href=\"\">".$page." (".($numberOfPages - 1).")</a><li>";
-						//page forward
-
-						if (($page + 1) < $numberOfPages) {
-							$html .= "<li class=\"page-item\"><a class=\"page-link\" href='".delTotalFromQuery("p", $_SERVER['REQUEST_URI'])."&p=". ($page + 1) ."' target='_self'>". ($page + 1) ."</a></li>";
-						}
-									//depends on the gml version!
-    						$html .= '</ul>';
-						$html .= '</nav>';
-//pagination ****************************************************************************************************************
-						//$e = new mb_exception($features);
-			
-					} else {
-						$html .=  "ft not in wfs - operation not possible!";
-						//request first object and metadata
-						//count objects
-					}
-				}
-
-			} else {
-				$html .= '<div id="wfs_info">';
-				$html .= "wfs successfully instantiated!";
-				$html .= "<br>";
-				$html .= "wfs title: ".$wfs->title." - version: ".$wfs->getVersion();
-				$html .= "<br>";
-				$ftNameArray = array();					
-				$html .= '</div>';				
-				$html .= '<div id="featuretype_table">';
-				foreach ($wfs->featureTypeArray as $featureType) {
-					//$numberOfObjects = $wfs->countFeatures($featureType->name);
-					$html .= "<a href='".$_SERVER['REQUEST_URI']."&ft=".$featureType->name."' target='_self'>".$featureType->title." (".$featureType->name.")</a><br>";
-					//echo "featuretype: <a href='".$_SERVER['REQUEST_URI']."&ft=".$featureType->name."'".$featureType->name." - objects: ".$numberOfObjects."<br>";
-
-			
-			/*$ft = $wfs->findFeatureTypeByName($featureType->name);
-
-					foreach ($ft->featuretypeOutputFormatArray as $outputFormat) {
-						echo "		format: ".$outputFormat."<br>";
-					}*/
-				}
-				$html .= '</div>';
-			}
-	}
-//add javascript things that have be done after !
-$html .= "<script>";
-$html .= "	function onEachFeature(feature, layer) {";
-$html .= "		var popupContent = \"<p>I started out as a GeoJSON \" +";
-$html .= "				feature.geometry.type + \", but now I'm a Leaflet vector!</p>\";";
-
-$html .= "		if (feature.properties && feature.properties.popupContent) {";
-$html .= "			popupContent += feature.properties.popupContent;";
-$html .= "		}";
-$html .= "		for (var key in feature.properties){";
-$html .= "		    	var value = feature.properties[key];";
-$html .= "		   	popupContent += \"<br>\"+key+\": \"+value;";
-$html .= "		}";
-
-$html .= "		layer.bindPopup(popupContent);";
-$html .= "	}";
-
-
-//zoom to featurecollection
-//$e = new mb_exception($minxFC.",".$minyFC.",".$maxxFC.",".$maxyFC);
-
-$html .= "		map.fitBounds([";
-$html .= "   				[".$minxFC.",".$minyFC."],";
-$html .= "   				[".$maxxFC.",".$maxyFC."]";
-$html .= "			]);";	
-
-$html .= "	L.geoJSON([feature_".$geomType."], {";
-$html .= "		style: function (feature) {";
-$html .= "			return feature.properties && feature.properties.style;";
-$html .= "		},";
-$html .= "		onEachFeature: onEachFeature,";
-$html .= "		pointToLayer: function (feature, latlng) {";
-$html .= "			return L.circleMarker(latlng, {";
-$html .= "				radius: 8,";
-$html .= "				fillColor: \"#ff7800\",";
-$html .= "				color: \"#000\",";
-$html .= "				weight: 1,";
-$html .= "				opacity: 1,";
-$html .= "				fillOpacity: 0.8";
-$html .= "			});";
-$html .= "		}";
-$html .= "	}).addTo(map);";
-
-/*$html .= "	map.on('dragged', function() { ";
-$html .= "	     alert(map.getBounds());";
-$html .= "	});";*/
-
-
-$html .= "	function zoomToExtent(minx,miny,maxx,maxy) {";
-$html .= "		map.fitBounds([";
-$html .= "   				[minx, miny],";
-$html .= "   				[maxx, maxy]";
-$html .= "			]);";	
-$html .= "	}";
-
-/*map.fitBounds([
-    [40.712, -74.227],
-    [40.774, -74.125]
-]);*/
-
-
-
-
-$html .= "</script>";
-$html .= '</body></html>';
-echo $html;
-}
-
-$versionsWithPaging = array("2.0.0","2.0.2");
-//list outputFormats for featuretypes
-
-function delTotalFromQuery($paramName, $url) {
-	$query = explode("?", $url);
-	parse_str($query[1], $vars);
-	unset($vars[$paramName]);
-	$urlNew = $query[0]."?".http_build_query($vars);
-	return $urlNew;
-}
-
-?>



More information about the Mapbender_commits mailing list