| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- <?php
- Lib::loadClass('Api_WfsGeomTypeConverter');
- Lib::loadClass('Core_AclHelper');
- class Api_Wfs_GetFeature {
- public static function convertOgcPropertyListToFeatureQueryCols(&$schemaCache, $ogcPropertyList, $acl) {
- return self::convertOgcPropsRecurse($schemaCache, $ogcPropertyList, $acl);
- }
- public static function convertOgcPropsRecurse(&$schemaCache, $ogcPropertyList, $aclOrSchema, $dbgLoopNr = 0) {
- if ($dbgLoopNr > 10) {
- DBG::log($ogcPropertyList, 'array', 'convertOgcPropsRecurse: LOOP LIMIT 10! - return []');
- 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)) {
- $ogcPropertyList = array_values($acl->getFieldListByIdZasob());
- $ogcPropertyList = array_filter($ogcPropertyList, function ($fieldName) use ($acl) {
- return $acl->canReadField($fieldName);
- });
- }
- $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)) {
- if (array_key_exists('*', $nestedFields)) {
- $nestedParts = $nestedFields['*'];
- unset($nestedFields['*']);
- DBG::log($nestedParts, 'array', "convertOgcPropsRecurse: TODO: '*' in \$nestedFields - \$nestedParts");
- $canReadRefs = array_values($acl->getFieldListByIdZasob());
- $canReadRefs = array_filter($canReadRefs, function ($fieldName) use ($acl) {
- return (false !== strpos($fieldName, ":") && $acl->canReadField($fieldName));
- });
- foreach ($canReadRefs as $refField) {
- foreach ($nestedParts as $nestedPart) {
- $nestedFields[ $refField ][] = $nestedPart;
- }
- }
- }
- }
- if (!empty($nestedFields)) {
- $aclFields = array_unique(array_merge($aclFields, array_keys($nestedFields)));
- }
- if (in_array('*', $aclFields)) {
- $aclFields = array_filter($aclFields, function ($fieldName) { return ( '*' !== $fieldName); });
- $allAclFields = array_values($acl->getFieldListByIdZasob());
- $allAclFields = array_filter($allAclFields, function ($fieldName) use ($acl) {
- return $acl->canReadField($fieldName);
- });
- if ($allAclFields) $aclFields = array_unique(array_merge($aclFields, $allAclFields));
- }
- DBG::log([$aclFields, $nestedFields], 'array', 'convertOgcPropsRecurse: splited to acl fields and nested fields');
- foreach ($aclFields as $fieldName) {
- if (!$acl->canReadField($fieldName)) throw new Exception("Access Denied to read field '{$fieldName}' from '" . $acl->getNamespace() . "'");
- }
- foreach ($aclFields as $fieldName) {
- if (false !== strpos($fieldName, ':')) {
- $childNs = str_replace(['__x3A__', ':'], '/', $fieldName);
- $schemaCache[$childNs] = SchemaFactory::loadDefaultObject('SystemObject')->getItem($childNs, [ 'propertyName' => '*,field' ]);
- }
- }
- $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::convertOgcPropsRecurse($schemaCache, $nestedProps, $schemaCache[$childNs], $dbgLoopNr + 1))
- );
- }
- DBG::log($contextFieldList, 'array', 'convertOgcPropsRecurse: return $contextFieldList');
- return $contextFieldList;
- }
- // TODO: add $contextAcl and context xpath to check for special perms by contextAcl
- public static function printXmlFeatureRecurse($xmlWriter, $acl, $item, $showFields, $tagName, $attrs = [], $showAdvancedAttrs = false, $schemaCache = [], $printedFidLog = []) {
- $dbgFid = V::get('fid', 0, $attrs);
- if(V::get('DBG_XML', '', $_GET))$xmlWriter->writeComment("DBG: print Xml Feature Recurse... '{$tagName}'" . ( $dbgFid ? " fid='{$dbgFid}'" : "" )); // TODO: DBG
- DBG::log($acl, 'array', "DBG: print Xml Feature Recurse( ... {$tagName}, \$acl)" . ( $dbgFid ? " fid='{$dbgFid}'" : "" ) . " \$acl");
- DBG::log($item, 'array', "DBG: print Xml Feature Recurse( ... {$tagName}, \$item)" . ( $dbgFid ? " fid='{$dbgFid}'" : "" ) . " \$item");
- DBG::log($showFields, 'array', "DBG: print Xml Feature Recurse( ... {$tagName}, \$item)" . ( $dbgFid ? " fid='{$dbgFid}'" : "" ) . " \$showFields");
- DBG::log([$attrs, $showAdvancedAttrs, array_keys($schemaCache), $printedFidLog], 'array', "DBG: print Xml Feature Recurse( ... {$tagName}, \$attrs, \$showAdvancedAttrs, keys(\$schemaCache), \$printedFidLog)");
- if ($dbgFid) {
- if (in_array($dbgFid, $printedFidLog)) {
- DBG::log("TODO: in_array({$dbgFid}, \$printedFidLog)");
- }
- }
- if ($dbgFid) $printedFidLog[] = $dbgFid;
- // $rootWfsNs = 'p5';
- list($itemPrefix, $localName) = explode(':', $tagName);
- if (1 === count($item) && !empty($item['xlink'])) {
- // @example 'xlink' => 'https://biuro.biall-net.pl/wfs/default_db/CRM_PROCES#PROCES.857'
- $xlink = $item['xlink'];
- list($xlinkUrl, $xlinkFid) = explode('#', $xlink);
- DBG::log($item[$fldName], 'array', "xlinks for '{$tagName}'");
- $xmlWriter->startElement($tagName);
- foreach ($attrs as $name => $value) {
- $xmlWriter->writeAttribute($name, $value);
- }
- if ($showAdvancedAttrs && !$acl->canReadObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_read", "false");
- }
- if ($showAdvancedAttrs && $acl->canWriteObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_write", "true");
- }
- $xmlWriter->writeAttribute('xlink:href', $xlink);
- $xmlWriter->endElement();// {$itemPrefix}:{$fldName}
- return;
- }
- $xmlWriter->startElement($tagName);
- foreach ($attrs as $name => $value) {
- $xmlWriter->writeAttribute($name, $value);
- }
- $fldList = $acl->getRealFieldListByIdZasob();
- $geomFld = null;
- foreach ($fldList as $fldName) {
- if ($acl->isGeomField($fldName)) {
- $geomFld = $fldName;
- }
- }
- DBG::log($fldList, 'array', ">>> loop start fields(".count($fldList).")");
- // DBG::log($showFields, 'array', "DBG: \$showLocalFields \$showFields 0");
- $showLocalFields = array_filter($showFields, function ($showFieldName) {
- return (false === strpos($showFieldName, "/"));
- });
- // DBG::log($showLocalFields, 'array', "DBG: \$showLocalFields");
- $fldList = array_filter($fldList, function ($fieldName) use ($showLocalFields) {
- return (in_array($fieldName, $showLocalFields));
- });
- DBG::log($fldList, 'array', ">>> loop start filtered fields(".count($fldList).")");
- foreach ($fldList as $idZasob => $fldName) {
- // TODO: show only fields from $showFields
- DBG::log(">>> loop {$idZasob} => {$fldName}...");
- $fldType = $acl->getXsdFieldType($fldName);
- DBG::log(">>> loop '{$fldName}' xsdType: '{$fldType}'");
- if (!$acl->canReadObjectField($fldName, (object)$item)) if(V::get('DBG_XML', '', $_GET))$xmlWriter->writeComment("DBG: skip - !canReadObjectField('{$fldName}')"); // TODO: DBG
- if (!$acl->canReadObjectField($fldName, (object)$item)) continue;
- DBG::log(">>> loop '{$fldName}' can read...");
- if ($geomFld != null && $fldName == $geomFld) {
- $xmlWriter->startElement("{$itemPrefix}:{$fldName}");
- if ($showAdvancedAttrs && !$acl->canReadObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_read", "false");
- }
- if ($showAdvancedAttrs && $acl->canWriteObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_write", "true");
- }
- (new Api_WfsGeomTypeConverter())->createGmlFromWkt_xmlWriter($item[$fldName], $xmlWriter);
- $xmlWriter->endElement();// {$itemPrefix}:{$fldName}
- } else if (is_array($item[$fldName])) {// TODO: by struct - REF field
- DBG::log($item[$fldName], 'array', ">>> loop({$itemKey}) REF item[{$itemKey}][{$fldName}]");
- if (empty($item[$fldName])) { // SKIP empty fields
- if(V::get('DBG_XML', '', $_GET))$xmlWriter->writeComment("DBG: skip empty field '{$fldName}'"); // TODO: DBG
- // $xmlWriter->h($fldName);
- } else {
- if(V::get('DBG_XML', '', $_GET))$xmlWriter->writeComment("DBG: TODO: array field... '{$fldName}'"); // TODO: DBG
- // $xmlWriter->writeComment("TODO: ".$acl->getName().".{$itemKey}/{$fldName} ...");
- $fieldNs = str_replace(['__x3A__', ':'], '/', $fldName); // substr($xsdType, 4));
- if (!array_key_exists($fieldNs, $schemaCache)) {
- // maybe only xlinks - acl not needed
- $firstItem = reset($item[$fldName]);
- if (1 === count($firstItem) && !empty($firstItem['xlink'])) { // TODO: $schemaCache[$fieldNs] must exists for xlinks - xlmns is required
- foreach ($item[$fldName] as $childItem) {
- self::printXmlFeatureRecurse($xmlWriter, $childAcl = null, $childItem, $showChildFields = [], $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', "fetch child acl ".$acl->getName().".{$itemKey}/{$fldName}");
- $childAcl = Core_AclHelper::getAclByNamespace($schemaCache[$fieldNs]['namespace'], false, $schemaCache[$fieldNs]);
- $childName = $schemaCache[$fieldNs]['name'];
- foreach ($item[$fldName] as $childItem) {
- // DBG::log($showFields, 'array', "DBG: fld({$fldName}) \$showFields 0");
- $showChildFields = array_filter($showFields, function ($showFieldName) use ($fldName) {
- return ("{$fldName}/" === substr("{$showFieldName}", 0, strlen($fldName) + 1));
- });
- // DBG::log($showChildFields, 'array', "DBG: fld({$fldName}) \$showChildFields 1");
- $showChildFields = array_map(function ($showFieldName) use ($fldName) {
- return substr($showFieldName, strlen($fldName) + 1);
- }, $showChildFields);
- // DBG::log($showChildFields, 'array', "DBG: fld({$fldName}) \$showChildFields 2");
- $childPK = V::get($childAcl->getPrimaryKeyField(), '', $childItem);
- self::printXmlFeatureRecurse($xmlWriter, $childAcl, $childItem, $showChildFields, $fldName, ($childPK) ? [ 'fid' => "{$childName}.{$childPK}" ] : [], $showAdvancedAttrs, $schemaCache, $printedFidLog);
- }
- // foreach ($item[$fldName] as $refItem) {
- // DBG::log($refItem, 'array', "\$refItem fld({$fldName})");
- // if (1 == count($refItem) && !empty($refItem['xlink'])) {
- // $xmlWriter->startElement($schemaCache[$fieldNs]['typeName']);
- // $xmlWriter->writeAttribute("xlink:href", $refItem['xlink']);
- // $xmlWriter->endElement();
- // } else {
- // $xmlWriter->writeComment("DBG: array field ref ... '{$fldName}'"); // TODO: DBG
- // $xmlWriter->startElement($schemaCache[$fieldNs]['typeName']);
- // foreach ($schemaCache[$fieldNs]['field'] as $field) {
- // if (array_key_exists($field['fieldNamespace'], $refItem)) {
- // $xmlWriter->writeComment("REF field ({$field['fieldNamespace']}) value({$refItem[$field['fieldNamespace']]}) TODO: get xsdType - TODO: recurse");
- // DBG::log($refItem[$field['fieldNamespace']], 'array', "REF field ({$field['fieldNamespace']}) TODO: get xsdType - TODO: recurse");
- // if (false !== strpos($field['fieldNamespace'], ':')) { // is ref - TODO: better check by xsdType
- // $xmlWriter->startElement($field['fieldNamespace']);
- // $xmlWriter->writeComment("TODO: recurse ...");
- // // $xmlWriter->text($refItem[$field['fieldNamespace']]);
- // $xmlWriter->endElement();
- // } else {
- // $xmlWriter->startElement("{$schemaCache[$fieldNs]['nsPrefix']}:{$field['fieldNamespace']}");
- // $xmlWriter->text($refItem[$field['fieldNamespace']]);
- // $xmlWriter->endElement();
- // }
- // }
- // }
- // $xmlWriter->endElement();
- // }
- // }
- }
- }
- } else if ('xsd:base64Binary' === $acl->getXsdFieldType($fldName)) {
- if (empty($item[$fldName]) && '0' !== $item[$fldName]) continue;
- $xmlWriter->startElement("{$itemPrefix}:{$fldName}");
- if ($showAdvancedAttrs && !$acl->canReadObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_read", "false");
- }
- if ($showAdvancedAttrs && $acl->canWriteObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_write", "true");
- }
- $xmlWriter->text(base64_encode($item[$fldName]));
- $xmlWriter->endElement();// {$itemPrefix}:{$fldName}
- } else {
- $value = str_replace('&', '&', $item[$fldName]);
- if (empty($value) && '0' !== $value) {
- continue;
- } else {
- $xmlWriter->startElement("{$itemPrefix}:{$fldName}");
- if ($showAdvancedAttrs && !$acl->canReadObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_read", "false");
- }
- if ($showAdvancedAttrs && $acl->canWriteObjectField($fldName, (object)$item)) {
- $xmlWriter->writeAttribute("p5:allow_write", "true");
- }
- $xmlWriter->text($value);
- $xmlWriter->endElement();// {$itemPrefix}:{$fldName}
- }
- }
- }
- $xmlWriter->endElement();
- }
- }
|