Просмотр исходного кода

fix wfs server: add data and qgis version, rm old wfs

Piotr Labudda 10 лет назад
Родитель
Сommit
428cbd9cf3

+ 6 - 0
SE/se-lib/Api.php

@@ -3,12 +3,17 @@
 class Api {
 
 	private $_apiUser;
+	private $_apiBaseUri;
 	private $_request;
 
 	public function setUser($user) {
 		$this->_apiUser = $user;
 	}
 
+	public function setBaseUri($uri) {
+		$this->_apiBaseUri = $uri;
+	}
+
 	public function execute($url) {
 		$request = $this->parseUrl($url);
 
@@ -21,6 +26,7 @@ class Api {
 		}
 		$apiRouter = new $apiRouterClassName();
 		$apiRouter->setUser($this->_apiUser);
+		$apiRouter->setBaseUri($this->_apiBaseUri);
 		$responseDocument = $apiRouter->execute($request);
 		if (empty($responseDocument)) {
 			throw new HttpException("No result", 404);

+ 14 - 35
SE/se-lib/Api/Wfs.php → SE/se-lib/Api/WfsData.php

@@ -1,40 +1,18 @@
 <?php
 
+Lib::loadClass('ApiRouteBase');
 Lib::loadClass('ApiDataSourceTodo');// TODO: @see Entity/Source/Mysql from feature-schema-install
 Lib::loadClass('Api_WfsException');
-Lib::loadClass('Api_WfsServer');
+Lib::loadClass('Api_WfsDataServer');
 Lib::loadClass('UserAcl');
 
-class Api_Wfs {
+class Api_WfsData extends ApiRouteBase {// TODO: extends Api_WfsBase which extends ApiBase
 
-	private $_apiUser;
-	private $_dataSourceName;
-	private $_tblName;
-	private $_tblSchema;
-
-	public function setUser($user) {
-		$this->_apiUser = $user;
-	}
-
-	private function reqDBG($request, $line) {
-		$reqLog = "[" . date("Y-m-d H:m:s") . "] WFS: ---- {$_SERVER['REQUEST_METHOD']}: {$_SERVER['REQUEST_URI']}";
-		if ($_SERVER['REQUEST_METHOD'] == 'POST') $reqLog .= "\n------------ POST:\n" . file_get_contents("php://input");
-		if (!empty($request)) $reqLog .= "\n------------ request: " . json_encode($request);
-		$reqLog .= "\n------------ END.";
-		$this->DBG($reqLog, $line);
-	}
-
-	private function DBG($reqLog, $line) {
-		$errorLogFile = APP_PATH_ROOT . "/wfs.log";
-		if (!is_writable($errorLogFile)) {
-			$fp = @fopen($errorLogFile, "w");
-			if ($fp === false) {
-				return;
-			}
-			@fclose($fp);
-		}
-		error_log("L.{$line}:{$reqLog}\n", 3, $errorLogFile);
-	}
+	public $_apiUser;
+	public $_apiBaseUri;
+	public $_dataSourceName;
+	public $_tblName;
+	public $_tblSchema;
 
 	public function execute($request) {
 
@@ -75,10 +53,10 @@ class Api_Wfs {
 		// return document tree - array of arrays
 	}
 
-	private function wfsServerAction($request) {
+	public function wfsServerAction($request) {
 	}
 
-	private function wfsExceptionAction($e) {
+	public function wfsExceptionAction($e) {
 		$dom = new DOMDocument('1.0', 'utf-8');
 		$dom->formatOutput = true;
 		$dom->preserveWhiteSpace = false;
@@ -94,7 +72,7 @@ class Api_Wfs {
 		return $dom->saveXML();
 	}
 
-	private function dataSourceAction($request) {
+	public function dataSourceAction($request) {
 		$document = '';
 		//$userAcl = User::getAcl();
 		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">user (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_apiUser);echo'</pre>';}
@@ -104,7 +82,8 @@ class Api_Wfs {
 		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$userAcl (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($userAcl);echo'</pre>';}
 
 		$this->DBG("WfsServer(" . $this->_apiUser->getID() . ") ...", __LINE__);
-		$wfsServer = new Api_WfsServer($userAcl);
+		$wfsServer = new Api_WfsDataServer($userAcl);
+		$wfsServer->setBaseUri($this->_apiBaseUri);
 		if ('WFS' != V::get('SERVICE', '', $request->query)) {
 			throw new Api_WfsException("Only WFS Service is allowed");
 		}
@@ -134,7 +113,7 @@ class Api_Wfs {
 		// TODO: return $document;
 	}
 
-	private function mainWpsAction($request) {
+	public function mainWpsAction($request) {
 		return array('TODO:'=>'TODO: Show main WPS GetCapabilities');
 	}
 

+ 244 - 0
SE/se-lib/Api/WfsDataServer.php

@@ -0,0 +1,244 @@
+<?php
+
+Lib::loadClass('Api_WfsServerBase');
+Lib::loadClass('Api_WfsException');
+Lib::loadClass('Api_WfsGeomTypeConverter');
+
+class Api_WfsDataServer extends Api_WfsServerBase {
+
+	public function parseXMLRequest() {
+		$data = array();
+		$reqContent = file_get_contents('php://input');
+		if (empty($reqContent)) {
+			throw new Exception("Empty request");
+		}
+		$parserXml = xml_parser_create();
+		xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0);
+		xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1);
+		if (0 == xml_parse_into_struct($parserXml, $reqContent, $tags)) {
+			throw new Exception("Error parsing xml");
+		}
+		xml_parser_free($parserXml);
+		if (empty($tags)) {
+			throw new Exception("Empty structure from request");
+		}
+
+		$rootTagName = V::get('tag', '', $tags[0]);
+		if ('Transaction' == $rootTagName) {
+			return $this->_parseTransactionXmlStruct($reqContent, $tags);
+		}
+
+		throw new Api_WfsException("TODO ... L." . __LINE__, 501);
+
+		$xml = new SimpleXMLElement($reqContent);
+		$namespaces = $xml->getNameSpaces(true);
+
+		if ('Transaction' == $xml->getName()) {
+			$this->_parseTransactionXml($xml);
+		}
+		else {
+			throw new Api_WfsException("Not Implemented " . htmlspecialchars($xml->getName()), 501);
+		}
+	}
+
+	public function getFeatureAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		$typeEx = explode(':', $type);
+		$maxFeatures = V::get('MAXFEATURES', '10000', $_REQUEST, 'int');// TODO: Set Deafult Limit
+		$ogcFilter = V::get('Filter', '', $_REQUEST);
+		$srsname = V::get('SRSNAME', '', $_REQUEST);// eg. EPSG:4326
+		if (count($typeEx) == 2) {
+			return $this->getFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname, $ogcFilter);
+		} else {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+	}
+
+	public function getFeatures($nsPrefix, $type, $maxFeatures, $srsname, $ogcFilter = '') {
+		$DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+		$fldList = $acl->getRealFieldList();
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		// get BBox from geom_field (only one geom fld is allowed)
+		$geomFld = null;
+		{
+			foreach ($fldList as $fldName) {
+				if ($acl->isGeomField($fldName)) {
+					$geomFld = $fldName;
+				}
+			}
+		}
+
+if($DBG){echo "ogcFilter(" . strlen($ogcFilter) . "): {$ogcFilter}\n";}
+		$searchParams = array();
+		$searchParams['limit'] = $maxFeatures;
+		$searchParams['order_by'] = $acl->getPrimaryKeyField();
+		$searchParams['order_dir'] = 'DESC';
+		if (strlen($ogcFilter) > 0) $searchParams['ogc:Filter'] = $ogcFilter;
+if($DBG){echo 'getItems:';print_r($searchParams);echo "\n";}
+		$items = $acl->getItems($searchParams);
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.opengis.net/wfs', 'wfs:FeatureCollection');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:wfs', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('xsi:schemaLocation', 'http://www.opengis.net/wfs');// TODO: add DescribeFeatureType xsd uri
+
+if($DBG){echo '(geomFld: '.$geomFld.'):';print_r($acl->getFieldType($geomFld));echo "\n";}
+		if (empty($items)) {
+			$pKeyField = $acl->getPrimaryKeyField();
+			$fakeItem = new stdClass();
+			$fakeItem->{$pKeyField} = 0;
+			$items[0] = $fakeItem;
+		}
+		foreach ($items as $itemKey => $item) {
+
+if($DBG){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld}).'):';print_r($item->{$geomFld});echo "\n";}
+
+			$featureMemberNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:featureMember');
+			$rootNode->appendChild($featureMemberNode);
+				$featureNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$type}");
+				$featureMemberNode->appendChild($featureNode);
+				$featureNode->setAttribute('fid', "{$type}.{$itemKey}");
+					foreach ($fldList as $fldName) {
+						$featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}");
+						if ($acl->isGeomField($fldName)) {
+							$geomNode = $this->_typeConverter->createGmlFromWkt($item->{$fldName}, $dom);
+							if (!$geomNode) continue;
+							$featureFldNode->appendChild($geomNode);
+						} else {
+							$featureFldNode->nodeValue = str_replace('&', '&amp;', $item->{$fldName});
+							if (empty($featureFldNode->nodeValue)) {
+								continue;
+							}
+						}
+						$featureNode->appendChild($featureFldNode);
+					}
+		}
+
+		return $dom->saveXml();
+	}
+
+	public function describeFeatureTypeAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		if (empty($type)) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		$typeEx = explode(':', $type);
+		if (count($typeEx) != 2) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		return $this->getDescribeFeatureType($typeEx[0], $typeEx[1]);
+	}
+
+	public function getDescribeFeatureType($nsPrefix, $type) {
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		if (empty($type)) {
+			throw new HttpException("Feature Type Name not defined", 400);
+		}
+		if (!$this->isAllowedFeatureType($nsPrefix, $type)) {
+			throw new Api_WfsException("Could not find type: " . htmlspecialchars($type));
+		}
+
+		$typeName = $type . 'Type';
+		$fldList = $acl->getRealFieldList();
+		header('Content-type: application/xml');
+		// <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://webgis.regione.sardegna.it:80/geoserver/schemas/gml/2.1.2/feature.xsd"/>
+		//	<xsd:element name="{type}" substitutionGroup="gml:_Feature" type="dbu:{typeName}"/>
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:schema');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('elementFormDefault', 'qualified');
+		$rootNode->setAttribute('targetNamespace', $wfsNsUri);
+
+		$cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType');
+		$rootNode->appendChild($cTypeNode);
+		$cTypeNode->setAttribute('name', $typeName);
+
+		$cConNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexContent');
+		$cTypeNode->appendChild($cConNode);
+
+		$extNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:extension');
+		$cConNode->appendChild($extNode);
+		$extNode->setAttribute('base', 'gml:AbstractFeatureType');
+
+		$seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:sequence');
+		$extNode->appendChild($seqNode);
+
+		// <xsd:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xsd:integer"/>
+		$pKeyField = $acl->getPrimaryKeyField();
+		foreach ($fldList as $fldName) {
+			$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+			$seqNode->appendChild($elNode);
+			$elNode->setAttribute('name', $fldName);
+			$minOccurs = 0;
+			if ($pKeyField == $fldName) {
+				$minOccurs = '1';
+			} else {
+				$minOccurs = '0';
+			}
+			$elNode->setAttribute('minOccurs', $minOccurs);
+			if ($acl->isIntegerField($fldName)) {
+				$fldType = 'xsd:integer';
+			}
+			else if ($acl->isDecimalField($fldName)) {
+				$fldType = 'xsd:decimal';
+			}
+			else if ($acl->isDateField($fldName)) {
+				$fldType = 'xsd:date';
+			}
+			else if ($acl->isDateTimeField($fldName)) {
+				$fldType = 'xsd:dateTime';
+			}
+			else if ($acl->isGeomField($fldName)) {
+				$fldType = 'gml:GeometryPropertyType';
+				//$fldType = 'gml:Polygon';// nie działa musi być gml:GeometryPropertyType
+			}
+			else {
+				$fldType = 'xsd:string';
+			}
+			$elNode->setAttribute('type', $fldType);
+			$elNode->setAttribute('nillable', 'true');
+		}
+
+		$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+		$rootNode->appendChild($elNode);
+		$elNode->setAttribute('name', $type);
+		$elNode->setAttribute('type', $wfsNs . ':' . $typeName);
+
+		echo $dom->saveXML();
+	}
+
+	public function getCapabilitiesAction() {
+		$wfsServerUrl = $this->getBaseUri();
+		$serviceTitle = "Web Feature Service";
+		$serviceDescription = "This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.";
+
+		//header('Content-type: application/xml; charset="utf-8"');
+		header('Content-type: application/xml');
+		$this->_getCapabilities($wfsServerUrl, $serviceTitle, $serviceDescription);
+	}
+
+}

+ 121 - 0
SE/se-lib/Api/WfsQgis.php

@@ -0,0 +1,121 @@
+<?php
+
+Lib::loadClass('ApiRouteBase');
+Lib::loadClass('ApiDataSourceTodo');// TODO: @see Entity/Source/Mysql from feature-schema-install
+Lib::loadClass('Api_WfsException');
+Lib::loadClass('Api_WfsQgisServer');
+Lib::loadClass('UserAcl');
+
+class Api_WfsQgis extends ApiRouteBase {// TODO: extends Api_WfsBase which extends ApiBase
+
+	public $_apiUser;
+	public $_apiBaseUri;
+	public $_dataSourceName;
+	public $_tblName;
+	public $_tblSchema;
+
+	public function execute($request) {
+
+		$this->reqDBG($request, __LINE__);
+
+		/* TODO: return response xml document
+		$responseDocument = null;
+		try {
+			$responseDocument = $this->wfsServerAction($request);
+		} catch (Api_WfsException $e) {// TODO: create WfsException - http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd
+		//} catch (Exception $e) {// TODO: create WfsException - http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd
+			$responseDocument = $this->wfsExceptionAction($request, $e);
+		}
+		return $responseDocument;
+		*/
+
+		if (empty($request->segments)) {
+			//$this->mainWpsAction($request);// show list of posible data source
+			throw new HttpException("Bad Request", 400);
+		} else {
+			$this->_dataSourceName = array_shift($request->segments);
+			$this->DBG("dataSourceAction({$this->_dataSourceName}) ...", __LINE__);
+			try {
+				$this->dataSourceAction($request);
+			} catch (Api_WfsException $e) {
+				$responseDocument = $this->wfsExceptionAction($e);
+				header('Content-type: application/xml');
+				echo $responseDocument;
+			} catch (Exception $e) {
+				$responseDocument = $this->wfsExceptionAction($e);
+				header('Content-type: application/xml');
+				echo $responseDocument;
+			}
+			$this->DBG("dataSourceAction() END", __LINE__);
+		}
+
+		exit;
+		// return document tree - array of arrays
+	}
+
+	public function wfsServerAction($request) {
+	}
+
+	public function wfsExceptionAction($e) {
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.opengis.net/ogc', 'ServiceExceptionReport');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+		$rootNode->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation', 'http://www.opengis.net/ogc http://schemas.opengis.net/wfs/1.0.0/OGC-exception.xsd');
+		$rootNode->setAttribute('version', '1.2.0');
+
+		$srvExNode = $dom->createElement('ServiceException', $e->getMessage());
+		$rootNode->appendChild($srvExNode);
+
+		return $dom->saveXML();
+	}
+
+	public function dataSourceAction($request) {
+		$document = '';
+		//$userAcl = User::getAcl();
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">user (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($this->_apiUser);echo'</pre>';}
+		$userAcl = new UserAcl($this->_apiUser->getID(), $use_cache = true);
+		$userAcl->fetchGroups();
+		$userAcl->fetchAllPerms(true);
+		DBG::_('DBG', '>2', 'userAcl', $userAcl, __CLASS__, __FUNCTION__, __LINE__);
+
+		$this->DBG("WfsServer(" . $this->_apiUser->getID() . ") ...", __LINE__);
+		$wfsServer = new Api_WfsQgisServer($userAcl);
+		$wfsServer->setBaseUri($this->_apiBaseUri);
+		DBG::_('DBG', true, 'getBaseNamespaceUri:', $wfsServer->getBaseNamespaceUri(), __CLASS__, __FUNCTION__, __LINE__);
+		if ('WFS' != V::get('SERVICE', '', $request->query)) {
+			throw new Api_WfsException("Only WFS Service is allowed");
+		}
+		$req = V::get('REQUEST', '', $request->query);
+		if (!empty($req)) {
+			$methodName = "{$req}Action";
+			if (!method_exists($wfsServer, $methodName)) {
+				throw new Api_WfsException("Not Implemented " . htmlspecialchars($req), 501);
+			}
+			$this->DBG("WfsServer->{$methodName}() ...", __LINE__);
+			$document = $wfsServer->$methodName($urlQuery);
+		}
+		else {
+			$this->DBG("WfsServer->parseXMLRequest() ...", __LINE__);
+			$document = $wfsServer->parseXMLRequest();
+
+			header('Content-type: application/xml');
+			echo '<?xml version="1.0" encoding="UTF-8"?>';
+			echo $document; exit;// TODO: return $document;
+		}
+		IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">$document (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($document);echo'</pre>';}
+
+		header('Content-type: application/xml');
+		echo $document; exit;// TODO: return $document;
+
+		exit;
+		// TODO: return $document;
+	}
+
+	public function mainWpsAction($request) {
+		return array('TODO:'=>'TODO: Show main WPS GetCapabilities');
+	}
+
+}

+ 288 - 0
SE/se-lib/Api/WfsQgisServer.php

@@ -0,0 +1,288 @@
+<?php
+
+Lib::loadClass('Api_WfsServerBase');
+Lib::loadClass('Api_WfsException');
+Lib::loadClass('Api_WfsGeomTypeConverter');
+
+class Api_WfsQgisServer extends Api_WfsServerBase {
+
+	public function parseXMLRequest() {
+		$data = array();
+		$reqContent = file_get_contents('php://input');
+		if (empty($reqContent)) {
+			throw new Exception("Empty request");
+		}
+		$parserXml = xml_parser_create();
+		xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0);
+		xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1);
+		if (0 == xml_parse_into_struct($parserXml, $reqContent, $tags)) {
+			throw new Exception("Error parsing xml");
+		}
+		xml_parser_free($parserXml);
+		if (empty($tags)) {
+			throw new Exception("Empty structure from request");
+		}
+
+		$rootTagName = V::get('tag', '', $tags[0]);
+		if ('Transaction' == $rootTagName) {
+			return $this->_parseTransactionXmlStruct($reqContent, $tags);
+		}
+
+		throw new Api_WfsException("TODO ... L." . __LINE__, 501);
+
+		$xml = new SimpleXMLElement($reqContent);
+		$namespaces = $xml->getNameSpaces(true);
+
+		if ('Transaction' == $xml->getName()) {
+			$this->_parseTransactionXml($xml);
+		}
+		else {
+			throw new Api_WfsException("Not Implemented " . htmlspecialchars($xml->getName()), 501);
+		}
+	}
+
+	public function getFeatureAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		$typeEx = explode(':', $type);
+		$maxFeatures = V::get('MAXFEATURES', '10000', $_REQUEST, 'int');// TODO: Set Deafult Limit
+		$srsname = V::get('SRSNAME', '', $_REQUEST);// eg. EPSG:4326
+		if (count($typeEx) == 2) {
+			return $this->getFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname);
+		} else {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+	}
+
+	public function getFeatures($nsPrefix, $type, $maxFeatures, $srsname) {
+		$DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+		$fldList = $acl->getRealFieldList();
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		// get BBox from geom_field (only one geom fld is allowed)
+		$geomFld = null;
+		{
+			foreach ($fldList as $fldName) {
+				if ($acl->isGeomField($fldName)) {
+					$geomFld = $fldName;
+				}
+			}
+		}
+
+		$dbGeomType = $acl->getGeomFieldType($geomFld);
+
+		$searchParams = array();
+		$searchParams['limit'] = $maxFeatures;
+		$searchParams['order_by'] = $acl->getPrimaryKeyField();
+		$searchParams['order_dir'] = 'DESC';
+		if ($geomFld) $searchParams["f_{$geomFld}"] = 'IS NOT NULL';
+		if ($geomFld) $searchParams["f_{$geomFld}"] = 'GeometryType=' . strtoupper($dbGeomType);
+		//if ($geomFld) $searchParams["f_{$geomFld}"] = 'GeometryType=LINESTRING';
+if($DBG){echo 'getItems:';print_r($searchParams);echo "\n";}
+		$items = $acl->getItems($searchParams);
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.opengis.net/wfs', 'wfs:FeatureCollection');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:wfs', 'http://www.opengis.net/wfs');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('xsi:schemaLocation', 'http://www.opengis.net/wfs');// TODO: add DescribeFeatureType xsd uri
+
+if(0){// TODO: get BBOX for add features
+			$boundedByNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:boundedBy');
+			$rootNode->appendChild($boundedByNode);
+				$boxNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:Box');
+				$boundedByNode->appendChild($boxNode);
+				$boxNode->setAttribute('srsName', "http://www.opengis.net/gml/srs/epsg.xml#4326");// TODO: EPSG
+					$coordinatesNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:coordinates');
+					$boxNode->appendChild($coordinatesNode);
+					$coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+					$coordinatesNode->setAttribute('decimal', '.');
+					$coordinatesNode->setAttribute('cs', ',');
+					$coordinatesNode->setAttribute('ts', ' ');
+					$coordinatesNode->nodeValue = '1544947.6295,4322758.105 1548002.2259,4330464.1001';// TODO: coordinates for all items?
+}
+
+if($DBG){echo '(geomFld: '.$geomFld.'):';print_r($acl->getFieldType($geomFld));echo "\n";}
+		if (empty($items)) {
+			$pKeyField = $acl->getPrimaryKeyField();
+			$fakeItem = new stdClass();
+			$fakeItem->{$pKeyField} = 0;
+			if ('polygon' == $dbGeomType) {
+				$fakeItem->the_geom = "POLYGON(())";
+			} else if ('linestring' == $dbGeomType) {
+				$fakeItem->the_geom = "LINESTRING()";
+			} else if ('point' == $dbGeomType) {
+				$fakeItem->the_geom = "POINT(0,0)";
+			}
+			$items[0] = $fakeItem;
+		}
+		foreach ($items as $itemKey => $item) {
+			//if($item->ID == 19)continue;
+
+if($DBG){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item->{$geomFld}).'):';print_r($item->{$geomFld});echo "\n";}
+			if ($geomFld) {
+				if (empty($item->{$geomFld})) {
+					continue;// QGIS crash when WFS contain features with empty geom field
+				}
+			}
+
+			$featureMemberNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:featureMember');
+			$rootNode->appendChild($featureMemberNode);
+				$featureNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$type}");
+				$featureMemberNode->appendChild($featureNode);
+				$featureNode->setAttribute('fid', "{$type}.{$itemKey}");
+if(0){// TODO: get BBOX
+					$boundedByNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:boundedBy');
+					$featureNode->appendChild($boundedByNode);
+						$boxNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:Box');
+						$boundedByNode->appendChild($boxNode);
+						$boxNode->setAttribute('srsName', "http://www.opengis.net/gml/srs/epsg.xml#4326");// TODO: EPSG
+							$coordinatesNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:coordinates');
+							$boxNode->appendChild($coordinatesNode);
+							$coordinatesNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+							$coordinatesNode->setAttribute('decimal', '.');
+							$coordinatesNode->setAttribute('cs', ',');
+							$coordinatesNode->setAttribute('ts', ' ');
+							$coordinatesNode->nodeValue = '1546472.2363,4328949.5775 1548002.2259,4330464.1001';// TODO: coordinates for item?
+}
+					foreach ($fldList as $fldName) {
+						$featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}");
+						if ($acl->isGeomField($fldName)) {
+							$geomNode = $this->_typeConverter->createGmlFromWkt($item->{$fldName}, $dom);
+							if (!$geomNode) continue;
+							$featureFldNode->appendChild($geomNode);
+						} else {
+							$featureFldNode->nodeValue = str_replace('&', '&amp;', $item->{$fldName});
+							if (empty($featureFldNode->nodeValue)) {
+								continue;
+							}
+						}
+						$featureNode->appendChild($featureFldNode);
+					}
+		}
+
+		return $dom->saveXml();
+	}
+
+	public function describeFeatureTypeAction() {
+		$type = V::get('TYPENAME', '', $_REQUEST);
+		if (empty($type)) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		$typeEx = explode(':', $type);
+		if (count($typeEx) != 2) {
+			throw new HttpException("Wrong param TYPENAME", 400);
+		}
+		return $this->getDescribeFeatureType($typeEx[0], $typeEx[1]);
+	}
+
+	public function getDescribeFeatureType($nsPrefix, $type) {
+		$typeName = "{$nsPrefix}:{$type}";
+		$acl = $this->getAclFromTypeName($typeName);
+
+		$baseNsUri = $this->getBaseNamespaceUri();
+		$wfsNs = 'p5_default_db_' . $type;//$nsPrefix;
+		$wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3) . '/' . $type;
+
+		if (empty($type)) {
+			throw new HttpException("Feature Type Name not defined", 400);
+		}
+		if (!$this->isAllowedFeatureType($nsPrefix, $type)) {
+			throw new Api_WfsException("Could not find type: " . htmlspecialchars($type));
+		}
+
+		$typeName = $type . 'Type';
+		$fldList = $acl->getRealFieldList();
+		header('Content-type: application/xml');
+		// <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://webgis.regione.sardegna.it:80/geoserver/schemas/gml/2.1.2/feature.xsd"/>
+		//	<xsd:element name="{type}" substitutionGroup="gml:_Feature" type="dbu:{typeName}"/>
+
+		$dom = new DOMDocument('1.0', 'utf-8');
+		$dom->formatOutput = true;
+		$dom->preserveWhiteSpace = false;
+		$rootNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:schema');
+		$dom->appendChild($rootNode);
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml');
+		$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri);
+		$rootNode->setAttribute('elementFormDefault', 'qualified');
+		$rootNode->setAttribute('targetNamespace', $wfsNsUri);
+
+		$cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType');
+		$rootNode->appendChild($cTypeNode);
+		$cTypeNode->setAttribute('name', $typeName);
+
+		$cConNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexContent');
+		$cTypeNode->appendChild($cConNode);
+
+		$extNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:extension');
+		$cConNode->appendChild($extNode);
+		$extNode->setAttribute('base', 'gml:AbstractFeatureType');
+
+		$seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:sequence');
+		$extNode->appendChild($seqNode);
+
+		// <xsd:element maxOccurs="1" minOccurs="0" name="{$fldName}" nillable="true" type="xsd:integer"/>
+		$pKeyField = $acl->getPrimaryKeyField();
+		foreach ($fldList as $fldName) {
+			$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+			$seqNode->appendChild($elNode);
+			$elNode->setAttribute('name', $fldName);
+			$minOccurs = 0;
+			if ($pKeyField == $fldName) {
+				$minOccurs = '1';
+			} else {
+				$minOccurs = '0';
+			}
+			$elNode->setAttribute('minOccurs', $minOccurs);
+			if ($acl->isIntegerField($fldName)) {
+				$fldType = 'xsd:integer';
+			}
+			else if ($acl->isDecimalField($fldName)) {
+				$fldType = 'xsd:decimal';
+			}
+			else if ($acl->isDateField($fldName)) {
+				$fldType = 'xsd:date';
+			}
+			else if ($acl->isDateTimeField($fldName)) {
+				$fldType = 'xsd:dateTime';
+			}
+			else if ($acl->isGeomField($fldName)) {
+				$fldType = 'gml:GeometryPropertyType';
+				//$fldType = 'gml:Polygon';// nie działa musi być gml:GeometryPropertyType
+			}
+			else {
+				$fldType = 'xsd:string';
+			}
+			$elNode->setAttribute('type', $fldType);
+			$elNode->setAttribute('nillable', 'true');
+		}
+
+		$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+		$rootNode->appendChild($elNode);
+		$elNode->setAttribute('name', $type);
+		$elNode->setAttribute('type', $wfsNs . ':' . $typeName);
+
+		echo $dom->saveXML();
+	}
+
+	public function getCapabilitiesAction() {
+		$wfsServerUrl = $this->getBaseUri();
+		$serviceTitle = "Web Feature Service for QGIS";
+		$serviceDescription = "This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction.";
+
+		//header('Content-type: application/xml; charset="utf-8"');
+		header('Content-type: application/xml');
+		$this->_getCapabilities($wfsServerUrl, $serviceTitle, $serviceDescription);
+	}
+
+}

