Jelajahi Sumber

updated DescribeFeatureTypeAdvanced, added p5:last_update_date

Piotr Labudda 9 tahun lalu
induk
melakukan
b24f8be24b
3 mengubah file dengan 201 tambahan dan 238 penghapusan
  1. 167 235
      SE/se-lib/Api/WfsServerBase.php
  2. 31 0
      SE/se-lib/Core/AclBase.php
  3. 3 3
      SE/se-lib/TableAcl.php

+ 167 - 235
SE/se-lib/Api/WfsServerBase.php

@@ -1373,6 +1373,9 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 	public function _getDescribeFeatureTypes($typeNames, $simple = true) {
 	public function _getDescribeFeatureTypes($typeNames, $simple = true) {
 		if (empty($typeNames)) throw new HttpException("Feature Type Names not defined", 400);
 		if (empty($typeNames)) throw new HttpException("Feature Type Names not defined", 400);
 		$this->DBG("types:" . json_encode($typeNames), __LINE__, __FUNCTION__, __CLASS__);
 		$this->DBG("types:" . json_encode($typeNames), __LINE__, __FUNCTION__, __CLASS__);
+		// TODO: fix namespace BUG for multiple types:
+		//  - fetch namespace for first type
+		//  - if another object has another namespace then -> import tag
 
 
 		$baseNsUri = Api_WfsNs::getBaseWfsUri();
 		$baseNsUri = Api_WfsNs::getBaseWfsUri();
 		$rootWfsNs = 'p5';
 		$rootWfsNs = 'p5';
@@ -1380,54 +1383,54 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 		$featureTypeUri = Api_WfsNs::getBaseWfsUri() . "?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType";
 		$featureTypeUri = Api_WfsNs::getBaseWfsUri() . "?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType";
 
 
 		header('Content-type: application/xml');
 		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}"/>
-
 		$nsMap = Api_WfsNs::getNsList();// uri => prefix
 		$nsMap = Api_WfsNs::getNsList();// uri => prefix
-
-		$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->setAttribute('elementFormDefault', 'qualified');
-		// $rootNode->setAttribute('targetNamespace', Api_WfsNs::getNsUri('p5_default_db'));// TODO:? what targetNamespace if showing types from p5_objects and p5_default_db
-		{// <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="...../gml/2.1.2/feature.xsd"/>
-			$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:import');
-			$rootNode->appendChild($elNode);
-			$elNode->setAttribute('namespace', "http://www.opengis.net/gml");
-			$elNode->setAttribute('schemaLocation', Request::getPathUri() . "schema/gml/2.1.2/feature.xsd");
+		$xsdTargetNamespace = null;
+		{ // targetNamespace
+			list($nsPrefix, $objectName) = reset($typeNames);
+			$typeName = "{$nsPrefix}:{$objectName}";
+			$acl = $this->getAclFromTypeName($typeName);
+			$aclNamespaceUri = Api_WfsNs::getNsUri($acl->getSourceName());
+			$xsdTargetNamespace = $aclNamespaceUri;
+			if (!array_key_exists($aclNamespaceUri, $nsMap)) $nsMap[$aclNamespaceUri] = $acl->getSourceName();
 		}
 		}
 
 
-		// TODO: fix namespace BUG for multiple types:
-		//  - fetch namespace for first type
-		//  - if another object has another namespace then -> import tag
-
-		foreach ($typeNames as $typeNameEx) {// $typeNameEx = [ nsPrefix , name => $objectName ]
-			$objectName = $typeNameEx[1];
+		$xmlWriter = new Core_XMLWriter();
+		if (!$xmlWriter) throw new HttpException("Error no XMLWriter", 404);
+		$xmlWriter->openUri('php://output');
+		$xmlWriter->setIndent(true);
+		$xmlWriter->startDocument('1.0','UTF-8');
+		$xmlWriter->startElement('xsd:schema');
+		$xmlWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema');
+		$xmlWriter->writeAttribute('xmlns:gml', 'http://www.opengis.net/gml');
+		foreach (Api_WfsNs::getNsList() as $uri => $prefix) {
+			$xmlWriter->writeAttribute("xmlns:{$prefix}", $uri);
+		}
+		$xmlWriter->writeAttribute('elementFormDefault', "qualified");
+		if ($xsdTargetNamespace) $xmlWriter->writeAttribute('targetNamespace', $xsdTargetNamespace);
+		$schemaLocations = [];
+		//$schemaLocations[] = 'http://www.opengis.net/wfs http://webgis.regione.sardegna.it:80/geoserver/schemas/wfs/1.0.0/WFS-capabilities.xsd';// @from http://webgis.regione.sardegna.it/geoserver/ows?service=WFS&request=GetCapabilities
+		if (!empty($schemaLocations)) $xmlWriter->writeAttribute('xsi:schemaLocation', implode(' ', $schemaLocations));
+		$xmlWriter->writeAttribute('version', "1.0.0");
+		$xmlWriter->h('xsd:import', [
+			'namespace' => "http://www.opengis.net/gml",
+			'schemaLocation' => Request::getPathUri() . "schema/gml/2.1.2/feature.xsd"
+		], null);
+		foreach ($typeNames as $typeNameEx) {
+			list($nsPrefix, $objectName) = $typeNameEx;
+			$typeName = "{$nsPrefix}:{$objectName}";
+			$xmlWriter->writeComment("typeName '{$typeName}'");
+			$acl = $this->getAclFromTypeName($typeName);
 
 
-			$acl = $this->getAclFromTypeName("{$typeNameEx[0]}:{$objectName}");
-			{// xmlns and targetNamespace for root element
-				$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();
+			$acl = $this->getAclFromTypeName($typeName);
+			$aclNamespaceUri = Api_WfsNs::getNsUri($acl->getSourceName());
+			if (!array_key_exists($aclNamespaceUri, $nsMap)) $nsMap[$aclNamespaceUri] = $acl->getSourceName();
+			if ($xsdTargetNamespace != $aclNamespaceUri) {
+				$xmlWriter->writeComment("TODO: typeName '{$typeName}' by import namespace '{$aclNamespaceUri}'");// TODO: <xsd:import>; continue;
 			}
 			}
-			$objectXsdName = "{$objectName}Type";
 
 
 			if ($acl->hasSimpleSchema()) {
 			if ($acl->hasSimpleSchema()) {
 				$simpleSchema = $acl->getSimpleSchema();
 				$simpleSchema = $acl->getSimpleSchema();
-
-				foreach ($simpleSchema as $ssName => $schema) {
-					if ('root' == $ssName) $ssName = $objectName;
-					list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($schema['@namespace']);
-					if (!array_key_exists($nsUri, $nsMap)) $nsMap[$nsUri] = $prefix;
-				}
-
-				foreach ($nsMap as $uri => $prefix) {
-					$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', "xmlns:{$prefix}", $uri);
-				}
+				$xmlWriter->writeComment("TODO: typeName '{$typeName}' hasSimpleSchema L." . __LINE__);
 
 
 				$aliasRefMap = array();// fieldName => namespace uri
 				$aliasRefMap = array();// fieldName => namespace uri
 				foreach ($simpleSchema as $ssName => $schema) {
 				foreach ($simpleSchema as $ssName => $schema) {
@@ -1437,7 +1440,6 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 							&& !empty($field['@ref'])
 							&& !empty($field['@ref'])
 							&& false !== strpos($field['@ref'], '/')
 							&& false !== strpos($field['@ref'], '/')
 						) {// @ref_uri
 						) {// @ref_uri
-							// $elNode->setAttribute('ref', "{$tnsPrefix}:{$fieldName}");
 							$aliasRefMap[ "{$ssName}_{$fieldName}" ] = $field['@ref'];
 							$aliasRefMap[ "{$ssName}_{$fieldName}" ] = $field['@ref'];
 						}
 						}
 					}
 					}
@@ -1446,10 +1448,7 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 					foreach ($aliasRefMap as $fieldName => $aliasNsUri) {
 					foreach ($aliasRefMap as $fieldName => $aliasNsUri) {
 						list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($aliasNsUri);
 						list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($aliasNsUri);
 						if (!array_key_exists($nsUri, $nsMap)) $nsMap[$nsUri] = $prefix;
 						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', "{$nsUri}.xsd");// TODO: real file url -> DescribeFeatureType[Advanced]
+						$xmlWriter->h('xsd:import', ['namespace' => $nsUri, 'schemaLocation' => "{$nsUri}.xsd"], null); // TODO: real file url -> DescribeFeatureType[Advanced]
 					}
 					}
 				}
 				}
 
 
@@ -1470,241 +1469,174 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 				    //         </xsd:extension>
 				    //         </xsd:extension>
 				    //     </xsd:complexContent>
 				    //     </xsd:complexContent>
 				    // </xsd:complexType>
 				    // </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();
 						$tnsPrefix = $acl->getSourceName();
+						$xmlWriter->startElement('xsd:complexType');
+						$xmlWriter->writeAttribute('name', "{$ssName}Type");
+						$xmlWriter->startElement('xsd:sequence');
 						foreach ($schema as $fieldName => $field) {
 						foreach ($schema as $fieldName => $field) {
+							// [@namespace] => default_db/ZALICZKA_POZYCJA/ZaliczkaPozycja
+	            // [id] => xsd:integer
+	            // [kwota] => xsd:decimal
+	            // [korespondencja] => [ '@ref' => Korespondencja ]
+	            // [projekt] => [ '@ref' => Projekt ]
 							// TODO: p5:field_name
 							// TODO: p5:field_name
 							if ('@' == substr($fieldName, 0, 1)) continue;// skip tags
 							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);
+							$xmlWriter->startElement('xsd:element');
 							if (!is_array($field)) throw new Exception("Error Processing simpleSchema: '{$ssName}/{$fieldName}'");
 							if (!is_array($field)) throw new Exception("Error Processing simpleSchema: '{$ssName}/{$fieldName}'");
 							if (!empty($field['@type'])) {
 							if (!empty($field['@type'])) {
-								$elNode->setAttribute('name', $fieldName);
-								$elNode->setAttribute('type', $field['@type']);
-								$elNode->setAttribute('nillable', "true");
+								$xmlWriter->writeAttribute('name', $fieldName);
+								$xmlWriter->writeAttribute('type', $field['@type']);
+								$xmlWriter->writeAttribute('nillable', "true");
 							} else if (!empty($field['@ref'])) {
 							} else if (!empty($field['@ref'])) {
 								if (false !== strpos($field['@ref'], '/')) {// @ref_uri
 								if (false !== strpos($field['@ref'], '/')) {// @ref_uri
-									$elNode->setAttribute('ref', "{$tnsPrefix}:{$ssName}_{$fieldName}");
-									$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fieldName);
+									$xmlWriter->writeAttribute('ref', "{$tnsPrefix}:{$ssName}_{$fieldName}");
+									$xmlWriter->writeAttributeNS($rootWfsNs, "name", $rootWfsNsUri, $fieldName);
 								} else {
 								} else {
-									$elNode->setAttribute('ref', "{$tnsPrefix}:{$field['@ref']}");
+									$xmlWriter->writeAttribute('ref', "{$tnsPrefix}:{$field['@ref']}");
 									if ($fieldName != $field['@ref']) {
 									if ($fieldName != $field['@ref']) {
-										$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fieldName);
+										$xmlWriter->writeAttributeNS($rootWfsNs, "name", $rootWfsNsUri, $fieldName);
 									}
 									}
 								}
 								}
 							} else {
 							} else {
 								throw new Exception("Error Processing simpleSchema - missing @type or @ref: '{$ssName}/{$fieldName}'");
 								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']);
+							if (array_key_exists('@minOccurs', $field)) $xmlWriter->writeAttribute('minOccurs', $field['@minOccurs']);
+							if (array_key_exists('@maxOccurs', $field)) $xmlWriter->writeAttribute('maxOccurs', $field['@maxOccurs']);
+							$xmlWriter->endElement(); // 'xsd:element'
 						}
 						}
