فهرست منبع

added simpleSchema support for Wfs server DescribeFeatureType

Piotr Labudda 9 سال پیش
والد
کامیت
37e2f088be
2فایلهای تغییر یافته به همراه136 افزوده شده و 16 حذف شده
  1. 4 1
      SE/se-lib/Api/WfsNs.php
  2. 132 15
      SE/se-lib/Api/WfsServerBase.php

+ 4 - 1
SE/se-lib/Api/WfsNs.php

@@ -53,7 +53,10 @@ class Api_WfsNs {
     return Request::getHostUri() . "/wfs";
   }
 
-  // @returns [ $nsUri, $prefix, $name ]
+  /**
+   * @return [ $nsUri, $prefix, $name ]
+   * @example: list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri('default_objects/AccessOwner');
+   */
   public static function parseObjectNsUri($objectNsUri) {
     if ('{' == substr($objectNsUri, 0, 1)) $objectNsUri = str_replace('}', '/', substr($objectNsUri, 1));// form like "{.../wfs/default_objects}AccessOwner"
     $nsEx = explode('/', $objectNsUri);

+ 132 - 15
SE/se-lib/Api/WfsServerBase.php

@@ -1394,24 +1394,141 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 			$elNode->setAttribute('schemaLocation', Request::getPathUri() . "schema/gml/2.1.2/feature.xsd");
 		}
 
