Преглед изворни кода

use basic ogc:Filter in Data_Source, WfsServer->getObject

Piotr Labudda пре 10 година
родитељ
комит
49e5bd813e
2 измењених фајлова са 138 додато и 5 уклоњено
  1. 5 2
      SE/se-lib/Api/WfsServer.php
  2. 133 3
      SE/se-lib/Data_Source.php

+ 5 - 2
SE/se-lib/Api/WfsServer.php

@@ -918,15 +918,16 @@ if(0){// TODO: get BBOX
 		$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->getObjects($typeEx[0], $typeEx[1], $maxFeatures, $srsname);
+			return $this->getObjects($typeEx[0], $typeEx[1], $maxFeatures, $srsname, $ogcFilter);
 		} else {
 			throw new HttpException("Wrong param TYPENAME", 400);
 		}
 	}
 
-	public function getObjects($nsPrefix, $type, $maxFeatures, $srsname) {
+	public function getObjects($nsPrefix, $type, $maxFeatures, $srsname, $ogcFilter = '') {
 		$DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler
 		$typeName = "{$nsPrefix}:{$type}";
 		$acl = $this->getAclFromTypeName($typeName);
@@ -945,10 +946,12 @@ if(0){// TODO: get BBOX
 			}
 		}
 
+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);
 

+ 133 - 3
SE/se-lib/Data_Source.php

@@ -1,5 +1,7 @@
 <?php
 