+						$xmlWriter->endElement(); // 'xsd:sequence'
+						$xmlWriter->endElement(); // 'xsd:complexType'
 
 
-						$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
-						$rootNode->appendChild($elNode);
-						$elNode->setAttribute('name', $ssName);
-						$elNode->setAttribute('type', "{$tnsPrefix}:{$ssName}Type");
+						$xmlWriter->startElement('xsd:element');
+						$xmlWriter->writeAttribute('name', $ssName);
+						$xmlWriter->writeAttribute('type', "{$tnsPrefix}:{$ssName}Type");
 						if (!$simple) {
 						if (!$simple) {
 							if (!empty($schema['@namespace'])) {// TODO: @namespace is required?
 							if (!empty($schema['@namespace'])) {// TODO: @namespace is required?
 								list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($schema['@namespace']);
 								list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($schema['@namespace']);
-								$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:namespace", '{' . $nsUri . '}' . $name);
+								$xmlWriter->writeAttributeNS($rootWfsNs, "namespace", $rootWfsNsUri, "{{$nsUri}}{$name}");
 							}
 							}
 						}
 						}
+						$xmlWriter->endElement(); // 'xsd:element'
 					}
 					}
 				}
 				}
 
 
 				if (!empty($aliasRefMap)) {
 				if (!empty($aliasRefMap)) {
 					foreach ($aliasRefMap as $fieldName => $aliasNsUri) {
 					foreach ($aliasRefMap as $fieldName => $aliasNsUri) {
 						list($nsUri, $prefix, $name) = Api_WfsNs::parseObjectNsUri($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");
+						$xmlWriter->h('xsd:element', ['name' => $fieldName, 'type' => "{$prefix}:{$name}Type"], null);
 					}
 					}
 				}
 				}
-
-				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', $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');
-			$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();
-			$p5Attributes = ($simple)? array() : $acl->getAttributesFromZasoby();
-			foreach ($fldList as $fldName) {
-				$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
-				$seqNode->appendChild($elNode);
-				$minOccurs = 0;
-				if ($pKeyField == $fldName) {
-					$minOccurs = '1';
-				} else {
-					$minOccurs = '0';
-				}
-				$elNode->setAttribute('minOccurs', $minOccurs);
-				$elNode->setAttribute('maxOccurs', '1');
-				$fldType = $acl->getXsdFieldType($fldName);
-				if (!$simple && $acl->isEnumerationField($fldName)) {
-					$fldType = $acl->getSourceName() . ":{$fldName}Type";
-				}
-				if ('ref:' == substr($fldType, 0, 4)) {
-					$elNode->setAttribute('ref', substr($fldType, 4));
-					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
-				} else if ('local_ref:' == substr($fldType, 0, 10)) {
-					$elNode->setAttribute('type', "{$fldName}Type");
-					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
-				} else if ('alias_ref:' == substr($fldType, 0, 10)) {
-					$elNode->setAttribute('ref', $acl->getSourceName() . ":{$fldName}");
-					$elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:name", $fldName);
-				} else {
-					$elNode->setAttribute('name', $fldName);
-					$elNode->setAttribute('type', $fldType);
-					$elNode->setAttribute('nillable', 'true');// nillable not allowed in ref
+			} else {
+				$objectXsdName = "{$objectName}Type";
+				$xmlWriter->startElement('xsd:complexType');
+				$xmlWriter->writeAttribute('name', $objectXsdName);
+				// if (!$simple) $xmlWriter->writeAttribute("xlmns:{$rootWfsNs}", $rootWfsNsUri);
+				if (!$simple) $xmlWriter->writeAttributeNS($rootWfsNs, "web_link", $rootWfsNsUri, Request::getPathUri() . "index.php?_route=ViewTableAjax&namespace=" . $acl->getNamespace());
+				if (!$simple && ($lastUpdateDate = $acl->lastUpdateDate())) $xmlWriter->writeAttributeNS($rootWfsNs, "last_update_date", $rootWfsNsUri, $lastUpdateDate);
+				$xmlWriter->startElement('xsd:complexContent');
+				$xmlWriter->startElement('xsd:extension');
+				$xmlWriter->writeAttribute('base', "gml:AbstractFeatureType");
+				$xmlWriter->startElement('xsd:sequence');
+				$pKeyField = $acl->getPrimaryKeyField();
+				$p5Attributes = ($simple)? array() : $acl->getAttributesFromZasoby();
+				$fldList = $this->_getFieldListFromAcl($acl);
+				foreach ($fldList as $fldName) {
+					$xmlWriter->startElement('xsd:element');
+					$xmlWriter->writeAttribute('minOccurs', ($pKeyField == $fldName) ? '1' : '0'); // TODO: get minOccurs from $acl->xsd()
+					$xmlWriter->writeAttribute('maxOccurs', '1');
+					$fldType = $acl->getXsdFieldType($fldName);
+					if (!$simple && $acl->isEnumerationField($fldName)) {
+						$fldType = $acl->getSourceName() . ":{$fldName}Type";
+					}
+					if ('ref:' == substr($fldType, 0, 4)) {
+						$xmlWriter->writeAttribute("ref", substr($fldType, 4));
+						$xmlWriter->writeAttributeNS($rootWfsNs, "name", $rootWfsNsUri, $fldName);
+					} else if ('local_ref:' == substr($fldType, 0, 10)) {
+						$xmlWriter->writeAttribute("type", "{$fldName}Type");
+						$xmlWriter->writeAttributeNS($rootWfsNs, "name", $rootWfsNsUri, $fldName);
+					} else if ('alias_ref:' == substr($fldType, 0, 10)) {
+						$xmlWriter->writeAttribute("ref", $acl->getSourceName() . ":{$fldName}");
+						$xmlWriter->writeAttributeNS($rootWfsNs, "name", $rootWfsNsUri, $fldName);
+					} else {
+						$xmlWriter->writeAttribute('name', $fldName);
+						$xmlWriter->writeAttribute('type', $fldType);
+						$xmlWriter->writeAttribute('nillable', 'true');// nillable not allowed in ref
+					}
+					if (!$simple) {
+						if (!empty($p5Attributes[$fldName])) {
+							$p5attrs = $p5Attributes[$fldName];
+							if (!empty($p5attrs['id_zasob'])) $xmlWriter->writeAttributeNS($rootWfsNs, "id_zasob", $rootWfsNsUri, $p5attrs['id_zasob']);
+							if (!empty($p5attrs['label'])) $xmlWriter->writeAttributeNS($rootWfsNs, "label", $rootWfsNsUri, $p5attrs['label']);
+							if (!empty($p5attrs['description'])) $xmlWriter->writeAttributeNS($rootWfsNs, "description", $rootWfsNsUri, $p5attrs['description']);
+						}
+						if ($acl->canWriteField($fldName)) $xmlWriter->writeAttributeNS($rootWfsNs, "allow_write", $rootWfsNsUri, "true");
+						if ($acl->canCreateField($fldName)) $xmlWriter->writeAttributeNS($rootWfsNs, "allow_create", $rootWfsNsUri, "true");
+						if (!$acl->canReadField($fldName)) $xmlWriter->writeAttributeNS($rootWfsNs, "allow_read", $rootWfsNsUri, "false");
+					}
+					$xmlWriter->endElement(); // xsd:element
 				}
 				}
+				$xmlWriter->endElement(); // xsd:sequence
+				$xmlWriter->h('xsd:attribute', ['name' => "instance", 'type' => $acl->getSourceName() . ":instanceType"], null);
+				$xmlWriter->endElement(); // xsd:extension
+				$xmlWriter->endElement(); // xsd:complexContent
+				$xmlWriter->endElement(); // xsd:complexType
 
 
 				if (!$simple) {
 				if (!$simple) {
-					if (!empty($p5Attributes[$fldName])) {
-						$p5attrs = $p5Attributes[$fldName];
-						if (!empty($p5attrs['id_zasob'])) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:id_zasob", $p5attrs['id_zasob']);
-						if (!empty($p5attrs['label'])) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:label", $p5attrs['label']);
-						if (!empty($p5attrs['description'])) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:description", $p5attrs['description']);
+					$xsdInstanceList = [];
+					$xsdInstanceList[] = ['xsd:enumeration', ['value'=>$acl->getName()], null];
+					if (method_exists($acl, 'getInstanceList')) {
+						foreach ($acl->getInstanceList() as $instanceName) {
+							$xsdInstanceList[] = ['xsd:enumeration', ['value'=>$instanceName], null];
+						}
 					}
 					}
-					if ($acl->canWriteField($fldName)) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true");
-					if ($acl->canCreateField($fldName)) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_create", "true");
-					if (!$acl->canReadField($fldName)) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false");
+					$xmlWriter->h('xsd:simpleType', ['name' => 'instanceType'], [
+						[ 'xsd:restriction', ['base' => 'xsd:string'], $xsdInstanceList ]
+					]);
 				}
 				}
-			}
 
 
-			if (!$simple) {
-				$instanceNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute');
-				$extNode->appendChild($instanceNode);
-				$instanceNode->setAttribute('name', 'instance');
-				$instanceNode->setAttribute('type', $acl->getSourceName() . ':' . "instanceType");
-
-				$instanceTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:simpleType');
-				$rootNode->appendChild($instanceTypeNode);
-				$instanceTypeNode->setAttribute('name', "instanceType");
-					$insResNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:restriction');
-					$instanceTypeNode->appendChild($insResNode);
-					$insResNode->setAttribute('base', "xsd:string");
-						$insEnumNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:enumeration');
-						$insResNode->appendChild($insEnumNode);
-						$insEnumNode->setAttribute('value', $acl->getName());
-						if (method_exists($acl, 'getInstanceList')) {
-							foreach ($acl->getInstanceList() as $instanceName) {
-								$insEnumNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:enumeration');
-								$insResNode->appendChild($insEnumNode);
-								$insEnumNode->setAttribute('value', $instanceName);
-							}
-						}
-			}
+				$xmlWriter->h('xsd:element', ['name' => $objectName, 'type' => $acl->getSourceName() . ':' . $objectXsdName, 'substitutionGroup'=>"gml:_Feature"], null);
 
 
-			$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
-			$rootNode->appendChild($elNode);
-			$elNode->setAttribute('name', $objectName);
-			$elNode->setAttribute('type', $acl->getSourceName() . ':' . $objectXsdName);
-			$elNode->setAttribute('substitutionGroup', 'gml:_Feature');// gml:AbstractFeature in gml 3
-
-			foreach ($fldList as $fldName) {
-				$fldType = $acl->getXsdFieldType($fldName);
-				if ('alias_ref:' == substr($fldType, 0, 10)) {
-					$localRefType = substr($fldType, 10);
-					// <xsd:element name="{$fldName}" ref="{$localRefType}">
-					$ctNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
-					$rootNode->appendChild($ctNode);
-					$ctNode->setAttribute('name', $fldName);
-					$ctNode->setAttribute('type', $localRefType);
-				} else if ('local_ref:' == substr($fldType, 0, 10)) {
-					$localRefType = substr($fldType, 10);
-					// <xsd:complexType name="produkt_Type">
-					// 	<xsd:sequence>
-					// 		<xsd:element name="idProd" type="xsd:integer" />
-					// 		<xsd:element name="nazwa" type="xsd:string" />
-					// 		<xsd:element name="cena" type="xsd:decimal" />
-					// 	</xsd:sequence>
-					// </xsd:complexType>
-					$ctNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType');
-					$rootNode->appendChild($ctNode);
-					$ctNode->setAttribute('name', "{$fldName}Type");
-
-					$seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:sequence');
-					$ctNode->appendChild($seqNode);
-
-					$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
-					$seqNode->appendChild($elNode);
-					$elNode->setAttribute('name', "test_id");
-					$elNode->setAttribute('type', "xsd:integer");
-
-					$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
-					$seqNode->appendChild($elNode);
-					$elNode->setAttribute('name', "test_opis");
-					$elNode->setAttribute('type', "xsd:string");
-
-					$elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element');
-					$seqNode->appendChild($elNode);
-					$elNode->setAttribute('name', "test_decimal");
-					$elNode->setAttribute('type', "xsd:decimal");
+				foreach ($fldList as $fldName) {
+					$fldType = $acl->getXsdFieldType($fldName);
+					if ('alias_ref:' == substr($fldType, 0, 10)) {
+						$localRefType = substr($fldType, 10);
+						$xmlWriter->h('xsd:element', ['name' => $fldName, 'type' => $localRefType], null);
+					} else if ('local_ref:' == substr($fldType, 0, 10)) {
+						$localRefType = substr($fldType, 10);
+						$xmlWriter->writeComment("TODO:
+							<xsd:complexType name=\"produkt_Type\">
+								<xsd:sequence>
+									<xsd:element name=\"idProd\" type=\"xsd:integer\" />
+									<xsd:element name=\"nazwa\" type=\"xsd:string\" />
+									<xsd:element name=\"cena\" type=\"xsd:decimal\" />
+								</xsd:sequence>
+							</xsd:complexType>
+						");
+					}
 				}
 				}
-			}
 
 
-			if (!$simple) {
-				foreach ($fldList as $fldName) {
-					if ($acl->isEnumerationField($fldName)) {
+				if (!$simple) {
+					foreach ($fldList as $fldName) {
+						if (!$acl->isEnumerationField($fldName)) continue;
+						$xsdEnumList = [];
 						$enum = $acl->getEnumerations($fldName);
 						$enum = $acl->getEnumerations($fldName);
-						$stNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:simpleType');
-						$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);
-							$resNode->setAttribute('base', 'xsd:string');
-							// TODO: if (!empty($p5Attributes[$fldName]['valuesMap'])) -> show only this values
-							foreach ($enum as $val => $label) {
-								$enumNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:enumeration');
-								$resNode->appendChild($enumNode);
-								$enumNode->setAttribute('value', "{$val}");
-
-								if (!empty($p5Attributes[$fldName]['valuesMap'][$val])) {
-									$enumNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:label", $p5Attributes[$fldName]['valuesMap'][$val]);
-								}
+						foreach ($enum as $val => $label) {
+							$xsdEnum = ['xsd:enumeration', ['value' => $val], null];
+							if (!empty($p5Attributes[$fldName]['valuesMap'][$val])) {
+								$xsdEnum[1]["xmlns:{$rootWfsNs}"] = $rootWfsNsUri;
+								$xsdEnum[1]["{$rootWfsNs}:label"] = $p5Attributes[$fldName]['valuesMap'][$val];
 							}
 							}
+							$xsdEnumList[] = $xsdEnum;
+						}
+						$xmlWriter->h('xsd:simpleType', ['name' => "{$fldName}Type"], [
+							[ 'xsd:restriction', ['base' => "xsd:string"], $xsdEnumList ]
+						]);
 					}
 					}
 				}
 				}
 			}
 			}
 		}
 		}