Разница между файлами не показана из-за своего большого размера
+ 57 - 1101
SE/se-lib/Api/WfsServerBase.php


+ 36 - 0
SE/se-lib/ApiRouteBase.php

@@ -0,0 +1,36 @@
+<?php
+
+class ApiRouteBase {
+
+	public $_apiUser;
+	public $_apiBaseUri;
+
+	public function setUser($user) {
+		$this->_apiUser = $user;
+	}
+
+	public function setBaseUri($uri) {
+		$this->_apiBaseUri = $uri;
+	}
+
+	public function reqDBG($request, $line) {
+		$reqLog = "[" . date("Y-m-d H:m:s") . "] WFS: ---- {$_SERVER['REQUEST_METHOD']}: {$_SERVER['REQUEST_URI']}";
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') $reqLog .= "\n------------ POST:\n" . file_get_contents("php://input");
+		if (!empty($request)) $reqLog .= "\n------------ request: " . json_encode($request);
+		$reqLog .= "\n------------ END.";
+		$this->DBG($reqLog, $line);
+	}
+
+	public function DBG($reqLog, $line) {
+		$errorLogFile = APP_PATH_ROOT . "/wfs.log";
+		if (!is_writable($errorLogFile)) {
+			$fp = @fopen($errorLogFile, "w");
+			if ($fp === false) {
+				return;
+			}
+			@fclose($fp);
+		}
+		error_log("L.{$line}:{$reqLog}\n", 3, $errorLogFile);
+	}
+
+}