+Lib::loadClass('SqlQueryWhereBuilder');
+
 /**
  * API:
  *   get($field_name) - source field value
@@ -237,6 +239,128 @@ if(V::get('DBG_DS', 0, $_GET) > 0){echo'<pre style="max-height:200px;overflow:au
 		return $fltrs;
 	}
 
+	public function _parseOgcFilter($ogcFilter) {
+		$ogcFilterXmlString = <<<OGC_FILTER_XML_FILE
+<?xml version="1.0" encoding="UTF-8"?>
+<filter xmlns="https://biuro.biall-net.pl/SE/version-git/schema/filter.xsd"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns:ogc="http://www.opengis.net/ogc">
+	{$ogcFilter}
+</filter>
+OGC_FILTER_XML_FILE;
+		$convertedGuiXml = $this->_convertGuiXmlToCmdList($ogcFilterXmlString);
+
+		DBG::_('DBG_DS_OGC', '>1', "convertedGuiXml(".strlen($convertedGuiXml).")", $convertedGuiXml, __CLASS__, __FUNCTION__, __LINE__);
+
+		$tags = array();
+		$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, $convertedGuiXml, $tags)) {
+			throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction failed");
+		}
+		xml_parser_free($parserXml);
+		if (empty($tags)) {
+			throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction returns empty structure");
+		}
+
+		$queryWhereBuilder = new SqlQueryWhereBuilder();
+		foreach ($tags as $tag) {
+			switch ($tag['tag']) {
+				case 'filter': {// root tag
+				}
+					break;
+				case 'sql_filter_comparisonFieldToValue': {
+					$fieldName = V::get('fieldName', '', $tag['attributes']);
+					$comparisonSign = V::get('comparisonSign', '', $tag['attributes']);
+					$value = V::get('value', '', $tag['attributes']);
+					$queryWhereBuilder->addComparisonFieldToValue($fieldName, $comparisonSign, $value);
+				}
+					break;
+				case 'sql_filter_openBlock': {
+					$blockType = V::get('type', '', $tag['attributes']);
+					DBG::_('DBG_DS_OGC', '>2', "sql_filter_openBlock block Type {$blockType} attrs", json_encode($tag), __CLASS__, __FUNCTION__, __LINE__);
+					$queryWhereBuilder->openBlock($blockType);
+				}
+					break;
+				case 'sql_filter_closeBlock': {
+					$blockType = V::get('type', '', $tag['attributes']);
+					$queryWhereBuilder->closeBlock($blockType);
+				}
+					break;
+				default: {
+					DBG::_('DBG_DS_OGC', '>1', "TODO: tag {$tag['tag']}", $queryWhereBuilder, __CLASS__, __FUNCTION__, __LINE__);
+					throw new Exception("TODO: tag {$tag['tag']}");
+				}
+			}
+		}
+
+		$queryWhereBuilder->parseQueryWhere();
+		DBG::_('DBG_DS_OGC', '>1', "queryWhereBuilder", $queryWhereBuilder, __CLASS__, __FUNCTION__, __LINE__);
+		return $queryWhereBuilder->getQueryWhere('t');
+	}
+
+	public function _convertGuiXmlToCmdList($ogcFilterXmlString) {
+		$convertOgcFilterXslString = <<<XSL_CONVERT_OGC_FILTER_TO_XML_TASK_LIST
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+								xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+								xmlns:filter="https://biuro.biall-net.pl/SE/version-git/schema/filter.xsd"
+								xmlns:ogc="http://www.opengis.net/ogc"
+								>
+	<xsl:output method="xml" omit-xml-declaration="yes" indent="no"/>
+
+	<xsl:template match="/">
+		<xsl:element name="filter">
+			<xsl:apply-templates select="filter:filter/ogc:Filter"/>
+		</xsl:element>
+	</xsl:template>
+
+	<xsl:template match="ogc:Filter">
+		<xsl:apply-templates/>
+	</xsl:template>
+
+	<xsl:template match="ogc:Or">
+		<xsl:element name="sql_filter_openBlock">
+			<xsl:attribute name="type"><xsl:value-of select="'or'" /></xsl:attribute>
+		</xsl:element>
+		<xsl:apply-templates/>
+		<xsl:element name="sql_filter_closeBlock">
+			<xsl:attribute name="type"><xsl:value-of select="'or'" /></xsl:attribute>
+		</xsl:element>
+	</xsl:template>
+
+	<xsl:template match="ogc:And">
+		<xsl:element name="sql_filter_openBlock">
+			<xsl:attribute name="type"><xsl:value-of select="'and'" /></xsl:attribute>
+		</xsl:element>
+		<xsl:apply-templates/>
+		<xsl:element name="sql_filter_closeBlock">
+			<xsl:attribute name="type"><xsl:value-of select="'and'" /></xsl:attribute>
+		</xsl:element>
+	</xsl:template>
+
+	<xsl:template match="ogc:PropertyIsEqualTo">
+		<xsl:element name="sql_filter_comparisonFieldToValue">
+			<xsl:attribute name="fieldName"><xsl:value-of select="ogc:PropertyName" /></xsl:attribute>
+			<xsl:attribute name="comparisonSign"><xsl:value-of select="'='" /></xsl:attribute>
+			<xsl:attribute name="value"><xsl:value-of select="ogc:Literal" /></xsl:attribute>
+		</xsl:element>
+	</xsl:template>
+
+</xsl:stylesheet>
+
+XSL_CONVERT_OGC_FILTER_TO_XML_TASK_LIST;
+		$requestXml = new DOMDocument();
+		$requestXml->loadXml($ogcFilterXmlString);
+
+		$convertOgcFilterXsl = new DOMDocument();
+		$convertOgcFilterXsl->loadXml($convertOgcFilterXslString);
+		$proc = new XSLTProcessor();
+		$proc->importStylesheet($convertOgcFilterXsl);
+		return $proc->transformToXML($requestXml);
+	}
+
 	function _parseSpecialFilter($fltr, $value) {
 		$sqlFltr = "";
 
@@ -393,7 +517,7 @@ if(V::get('DBG_DS', 0, $_GET) > 0){echo'<pre style="max-height:200px;overflow:au
 		return false;
 	}
 
-	function _parse_sql_where($params = array()) {
+	public function _parseSqlWhere($params = array()) {
 
 		// default filter value
 		if (empty($params['sf_Access'])) $params['sf_Access'] = 'HIDE';
@@ -473,6 +597,12 @@ if(V::get('DBG_DS', 0, $_GET) > 0){echo'<pre style="max-height:200px;overflow:au
 					$sql_where_and[] = $sqlFltr;
 				}
 			}
+			else if ('ogc:Filter' == $k) {
+				$sqlFltr = $this->_parseOgcFilter($v);
+				if (!empty($sqlFltr)) {
+					$sql_where_and[] = $sqlFltr;
+				}
+			}
 		}
 		if (!empty($sql_where_and)) {
 			$sql_where = implode(" and ", $sql_where_and);
@@ -588,7 +718,7 @@ if(V::get('DBG_DS', 0, $_GET) > 0){echo'<pre style="max-height:200px;overflow:au
 			}
 		}
 		$sql_cols = $this->_get_sql_cols();
-		$sql_where = $this->_parse_sql_where($params);
+		$sql_where = $this->_parseSqlWhere($params);
 		$sql = "select {$sql_cols}
 			from {$this->_tbl} as t
 			where {$sql_where}
@@ -653,7 +783,7 @@ if(V::get('DBG_DS', 0, $_GET) > 2){echo'<pre style="max-height:200px;overflow:au
 
 	public function getTotal($params = array()) {
 		$ret = 0;
-		$sql_where = $this->_parse_sql_where($params);
+		$sql_where = $this->_parseSqlWhere($params);
 		$sql = "select count(1) as cnt
 			from {$this->_tbl} as t
 			where {$sql_where}