-
-		foreach ($nsMap as $uri => $prefix) {
-			$rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', "xmlns:{$prefix}", $uri);
-		}
-
-		return $dom->saveXML();
+		$xmlWriter->endElement(); // 'xsd:schema'
+		$xmlWriter->endDocument();
 	}
 	}
 
 
 	public function _getTableAclList() {// Use only Tables from default_db
 	public function _getTableAclList() {// Use only Tables from default_db

+ 31 - 0
SE/se-lib/Core/AclBase.php

@@ -14,6 +14,8 @@ Lib::loadClass('ACL');
 */
 */
 class Core_AclBase {
 class Core_AclBase {
 
 
+  public $_rootTableName = null;
+
   public function getNamespace() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getNamespace() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getSourceName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getSourceName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
   public function getName() { throw new HttpException("Acl function " . __FUNCTION__ . " Not implemented", 501); }
@@ -823,4 +825,33 @@ if($DBG){die();}
 
 
   public function getSqlFieldName($childName) { throw new Exception("Unimplemented - TODO: " . get_class($this) . "::" . __FUNCTION__); }
   public function getSqlFieldName($childName) { throw new Exception("Unimplemented - TODO: " . get_class($this) . "::" . __FUNCTION__); }
 
 
+  public function getHistItems($primaryKey) { throw new Exception("Unimplemented - TODO: " . get_class($this) . "::" . __FUNCTION__); }
+
+  public function lastUpdateDate() {
+    try {
+      if (!$this->_rootTableName) throw new Exception("Missing rootTableName in (" . get_class($this) . ", " . $this->getNamespace() . ")");
+      $lastUpdateDate = DB::getPDO()->fetchValue("
+        select IF('N/S;' = A_RECORD_UPDATE_DATE or A_RECORD_UPDATE_DATE is null or '' = A_RECORD_UPDATE_DATE, A_RECORD_CREATE_DATE, A_RECORD_UPDATE_DATE) as lastUpdateDate
+        from `{$this->_rootTableName}_HIST`
+        order by ID DESC
+        limit 1
+      ");
+      if ($lastUpdateDate) {// convert to xsd format '2002-05-30T09:00:00'
+        $xsdLastUpdate = '';
+        if (preg_match('/^\d\d\d\d\-\d\d\-\d\d\-\d\d:\d\d$/', $lastUpdateDate)) { // 'Y-m-d-H:i'
+          $xsdLastUpdate = substr($lastUpdateDate, 0, 10) . "T" . substr($lastUpdateDate, 11) . ":00";
+        } else if (preg_match('/^\d\d\d\d\-\d\d\-\d\d\-\d\d:\d\d:\d\d$/', $lastUpdateDate)) { // 'Y-m-d-H:i:s'
+          $xsdLastUpdate = substr($lastUpdateDate, 0, 10) . "T" . substr($lastUpdateDate, 11);
+        }
+        if (preg_match('/^\d\d\d\d\-\d\d\-\d\d\ \d\d:\d\d:\d\d$/', $lastUpdateDate)) {
+          $xsdLastUpdate = substr($lastUpdateDate, 0, 10) . "T" . substr($lastUpdateDate, 11);
+        }
+        return $xsdLastUpdate;
+      }
+    } catch (Exception $e) {
+      DBG::log($e);
+    }
+    return '';
+  }
+
 }
 }

+ 3 - 3
SE/se-lib/TableAcl.php

@@ -1509,12 +1509,12 @@ class TableAcl extends Core_AclBase {
 		return $geomType;
 		return $geomType;
 	}
 	}
 
 
-	public function getHistItems($id) {
+	public function getHistItems($primaryKey) {
 		if ($this->_schemaClass && method_exists($this->_schemaClass, 'hasGetHistItems') && $this->_schemaClass->hasGetHistItems()) {
 		if ($this->_schemaClass && method_exists($this->_schemaClass, 'hasGetHistItems') && $this->_schemaClass->hasGetHistItems()) {
-			return $this->_schemaClass->getHistItems($id);
+			return $this->_schemaClass->getHistItems($primaryKey);
 		}
 		}
 		$ds = $this->getDataSource();
 		$ds = $this->getDataSource();
-		return $ds->getHistItems($id);
+		return $ds->getHistItems($primaryKey);
 	}
 	}
 
 
 	public function getHistItem($id, $idHist) {
 	public function getHistItem($id, $idHist) {