+ 64 - 0
SE/wfs-data.php

@@ -0,0 +1,64 @@
+<?php
+
+// Api for QGIS moved to wfs-qgis.php
+
+if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') {
+	header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
+	exit();
+}
+
+require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
+
+date_default_timezone_set('Europe/Warsaw');// PHP 5 >= 5.1.0 required by date functions
+
+$errorReportingLevel = E_ALL & ~E_NOTICE;
+error_reporting($errorReportingLevel);
+ini_set('error_reporting', $errorReportingLevel);
+
+if (file_exists(APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php")) {
+	require APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php";
+}
+if (file_exists(APP_PATH_ROOT . "/.config.php")) include APP_PATH_ROOT . "/.config.php";
+
+require_once APP_PATH_ROOT . "/superedit-SEF.php";
+SEF('DEBUG_S');
+
+Lib::loadClass('ApiUser');
+Lib::loadClass('Api');
+
+session_start();
+session_write_close();
+
+$apiUser = new ApiUser();
+// ?LOGIN=LOGOUT
+if ('LOGOUT' == V::get('LOGIN', '', $_GET)) {
+	$apiUser->logout();
+} else {
+	$apiUser->auth();
+}
+
+set_time_limit(5 * 60);
+
+$reqUri = V::get('REQUEST_URI', '', $_SERVER);
+$reqScript = V::get('SCRIPT_NAME', '', $_SERVER);
+$taskPath = str_replace($reqScript, '', $reqUri);
+$taskPath = "/xml/wfsData{$taskPath}";
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
+
+$api = new Api();
+$api->setUser($apiUser);
+$apiBaseUri = V::get('SCRIPT_URI', '', $_SERVER);
+$api->setBaseUri($apiBaseUri);
+try {
+	$api->execute($taskPath);
+}
+catch (HttpException $e) {
+	Http::sendHeaderByCode($e->getCode());
+	echo $e->getMessage();
+}
+catch (Exception $e) {
+	Http::sendHeaderByCode(500);
+	echo $e->getMessage();
+}
+
+?>

+ 64 - 0
SE/wfs-qgis.php

@@ -0,0 +1,64 @@
+<?php
+
+// Api for QGIS moved to wfs-qgis.php
+
+if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') {
+	header("Location: https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}");
+	exit();
+}
+
+require_once dirname(__FILE__) . '/se-lib/bootstrap.php';
+
+date_default_timezone_set('Europe/Warsaw');// PHP 5 >= 5.1.0 required by date functions
+
+$errorReportingLevel = E_ALL & ~E_NOTICE;
+error_reporting($errorReportingLevel);
+ini_set('error_reporting', $errorReportingLevel);
+
+if (file_exists(APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php")) {
+	require APP_PATH_ROOT . "/config/.config_{$_SERVER['SERVER_NAME']}.php";
+}
+if (file_exists(APP_PATH_ROOT . "/.config.php")) include APP_PATH_ROOT . "/.config.php";
+
+require_once APP_PATH_ROOT . "/superedit-SEF.php";
+SEF('DEBUG_S');
+
+Lib::loadClass('ApiUser');
+Lib::loadClass('Api');
+
+session_start();
+session_write_close();
+
+$apiUser = new ApiUser();
+// ?LOGIN=LOGOUT
+if ('LOGOUT' == V::get('LOGIN', '', $_GET)) {
+	$apiUser->logout();
+} else {
+	$apiUser->auth();
+}
+
+set_time_limit(5 * 60);
+
+$reqUri = V::get('REQUEST_URI', '', $_SERVER);
+$reqScript = V::get('SCRIPT_NAME', '', $_SERVER);
+$taskPath = str_replace($reqScript, '', $reqUri);
+$taskPath = "/xml/wfsQgis{$taskPath}";
+IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
+
+$api = new Api();
+$api->setUser($apiUser);
+$apiBaseUri = V::get('SCRIPT_URI', '', $_SERVER);
+$api->setBaseUri($apiBaseUri);
+try {
+	$api->execute($taskPath);
+}
+catch (HttpException $e) {
+	Http::sendHeaderByCode($e->getCode());
+	echo $e->getMessage();
+}
+catch (Exception $e) {
+	Http::sendHeaderByCode(500);
+	echo $e->getMessage();
+}
+
+?>

+ 5 - 5
SE/wfs.php

@@ -45,9 +45,14 @@ $reqUri = V::get('REQUEST_URI', '', $_SERVER);
 $reqScript = V::get('SCRIPT_NAME', '', $_SERVER);
 $taskPath = str_replace($reqScript, '', $reqUri);
 IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">taskPath (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($taskPath);echo'</pre>';}
+if ('/xml/wfs' == substr($taskPath, 0, 8)) {
+	$taskPath = "/xml/wfsQgis/" . substr($taskPath, 9);
+}
 
 $api = new Api();
 $api->setUser($apiUser);
+$apiBaseUri = V::get('SCRIPT_URI', '', $_SERVER);
+$api->setBaseUri($apiBaseUri);
 try {
 	$api->execute($taskPath);
 }
@@ -60,9 +65,4 @@ catch (Exception $e) {
 	echo $e->getMessage();
 }
 
-IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">PHP_AUTH_USER (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['PHP_AUTH_USER']);echo'</pre>';}
-IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">REQUEST_URI (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['REQUEST_URI']);echo'</pre>';}
-IF(V::get('DBG','',$_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;">SCRIPT_NAME (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($_SERVER['SCRIPT_NAME']);echo'</pre>';}
-IF(V::get('DBG','',$_GET)){die("\nEOF L." . __LINE__);}
-
 ?>

Некоторые файлы не были показаны из-за большого количества измененных файлов