Bladeren bron

fixed WFS GetFeature recurse

Piotr Labudda 8 jaren geleden
bovenliggende
commit
6b113e7675
2 gewijzigde bestanden met toevoegingen van 158 en 77 verwijderingen
  1. 155 2
      SE/se-lib/Api/Wfs/GetFeature.php
  2. 3 75
      SE/se-lib/Api/WfsDataServer.php

+ 155 - 2
SE/se-lib/Api/Wfs/GetFeature.php

@@ -1,9 +1,154 @@
 <?php
 
 Lib::loadClass('Api_WfsGeomTypeConverter');
+Lib::loadClass('Core_AclHelper');
 
 class Api_Wfs_GetFeature {
 
+	public static function convertOgcPropertyListToFeatureQueryColsRecurseDBG(&$schemaCache, $ogcPropertyList, $aclOrSchema, $dbgLoopNr = 0) {
+		if ($dbgLoopNr > 10) {
+			DBG::log($ogcPropertyList, 'array', 'TODO: split $ogcPropertyList to acl fields and nested fields - DBG LOOP LIMIT 10');
+			return [];
+		}
+		$acl = null;
+		if (is_array($aclOrSchema) && !empty($aclOrSchema['namespace'])) {
+			$acl = Core_AclHelper::getAclByNamespace($aclOrSchema['namespace'], false, $aclOrSchema);
+		} else if ($aclOrSchema instanceof Core_AclBase) {
+			$acl = $aclOrSchema;
+		} else throw new Exception("Missing acl");
+
+		if (empty($ogcPropertyList)) {
+			// DBG::log($acl->getFields(), '', "TODO: \$ogcPropertyList = \$acl->getFields()");
+			// DBG::log($acl->getFieldListByIdZasob(), 'array', "TODO: \$ogcPropertyList = \$acl->getFieldListByIdZasob()");
+			$ogcPropertyList = array_values($acl->getFieldListByIdZasob());
+		}
+
+		DBG::log($ogcPropertyList, 'array', 'TODO: split $ogcPropertyList to acl fields and nested fields');
+		$aclFields = array_filter($ogcPropertyList, function ($prop) { return ( false === strpos($prop, '/') ); });
+		$nestedFields = array_reduce(
+			array_filter($ogcPropertyList, function ($prop) { return ( false !== strpos($prop, '/') ); }),
+			function ($ret, $propNested) {
+				list($childName, $nestedPart) = explode('/', $propNested, 2);
+				if (!array_key_exists($childName, $ret)) $ret[ $childName ] = [];
+				$ret[ $childName ][] = $nestedPart;
+				return $ret;
+			},
+			[]
+		);
+		if (!empty($nestedFields)) {
+			$aclFields = array_unique(array_merge($aclFields, array_keys($nestedFields)));
+		}
+		DBG::log([$aclFields, $nestedFields], 'array', 'TODO: splited $ogcPropertyList to acl fields and nested fields');
+
+		// TODO: convert '*' to local fields
+		// TODO: validate $aclFields is in $acl->getFields() or in $schemaCache[ nsLocal ]
+
+		$contextFieldList = $aclFields;
+		foreach ($nestedFields as $childName => $nestedProps) {
+			$childNs = str_replace(['__x3A__', ':'], '/', $childName);
+			if (!array_key_exists($childNs, $schemaCache)) {
+				$schemaCache[$childNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($childNs, [ 'propertyName' => '*,field' ]);
+			}
+			$contextFieldList = array_merge(
+	   			$contextFieldList,
+	   			array_map(function ($childCtxFld) use ($childName) {
+					return "{$childName}/{$childCtxFld}";
+				}, self::convertOgcPropertyListToFeatureQueryColsRecurseDBG($schemaCache, $nestedProps, $schemaCache[$childNs], $dbgLoopNr + 1))
+	   		);
+		}
+		DBG::log($contextFieldList, 'array', 'TODO: splited $ogcPropertyList return $contextFieldList');
+		return $contextFieldList;
+		// $acl__getAllFieldNames = function ($listFields) {
+		// 	return array_map(function ($field) {
+		// 		return $field['fieldNamespace'];
+		// 	}, $listFields);
+		// };
+		// $acl__getLocalFieldNames = function ($listFields) {
+		// 	return array_map(function ($field) {
+		// 		return $field['fieldNamespace'];
+		// 	}, array_filter($listFields, function ($field) {
+		// 		return $field['isLocal'];
+		// 	}));
+		// };
+	}
+	public static function convertOgcPropertyListToFeatureQueryCols(&$schemaCache, $ogcPropertyList, $acl) {
+		$contextFieldList = [];
+		$acl__getAllFieldNames = function ($listFields) {
+			return array_map(function ($field) {
+				return $field['fieldNamespace'];
+			}, $listFields);
+		};
+		$acl__getLocalFieldNames = function ($listFields) {
+			return array_map(function ($field) {
+				return $field['fieldNamespace'];
+			}, array_filter($listFields, function ($field) {
+				return $field['isLocal'];
+			}));
+		};
+		// DBG::log($acl->getFields(), 'array', "\$contextFieldList ACL fields");
+		// if (empty($ogcPropertyList)) { // get all local fields
+		// 	// $contextFieldList = $acl__getLocalFieldNames($acl->getFields());
+		// 	$contextFieldList = $acl__getAllFieldNames($acl->getFields());
+		// } else {
+		// 	foreach ($ogcPropertyList as $fieldXPath) {
+		// 		if ('*' === $fieldXPath) {
+		// 			$contextFieldList = array_merge($contextFieldList, $acl__getLocalFieldNames($acl->getFields()));
+		// 		} else if (false === strpos($fieldXPath, '/') && false === strpos($fieldXPath, ':')) {
+		// 			$contextFieldList[] = $fieldXPath;
+		// 		} else if (false === strpos($fieldXPath, '/') && false !== strpos($fieldXPath, ':')) {
+		// 			$contextFieldList[] = $fieldXPath;
+		// 			$fieldNs = str_replace(['__x3A__', ':'], '/', $fieldXPath);
+		// 			$schemaCache[$fieldNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($fieldNs, [ 'propertyName' => '*,field' ]);
+		// 			DBG::log($schemaCache[$fieldNs], 'array', "\$schemaCache[{$fieldNs}]");
+		// 		} else if ('/*' === substr($fieldXPath, -2) && false === strpos(substr($fieldXPath, 0, -2), '/')) {
+		// 			$fieldName = substr($fieldXPath, 0, -2);
+		// 			$contextFieldList[] = $fieldName;
+		// 			$xsdType = $acl->getXsdFieldType($fieldName);
+		// 			if ('ref:' !== substr($xsdType, 0, 4)) throw new Exception("Error Processing Request - field '{$fieldXPath}' type is not ref '/*' is not allowed");
+		// 			$fieldNs = str_replace(['__x3A__', ':'], '/', substr($xsdType, 4));
+		// 			if (!array_key_exists($fieldNs, $schemaCache)) {
+		// 				$schemaCache[$fieldNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($fieldNs, [ 'propertyName' => '*,field' ]);
+		// 				DBG::log($schemaCache[$fieldNs], 'array', "\$schemaCache[{$fieldNs}]");
+		// 			}
+		// 			$fieldPrefix = "{$fieldName}";
+		// 			$contextFieldList = array_merge($contextFieldList, array_map(function ($fieldName) use ($fieldPrefix) {
+		// 				return "{$fieldPrefix}/{$fieldName}";
+		// 			}, $acl__getLocalFieldNames($schemaCache[$fieldNs]['field'])));
+		// 		} else {
+		// 			$fieldName = trim($fieldXPath, '*/');
+		// 			DBG::log(['$fieldXPath'=>$fieldXPath, '$fieldName'=>$fieldName], 'array', "\$contextFieldList TODO");
+		// 			if (false !== strpos($fieldName, '/')) {
+		// 				$xpathParts = explode('/', $fieldName);
+		// 				DBG::log($xpathParts, 'array', "\$xpathParts recurse TODO");
+		// 				$localFieldName = array_shift($xpathParts);
+		// 				DBG::log($localFieldName, 'array', "\$xpathParts recurse TODO \$localFieldName");
+		// 				if ('*' === end($xpathParts)) array_pop($xpathParts);
+		// 				if (!empty($xpathParts)) {
+		// 					foreach ($xpathParts as $part) {
+		// 						if (false !== strpos($part, ':')) {
+		// 							$fieldNs = str_replace(['__x3A__', ':'], '/', $part);
+		// 							if (!array_key_exists($fieldNs, $schemaCache)) {
+		// 								$schemaCache[$fieldNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($fieldNs, [ 'propertyName' => '*,field' ]);
+		// 								DBG::log($schemaCache[$fieldNs], 'array', "\$schemaCache[{$fieldNs}] recurse TODO");
+		// 							}
+		// 						}
+		// 					}
+		// 					$contextFieldList[] = $localFieldName . "/" . implode("/", $xpathParts) . "/*";
+		// 				}
+		// 				// 'default_db__x3A__CRM_PROCES:PROCES/ID',
+		// 				// 'default_db__x3A__CRM_PROCES:PROCES/default_db__x3A__CRM_WSKAZNIK:CRM_WSKAZNIK/*',
+		// 			}
+		// 		}
+		// 	}
+		// }
+		// DBG::log($contextFieldList, 'array', "\$contextFieldList");
+		// DBG::log(array_keys($schemaCache), 'array', "\$schemaCache keys");
+
+		return self::convertOgcPropertyListToFeatureQueryColsRecurseDBG($schemaCache, $ogcPropertyList, $acl);
+
+		return $contextFieldList;
+	}
+
 	// TODO: add $contextAcl and context xpath to check for special perms by contextAcl
 	public static function printXmlFeatureRecurse($xmlWriter, $acl, $item, $tagName, $attrs = [], $showAdvancedAttrs = false, $schemaCache = [], $printedFidLog = []) {
 		$dbgFid = V::get('fid', 0, $attrs);
@@ -85,8 +230,16 @@ class Api_Wfs_GetFeature {
 					// $xmlWriter->writeComment("TODO: ".$acl->getName().".{$itemKey}/{$fldName} ...");
 					$fieldNs = str_replace(['__x3A__', ':'], '/', $fldName); // substr($xsdType, 4));
 					if (!array_key_exists($fieldNs, $schemaCache)) {
-						DBG::log($schemaCache, 'array', "Error Processing Request - field is not ref or missing acl ".$acl->getName().".{$itemKey}/{$fldName}");
-						if(V::get('DBG_XML', '', $_GET))$xmlWriter->writeComment("Error Processing Request - field is not ref or missing acl ".$acl->getName().".{$itemKey}/{$fldName}");
+						// maybe only xlinks - acl not needed
+						$firstItem = reset($item[$fldName]);
+						if (1 === count($firstItem) && !empty($firstItem['xlink'])) {
+							foreach ($item[$fldName] as $childItem) {
+								self::printXmlFeatureRecurse($xmlWriter, $childAcl = null, $childItem, $fldName, [], $showAdvancedAttrs, $schemaCache, $printedFidLog);
+							}
+						} else {
+							DBG::log($schemaCache, 'array', "Error Processing Request - field is not ref or missing acl ".$acl->getName().".{$itemKey}/{$fldName}");
+							if(V::get('DBG_XML', '', $_GET))$xmlWriter->writeComment("Error Processing Request - field is not ref or missing acl ".$acl->getName().".{$itemKey}/{$fldName}");
+						}
 					} else {
 						DBG::log($schemaCache[$fieldNs], 'array', "TODO: xxxxxxx ".$acl->getName().".{$itemKey}/{$fldName}");
 						$childAcl = Core_AclHelper::getAclByNamespace($schemaCache[$fieldNs]['namespace'], false, $schemaCache[$fieldNs]);

+ 3 - 75
SE/se-lib/Api/WfsDataServer.php

@@ -180,82 +180,11 @@ class Api_WfsDataServer extends Api_WfsServerBase {
 		if (!empty($args['primaryKey'])) $searchParams['primaryKey'] = $args['primaryKey'];// featureID
 		if (!empty($args['bbox'])) $searchParams['f_the_geom'] = "BBOX:{$args['bbox']}";
 
-		$contextFieldList = []; // convert $args['filterFields'] to field list
+		DBG::log($args, 'array', "\$args");
 		$schemaCache = array();
+		Lib::loadClass('Api_Wfs_GetFeature');
 		try {
-			$acl__getAllFieldNames = function ($listFields) {
-				return array_map(function ($field) {
-					return $field['fieldNamespace'];
-				}, $listFields);
-			};
-			$acl__getLocalFieldNames = function ($listFields) {
-				return array_map(function ($field) {
-					return $field['fieldNamespace'];
-				}, array_filter($listFields, function ($field) {
-					return $field['isLocal'];
-				}));
-			};
-			DBG::log($args, 'array', "\$args");
-			DBG::log($acl->getFields(), 'array', "\$contextFieldList ACL fields");
-			if (empty($args['filterFields'])) { // get all local fields
-				// $contextFieldList = $acl__getLocalFieldNames($acl->getFields());
-				$contextFieldList = $acl__getAllFieldNames($acl->getFields());
-			} else {
-				foreach ($args['filterFields'] as $fieldXPath) {
-					if ('*' === $fieldXPath) {
-						$contextFieldList = array_merge($contextFieldList, $acl__getLocalFieldNames($acl->getFields()));
-					} else if (false === strpos($fieldXPath, '/') && false === strpos($fieldXPath, ':')) {
-						$contextFieldList[] = $fieldXPath;
-					} else if (false === strpos($fieldXPath, '/') && false !== strpos($fieldXPath, ':')) {
-						$contextFieldList[] = $fieldXPath;
-						$fieldNs = str_replace(['__x3A__', ':'], '/', $fieldXPath);
-						$schemaCache[$fieldNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($fieldNs, [ 'propertyName' => '*,field' ]);
-						DBG::log($schemaCache[$fieldNs], 'array', "\$schemaCache[{$fieldNs}]");
-					} else if ('/*' === substr($fieldXPath, -2) && false === strpos(substr($fieldXPath, 0, -2), '/')) {
-						$fieldName = substr($fieldXPath, 0, -2);
-						$contextFieldList[] = $fieldName;
-						$xsdType = $acl->getXsdFieldType($fieldName);
-						if ('ref:' !== substr($xsdType, 0, 4)) throw new Exception("Error Processing Request - field '{$fieldXPath}' type is not ref '/*' is not allowed");
-						$fieldNs = str_replace(['__x3A__', ':'], '/', substr($xsdType, 4));
-						if (!array_key_exists($fieldNs, $schemaCache)) {
-							$schemaCache[$fieldNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($fieldNs, [ 'propertyName' => '*,field' ]);
-							DBG::log($schemaCache[$fieldNs], 'array', "\$schemaCache[{$fieldNs}]");
-						}
-						$fieldPrefix = "{$fieldName}";
-						$contextFieldList = array_merge($contextFieldList, array_map(function ($fieldName) use ($fieldPrefix) {
-							return "{$fieldPrefix}/{$fieldName}";
-						}, $acl__getLocalFieldNames($schemaCache[$fieldNs]['field'])));
-					} else {
-						$fieldName = trim($fieldXPath, '*/');
-						DBG::log(['$fieldXPath'=>$fieldXPath, '$fieldName'=>$fieldName], 'array', "\$contextFieldList TODO");
-						if (false !== strpos($fieldName, '/')) {
-							$xpathParts = explode('/', $fieldName);
-							DBG::log($xpathParts, 'array', "\$xpathParts recurse TODO");
-							$localFieldName = array_shift($xpathParts);
-							DBG::log($localFieldName, 'array', "\$xpathParts recurse TODO \$localFieldName");
-							if ('*' === end($xpathParts)) array_pop($xpathParts);
-							if (!empty($xpathParts)) {
-								foreach ($xpathParts as $part) {
-									if (false !== strpos($part, ':')) {
-										$fieldNs = str_replace(['__x3A__', ':'], '/', $part);
-										if (!array_key_exists($fieldNs, $schemaCache)) {
-											$schemaCache[$fieldNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($fieldNs, [ 'propertyName' => '*,field' ]);
-											DBG::log($schemaCache[$fieldNs], 'array', "\$schemaCache[{$fieldNs}] recurse TODO");
-										}
-									}
-								}
-								$contextFieldList[] = $localFieldName . "/" . implode("/", $xpathParts) . "/*";
-							}
-							// 'default_db__x3A__CRM_PROCES:PROCES/ID',
-							// 'default_db__x3A__CRM_PROCES:PROCES/default_db__x3A__CRM_WSKAZNIK:CRM_WSKAZNIK/*',
-						}
-					}
-				}
-			}
-			DBG::log($contextFieldList, 'array', "\$contextFieldList");
-			DBG::log(array_keys($schemaCache), 'array', "\$schemaCache keys");
-
-			$searchParams['cols'] = $contextFieldList;
+			$searchParams['cols'] = Api_Wfs_GetFeature::convertOgcPropertyListToFeatureQueryCols($schemaCache, $args['filterFields'], $acl); // convert $args['filterFields'] to field list
 		} catch (Exception $e) {
 			DBG::log($e);
 			throw $e;
@@ -305,7 +234,6 @@ class Api_WfsDataServer extends Api_WfsServerBase {
 			if (!empty($geomFld)) DBG::log(['msg'=>"item[{$itemKey}] ({$geomFld})isEmpty(".empty($item[$geomFld])."):", '$item['.$geomFld.']'=>$item[$geomFld]]);
 			DBG::log([ 'msg'=>">>> loop({$itemKey})", '$item'=>$item ]);
 			$xmlWriter->startElement('gml:featureMember');
-			Lib::loadClass('Api_Wfs_GetFeature');
 			Api_Wfs_GetFeature::printXmlFeatureRecurse($xmlWriter, $acl, $item, $tagName = "{$wfsNs}:{$type}", array_merge(
 				[
 					'fid' => "{$type}.{$itemKey}",