-		foreach ($typeNames as $typeNameEx) {
-			$nsPrefix = $typeNameEx[0];
-			$type = $typeNameEx[1];
+		// TODO: fix namespace BUG for multiple types:
+		//  - fetch namespace for first type
+		//  - if another object has another namespace then -> import tag
 
-			$typeName = "{$nsPrefix}:{$type}";
-			$acl = $this->getAclFromTypeName($typeName);
+		foreach ($typeNames as $typeNameEx) {// $typeNameEx = [ nsPrefix , name => $objectName ]
+			$objectName = $typeNameEx[1];
+
+			$acl = $this->getAclFromTypeName("{$typeNameEx[0]}:{$objectName}");
 			{// xmlns and targetNamespace for root element
-				$aclNamespace = Api_WfsNs::getNsUri($acl->getSourceName());
-				$rootNode->setAttribute('targetNamespace', $aclNamespace);
-				if (!array_key_exists($aclNamespace, $nsMap)) $nsMap[$aclNamespace] = $nsPrefix;
+				$aclNamespaceUri = Api_WfsNs::getNsUri($acl->getSourceName());
+				$rootNode->setAttribute('targetNamespace', $aclNamespaceUri);
+				// TODO: if targetNamespace already set then import tag
+				if (!array_key_exists($aclNamespaceUri, $nsMap)) $nsMap[$aclNamespaceUri] = $acl->getSourceName();
 			}
-			$typeName = $type . 'Type';
+			$objectXsdName = "{$objectName}Type";
+
+			if ($acl->hasSimpleSchema()) {
+				$simpleSchema = $acl->getSimpleSchema();
+
+				$aliasRefMap = array();// fieldName => namespace uri
+				foreach ($simpleSchema as $ssName => $schema) {
+					if ('root' == $ssName) $ssName = $objectName;
+					foreach ($schema as $fieldName => $field) {
+						if (is_array($field)
+							&& !empty($field['@ref'])
+							&& false !== strpos($field['@ref'], '/')
+						) {// @ref_uri
+							// $elNode->setAttribute('ref', "{$tnsPrefix}:{$fieldName}");
+							$aliasRefMap[ "{$ssName}_{$fieldName}" ] = $field['@ref'];
+						}
+					}
+				}
+				if (!empty($aliasRefMap)) {
+					foreach ($aliasRefMap as $fieldName => $aliasNsUri) {
+						list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($aliasNsUri);
+						if (!array_key_exists($nsUri, $nsMap)) $nsMap[$nsUri] = $prefix;
+						$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:import');
+						$rootNode->appendChild($elNode);
+						$elNode->setAttribute('namespace', $nsUri);
+						$elNode->setAttribute('schemaLocation', "{$name}.xsd");// TODO: real file url -> DescribeFeatureType[Advanced]
+					}
+				}
+
+				foreach ($simpleSchema as $ssName => $schema) {
+					{// code from Code_AclSimpleSchema
+						if ('root' == $ssName) $ssName = $objectName;
+
+				    if (empty($schema['@namespace'])) throw new Exception("Missing @namespace in schema for '{$ssName}'");
+				    $ns = explode('/', $schema['@namespace']);
+				    $name = end($ns);
+				    if (count($ns) < 2) throw new Exception("Wrong @namespace syntax in schema for '{$ssName}'");
+				    $rootTableName = $ns[1];
+
+						$aclNamespaceUri = Api_WfsNs::getNsUri("default_db__x3A__{$rootTableName}");
+						if (!array_key_exists($aclNamespaceUri, $nsMap)) $nsMap[$aclNamespaceUri] = "default_db__x3A__{$rootTableName}";
+
+						// <xsd:complexType name="ZaliczkaPozycjaType">
+				    //     <xsd:complexContent>
+				    //         <xsd:extension base="gml:AbstractFeatureType">
+				    //             <xsd:sequence>
+				    //                 <xsd:element minOccurs="0" maxOccurs="1" name="id" type="xsd:integer" nillable="true"/>
+				    //                 <xsd:element minOccurs="0" maxOccurs="1" name="created" type="xsd:date" nillable="true"/>
+				    //                 <xsd:element minOccurs="0" maxOccurs="1" ref="default_objects/AccessOwner" p5:name="worker"/>
+				    //                 <xsd:element minOccurs="0" maxOccurs="1" name="kwota" type="xsd:decimal" nillable="true"/>
+				    //                 <xsd:element minOccurs="0" maxOccurs="1" ref="ZaliczkaPozycja" p5:name="pozycja"/>
+				    //             </xsd:sequence>
+				    //         </xsd:extension>
+				    //     </xsd:complexContent>
+				    // </xsd:complexType>
+						$cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType');
+						$rootNode->appendChild($cTypeNode);
+						$cTypeNode->setAttribute('name', "{$ssName}Type");
+
+						$seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:sequence');
+						$cTypeNode->appendChild($seqNode);
+
+						// [@namespace] => default_db/ZALICZKA_POZYCJA/ZaliczkaPozycja
+            // [id] => xsd:integer
+            // [kwota] => xsd:decimal
+            // [korespondencja] => [ '@ref' => Korespondencja ]
+            // [projekt] => [ '@ref' => Projekt ]
+
+						$tnsPrefix = $acl->getSourceName();
+						foreach ($schema as $fieldName => $field) {
+							// TODO: p5:field_name
+							if ('@' == substr($fieldName, 0, 1)) continue;// skip tags
+							//                 <xsd:element minOccurs="0" maxOccurs="1" name="id" type="xsd:integer" nillable="true"/>
+							$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+							$seqNode->appendChild($elNode);
+							if (!is_array($field)) throw new Exception("Error Processing simpleSchema: '{$ssName}/{$fieldName}'");
+							if (!empty($field['@type'])) {
+								$elNode->setAttribute('name', $fieldName);
+								$elNode->setAttribute('type', $field['@type']);
+								$elNode->setAttribute('nillable', "true");
+							} else if (!empty($field['@ref'])) {
+								if (false !== strpos($field['@ref'], '/')) {// @ref_uri
+									$elNode->setAttribute('ref', "{$tnsPrefix}:{$ssName}_{$fieldName}");
+								} else {
+									$elNode->setAttribute('ref', "{$tnsPrefix}:{$field['@ref']}");
+								}
+							} else {
+								throw new Exception("Error Processing simpleSchema - missing @type or @ref: '{$ssName}/{$fieldName}'");
+							}
+							if (array_key_exists('@minOccurs', $field)) $elNode->setAttribute('minOccurs', $field['@minOccurs']);
+							if (array_key_exists('@maxOccurs', $field)) $elNode->setAttribute('maxOccurs', $field['@maxOccurs']);
+						}
+
+						$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+						$rootNode->appendChild($elNode);
+						$elNode->setAttribute('name', $ssName);
+						$elNode->setAttribute('type', "{$tnsPrefix}:{$ssName}Type");
+						if (!$simple) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:namespace", $aclNamespaceUri);
+					}
+
+					if (!empty($aliasRefMap)) {
+						foreach ($aliasRefMap as $fieldName => $aliasNsUri) {
+							list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($aliasNsUri);
+							$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
+							$rootNode->appendChild($elNode);
+							$elNode->setAttribute('name', $fieldName);
+							$elNode->setAttribute('type', "{$prefix}:{$name}Type");
+						}
+					}
+				}
+
+				if (V::get('DBG_SS', '', $_GET)) echo "\n<!--\n" . $acl . "\n-->\n";// TODO: DBG
+				continue;
+			}
+
 			$fldList = $this->_getFieldListFromAcl($acl);
 			DBG::_('DBG_XSD', '>1', "field list", $fldList, __CLASS__, __FUNCTION__, __LINE__);
 
 			$cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType');
 			$rootNode->appendChild($cTypeNode);
-			$cTypeNode->setAttribute('name', $typeName);
+			$cTypeNode->setAttribute('name', $objectXsdName);
 			if (!$simple) $cTypeNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:web_link", Request::getPathUri() . "index.php?_route=ViewTableAjax&namespace=" . $acl->getNamespace());
 
 			$cConNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexContent');
@@ -1440,7 +1557,7 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 				$elNode->setAttribute('maxOccurs', '1');
 				$fldType = $acl->getXsdFieldType($fldName);
 				if (!$simple && $acl->isEnumerationField($fldName)) {
-					$fldType = "{$nsPrefix}:{$fldName}Type";
+					$fldType = $acl->getSourceName() . ":{$fldName}Type";
 				}
 				if ('ref:' == substr($fldType, 0, 4)) {
 					$elNode->setAttribute('ref', substr($fldType, 4));
@@ -1449,7 +1566,7 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 					$elNode->setAttribute('type', "{$fldName}Type");
 					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
 				} else if ('alias_ref:' == substr($fldType, 0, 10)) {
-					$elNode->setAttribute('ref', "p5_" . $acl->getSourceName() . ":{$fldName}");
+					$elNode->setAttribute('ref', $acl->getSourceName() . ":{$fldName}");
 					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
 				} else {
 					$elNode->setAttribute('name', $fldName);
@@ -1472,8 +1589,8 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 
 			$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
 			$rootNode->appendChild($elNode);
-			$elNode->setAttribute('name', $type);
-			$elNode->setAttribute('type', $nsPrefix . ':' . $typeName);// TODO: $acl->getSourceName() != $nsPrefix
+			$elNode->setAttribute('name', $objectName);
+			$elNode->setAttribute('type', $acl->getSourceName() . ':' . $objectXsdName);
 			$elNode->setAttribute('substitutionGroup', 'gml:_Feature');// gml:AbstractFeature in gml 3
 
 			foreach ($fldList as $fldName) {
@@ -1523,7 +1640,7 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 					if ($acl->isEnumerationField($fldName)) {
 						$enum = $acl->getEnumerations($fldName);
 						$stNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:simpleType');
-						$stNode->setAttribute('name', "{$fldName}Type");//"{$nsPrefix}:{$fldName}Type");
+						$stNode->setAttribute('name', "{$fldName}Type");// $acl->getSourceName() . ":{$fldName}Type"
 						$rootNode->appendChild($stNode);
 							$resNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:restriction');
 							$stNode->appendChild($resNode);