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); if ($dbgFid) $printedFidLog[] = $dbgFid; if(V::get('DBG_XML', '', $_GET))$xmlWriter->writeComment("DBG: printXmlFeatureRecurse... '{$tagName}'" . ( $dbgFid ? " fid='{$dbgFid}'" : "" )); // TODO: DBG DBG::log($acl, 'array', "DBG: printXmlFeatureRecurse( ... {$tagName}, \$acl)" . ( $dbgFid ? " fid='{$dbgFid}'" : "" )); DBG::log($item, 'array', "DBG: printXmlFeatureRecurse( ... {$tagName}, \$item)" . ( $dbgFid ? " fid='{$dbgFid}'" : "" )); DBG::log([$attrs, $showAdvancedAttrs, array_keys($schemaCache), $printedFidLog], 'array', "DBG: printXmlFeatureRecurse( ... {$tagName}, \$attrs, \$showAdvancedAttrs, keys(\$schemaCache), \$printedFidLog)"); // $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); // } else if (1 == count($item[$fldName]) && !empty($item[$fldName][0]['xlink'])) { // $xmlWriter->writeComment("TODO: xlinks for '{$fldName}'"); // TODO: DBG DBG::log($item[$fldName], 'array', "TODO: xlinks for '{$tagName}'"); // $xlink = $item[$fldName][0]['xlink']; // $xlinkParts = explode(':', $xlink); // if (2 != count($xlinkParts)) throw new Exception("Error Processing Request - wrong xlink format for ".$acl->getName().".{$itemKey}/{$fldName}"); // $xlinkParts[0] = Api_WfsNs::getNsUri($xlinkParts[0]); // $xlink = implode('#', $xlinkParts); $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).")"); foreach ($fldList as $idZasob => $fldName) { 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'])) { 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]); $childName = $schemaCache[$fieldNs]['name']; foreach ($item[$fldName] as $childItem) { $childPK = V::get($childAcl->getPrimaryKeyField(), '', $childItem); self::printXmlFeatureRecurse($xmlWriter, $childAcl, $childItem, $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(); } }