_usrAcl = $usrAcl; $this->_typeConverter = new Api_WfsGeomTypeConverter(); $this->_apiBaseUri = ''; } public function setBaseUri($uri) { $this->_apiBaseUri = $uri; } public function getBaseUri() { return $this->_apiBaseUri; } public function getBaseNamespaceUri() { $baseNsUri = $this->_apiBaseUri; $protocolType = ''; if (!empty($baseNsUri)) { if ('https://' == substr($baseNsUri, 0, 8)) { $protocolType = 'https'; $baseNsUri = substr($baseNsUri, 8); } else if ('http://' == substr($baseNsUri, 0, 7)) { $protocolType = 'http'; $baseNsUri = substr($baseNsUri, 6); } } if (!empty($baseNsUri)) { if (false !== ($pos = strpos($baseNsUri, '/'))) { $baseNsUri = substr($baseNsUri, 0, $pos); } } return "{$protocolType}://{$baseNsUri}/wfs"; } public function isAllowedFeatureType($nsPrefix, $type) { if ('p5_' != substr($nsPrefix, 0, 3)) return false; if ('p5_default_db' == $nsPrefix) { $typeName = "p5_default_db:{$type}"; try { $acl = $this->getAclFromTypeName($typeName); } catch (Exception $e) { return false; } if ($acl) { return true; } } else if ('p5_objects' == $nsPrefix && 'File' == $type) { return true; } return false; } /** * @param string $typeName - 'p5_default_db:TEST_PERMS' */ public function getAclFromTypeName($typeName) { $typeEx = explode(':', $typeName); if (2 != count($typeEx)) throw new Api_WfsException("Could not get acl for '{$typeName}' - syntax error"); if ('p5_' != substr($typeEx[0], 0, 3)) throw new Api_WfsException("Could not get acl for '{$typeName}' - prefix error"); $sourceName = substr($typeEx[0], 3); $objName = $typeEx[1]; $acl = $this->_usrAcl->getObjectAcl($sourceName, $objName); if (!$acl) throw new Api_WfsException("Could not get acl for '{$typeName}'"); $forceTblAclInit = 0;//('1' == V::get('_force', '', $_GET)); $acl->init($forceTblAclInit); return $acl; } public function _getCapabilities($wfsServerUrl, $serviceTitle, $serviceDescription) { echo ''; ?> _getXmlNamespaceList(); ?> _getXmlSchemaLocation(); ?> version="1.0.0"> WFS <?php echo $serviceTitle; ?> WFS, WMS NONE NONE _printGetCapabilitiesXml($wfsServerUrl); ?> _printDescribeFeatureTypeXml($wfsServerUrl); ?> _printGetFeatureXml($wfsServerUrl); ?> _printTransactionXml($wfsServerUrl); ?> _printLockFeatureXml($wfsServerUrl); ?> _printGetFeatureWithLockXml($wfsServerUrl); ?> _printFeatureTypeListXml(); ?> abs abs_2 abs_3 abs_4 acos AddCoverages Aggregate Area area2 AreaGrid asin atan atan2 BarnesSurface between boundary boundaryDimension Bounds buffer BufferFeatureCollection bufferWithSegments Categorize ceil Centroid classify Clip CollectGeometries Collection_Average Collection_Bounds Collection_Count Collection_Max Collection_Median Collection_Min Collection_Sum Collection_Unique Concatenate contains Contour convert convexHull cos Count CropCoverage crosses dateFormat dateParse difference dimension disjoint disjoint3D distance distance3D double2bool endAngle endPoint env envelope EqualInterval equalsExact equalsExactTolerance equalTo exp exteriorRing Feature floor geometryType geomFromWKT geomLength getGeometryN getX getY getz greaterEqualThan greaterThan Grid Heatmap id IEEEremainder if_then_else in10 in2 in3 in4 in5 in6 in7 in8 in9 InclusionFeatureCollection int2bbool int2ddouble interiorPoint interiorRingN Interpolate intersection IntersectionFeatureCollection intersects intersects3D isClosed isCoverage isEmpty isLike isNull isometric isRing isSimple isValid isWithinDistance isWithinDistance3D Jenks length lessEqualThan lessThan list log LRSGeocode LRSMeasure LRSSegment max max_2 max_3 max_4 min min_2 min_3 min_4 mincircle minimumdiameter minrectangle modulo MultiplyCoverages Nearest not notEqualTo numberFormat numberFormat2 numGeometries numInteriorRing numPoints octagonalenvelope offset overlaps parameter parseBoolean parseDouble parseInt parseLong pi PointBuffers pointN PointStacker PolygonExtraction pow property PropertyExists Quantile Query random RangeLookup RasterAsPointCollection RasterZonalStatistics Recode RectangularClip relate relatePattern Reproject rint round round_2 roundDouble ScaleCoverage sdo_nn setCRS Simplify sin Snap sqrt StandardDeviation startAngle startPoint strCapitalize strConcat strEndsWith strEqualsIgnoreCase strIndexOf strLastIndexOf strLength strMatches strPosition strReplace strStartsWith strSubstring strSubstringStart strToLowerCase strToUpperCase strTrim strTrim2 StyleCoverage symDifference tan toDegrees toRadians touches toWKT Transform union UnionFeatureCollection Unique UniqueInterval VectorToRaster VectorZonalStatistics vertices within getBaseNamespaceUri(); $listNs = array(); $listNs[] = 'xmlns:p5_default_db="' . $baseNsUri . '/default_db"'; $listNs[] = 'xmlns:p5_objects="' . $baseNsUri . '/objects"'; return implode("\n", $listNs); } public function _getXmlNamespaceList__OLD() { $baseNsUri = $this->getBaseNamespaceUri(); $namespaceList = $this->_getSourceNsList(); $namespaceListOut = array(); foreach ($namespaceList as $nsObj) { $ns = "p5_{$nsObj[0]}_{$nsObj[1]}"; $uri = "{$baseNsUri}/{$nsObj[0]}/{$nsObj[1]}"; $namespaceListOut[] = 'xmlns:' . $ns . '="' . $uri . '"'; } return implode(' ', $namespaceListOut); } public function _getSourceNsList() { $usrObjList = array(); $tblsAcl = $this->_usrAcl->getTablesAcl(); foreach ($tblsAcl as $tblAcl) { $dataSourceName = 'default_db';// TODO: getSourceName $tblName = $tblAcl->getName(); $usrObjList[] = array($dataSourceName, $tblName); } $usrObjList[] = array('objects', 'File'); return $usrObjList; } public function _printGetCapabilitiesXml($wfsServerUrl) { ?> _getTableAclList(); foreach ($tblsAcl as $tblAcl) { $dataSourceName = 'default_db';// TODO: getSourceName $tblName = $tblAcl->getName(); $usrObjList[] = array($dataSourceName, $tblName); $featureType = array(); $featureType['ns'] = "p5_{$dataSourceName}"; $featureType['Title'] = $tblAcl->getRawLabel(); $featureType['Abstract'] = $tblAcl->getRawOpis(); $featureType['Keywords'] = array(); $featureType['Keywords'][] = $tblAcl->getID(); $featureType['Keywords'][] = $tblName; $featureType['Keywords'][] = $tblAcl->getRawLabel(); $featureType['Keywords'] = implode(", ", $featureType['Keywords']); $featureType['SRS'] = "EPSG:4326"; $featureType['LatLongBoundingBox'] = array();// TODO: feature LatLongBoundingBox $featureType['LatLongBoundingBox']['minx'] = "8.12328509871721"; $featureType['LatLongBoundingBox']['miny'] = "38.8575126897477"; $featureType['LatLongBoundingBox']['maxx'] = "9.838674658246807"; $featureType['LatLongBoundingBox']['maxy'] = "41.31378404137082"; $featureTypes[$tblName] = $featureType; } {// add p5_objects:File Lib::loadClass('FileStorage'); $featureType = array(); $featureType['ns'] = "p5_objects"; $featureType['Title'] = "Pliki"; $featureType['Abstract'] = "Pliki"; $featureType['Keywords'] = "Pliki"; $featureType['SRS'] = "EPSG:4326"; // $featureType['LatLongBoundingBox'] = array();// TODO: feature LatLongBoundingBox // $featureType['LatLongBoundingBox']['minx'] = "8.12328509871721"; // $featureType['LatLongBoundingBox']['miny'] = "38.8575126897477"; // $featureType['LatLongBoundingBox']['maxx'] = "9.838674658246807"; // $featureType['LatLongBoundingBox']['maxy'] = "41.31378404137082"; $featureTypes['File'] = $featureType; } /* ppr06:AMBITIPAESAGGIO AMBITIPAESAGGIO features, AMBITIPAESAGGIO EPSG:4326 */ $featureTypesXml = ''; foreach ($featureTypes as $tblName => $feature) { $featureTypesXml .= " " . '' . "\n"; $featureTypesXml .= " " . '' . "{$feature['ns']}:{$tblName}" . '' . "\n"; $featureTypesXml .= " " . '' . "{$feature['Title']}" . '' . "\n"; if (!empty($feature['Abstract'])) { $featureTypesXml .= " " . '' . "{$feature['Abstract']}" . '' . "\n"; } else { $featureTypesXml .= " " . '' . "\n"; } if (!empty($feature['Keywords'])) { $featureTypesXml .= " " . '' . "{$feature['Keywords']}" . '' . "\n"; } else { $featureTypesXml .= " " . '' . "\n"; } $featureTypesXml .= " " . '' . "{$feature['SRS']}" . '' . "\n"; if (!empty($feature['LatLongBoundingBox'])) { $latLongBoundingBoxOut = array(); $latLongBoundingBoxOut[] = 'minx="' . $feature['LatLongBoundingBox']['minx'] . '"'; $latLongBoundingBoxOut[] = 'miny="' . $feature['LatLongBoundingBox']['miny'] . '"'; $latLongBoundingBoxOut[] = 'maxx="' . $feature['LatLongBoundingBox']['maxx'] . '"'; $latLongBoundingBoxOut[] = 'maxy="' . $feature['LatLongBoundingBox']['maxy'] . '"'; $featureTypesXml .= " " . '' . "\n"; } $featureTypesXml .= " " . '' . "\n"; } echo $featureTypesXml; } public function _parseTransactionXmlStruct($requestXml, $requestXmlTags) { $DBG = (V::get('DBG_XML', '', $_GET) > 0);// TODO: Profiler $rootTagName = V::get('tag', '', $requestXmlTags[0]); if ('Transaction' != $rootTagName) { throw new Api_WfsException("Parse Request XML Error - Missing Transaction as root xml tag", __LINE__, null, 'TransactionParseError', 'request'); } // 1. convert request: wfs.transaction.convert-wfs-request.xsl // 2. validate converted request: wfs.transaction-converted-request.xsd // 3. execute request in data source // ? acl check? $usedSourceNsList = array(); $sourceNsList = $this->_getSourceNsList(); //$sourceNsList = array(); //foreach ($requestXmlTags[0]['attributes'] as $attrName => $attrValue) { // if ('xmlns:p5_' == substr($attrName, 0, 9)) { // $sourceNsList[substr($attrName, 6)] = $attrValue; // } //} {// get used typeNames $usedTypeNames = array(); // foreach ($requestXmlTags as $tag) { if ('Update' == $tag['tag'] && 'open' == $tag['type']) { $typeName = $tag['attributes']['typeName']; foreach ($sourceNsList as $nsInd => $ns) { if ("p5_{$ns[0]}:{$ns[1]}" == $typeName) { $usedSourceNsList[$nsInd] = $ns; } } } } // TODO: check: // $lastTagName = ''; foreach ($requestXmlTags as $tag) { if ('Insert' == $lastTagName) { $typeName = $tag['tag']; foreach ($sourceNsList as $nsInd => $ns) { if ("{$ns[1]}" == $typeName) { $usedSourceNsList[$nsInd] = $ns; } } } $lastTagName = $tag['tag']; } // foreach ($requestXmlTags as $tag) { if ('Delete' == $tag['tag'] && 'open' == $tag['type']) { $typeName = $tag['attributes']['typeName']; foreach ($sourceNsList as $nsInd => $ns) { if ("p5_{$ns[0]}:{$ns[1]}" == $typeName) { $usedSourceNsList[$nsInd] = $ns; } } } } } if (empty($usedSourceNsList)) { throw new Api_WfsException("Parse Request XML Error - Empty source NS list", __LINE__, null, 'TransactionParseError', 'request'); } $convertedTransaction = $this->_convertTransactionXml($requestXml, $usedSourceNsList); if($DBG){echo 'L.' . __LINE__ . ' $convertedTransaction:';print_r($convertedTransaction);echo "\n";} if (empty($convertedTransaction)) { throw new Api_WfsException("Parse Request XML Error - Empty transaction", __LINE__, null, 'TransactionParseError', 'request'); } if (!$this->_validateConvertedTransactionXml($convertedTransaction, $usedSourceNsList)) { // // // 41 // 3 // // $transXml = @simplexml_load_string($convertedTransaction); foreach ($transXml->children() as $funcXml) { $funcName = substr($funcXml->getName(), 0, 6);// Insert... , Update... , Delete... if (empty($funcXml['typeName'][0])) throw new Api_WfsException("Missing typeName for function '{$funcName}'", __LINE__, null, 'MissingTypeName', 'request'); $typeName = $funcXml['typeName'][0]; $acl = $this->getAclFromTypeName("p5_default_db:{$typeName}"); $primaryKey = $acl->getPrimaryKeyField(); $pkObject = null; foreach ($funcXml->children() as $fieldXml) { if ($primaryKey == $fieldXml->getName()) $pkObject = $fieldXml[0]; } if ('Insert' == $funcName && $pkObject) $funcName = 'Update'; if ('Update' == $funcName) {// check perm W - skip $primaryKey if (!$pkObject) throw new Api_WfsException("Missing primary key ({$primaryKey}) for action Update", __LINE__, null, 'MissingPrimaryKey', 'request'); $toUpdateFields = array(); foreach ($funcXml->children() as $fieldXml) { if ($primaryKey == $fieldXml->getName()) continue;// skip primary key $toUpdateFields[] = $fieldXml->getName(); } if (empty($toUpdateFields)) throw new Api_WfsException("Missing fields to update", __LINE__, null, 'MissingFieldToUpdate', 'request'); $oldObject = $acl->getItem($pkObject); if (!$oldObject) throw new Api_WfsException("Object '{$typeName}.{$pkObject}' not exists", __LINE__, null, 'ObjectNotExists', 'request'); if (!$acl->canWriteRecord($oldObject) && !$acl->hasPermSuperWrite()) { throw new Api_WfsException("Access Denied to Update object '{$typeName}.{$pkObject}'", __LINE__, null, 'MissingObjectPermUpdate', 'request'); } foreach ($toUpdateFields as $fieldName) { $aclIdFld = $acl->getFieldIdByName($fieldName); if (!$acl->isAllowed($aclIdFld, 'W', $oldObject)) { throw new Api_WfsException("Access Denied to Update field '{$fieldName}' in object '{$typeName}.{$pkObject}'", __LINE__, null, 'MissingFieldPermWrite', 'request'); } } } else if ('Insert' == $funcName) {// check perm C foreach ($funcXml->children() as $fieldXml) { $fieldName = $fieldXml->getName(); $aclIdFld = $acl->getFieldIdByName($fieldXml->getName()); if (!$acl->isAllowed($aclIdFld, 'C')) { throw new Api_WfsException("Access Denied to Create field '{$fieldName}' in object '{$typeName}.{$pkObject}'", __LINE__, null, 'MissingFieldPermCreate', 'request'); } } } else { // TODO: Delete, ... ? } } throw new Exception("Parse Request xml error #" . __LINE__ . ": schema validation failed"); } $parserXml = xml_parser_create(); xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0); xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1); if (0 == xml_parse_into_struct($parserXml, $convertedTransaction, $tags)) { throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction failed"); } xml_parser_free($parserXml); if (empty($tags)) { throw new Exception("Parse Request xml error #" . __LINE__ . ": parse converted transaction returns empty structure"); } // [{"tag":"Transaction","type":"open","level":1,"attributes":{"version":"1.0.0","service":"WFS"}}, // {"tag":"Update","type":"open","level":2,"attributes": // {"typeName":"p5_default_db_13051:TEST_PERMS","featureId":"TEST_PERMS.25"}}, // {"tag":"PARENT_ID","type":"complete","level":3,"value":"0"}, // {"tag":"Update","type":"close","level":2}, // {"tag":"Transaction","type":"close","level":1}] if($DBG){echo "\ntags L." . __LINE__ . ":\n"; print_r($tags);echo "\n";} $actionTag = null; $prevTagName = ''; $theGeomField = 'the_geom';// TODO: get the geom field name from acl $itemPatchs = array(); foreach ($tags as $tag) { switch (substr($tag['tag'], 0, 6)) { case 'Transa': continue; break;// Transaction case 'Update': case 'Insert': case 'Delete': case 'Native': if ('open' == $tag['type'] // Insert, Update || 'complete' == $tag['type'] // Delete ) { if($DBG){echo "\ntags loop 1 - tag: L." . __LINE__ . ":\n"; print_r($tag);echo "\n";} $actionTag = array(); $actionTag['tag'] = substr($tag['tag'], 0, 6); $actionTag['typeName'] = $tag['attributes']['typeName']; if ('Insert' == substr($tag['tag'], 0, 6)) { $typeNsPrefix = 'p5_default_db'; if (!empty($tag['attributes']['typeNsUri'])) { $baseNsUri = $this->getBaseNamespaceUri(); if ("{$baseNsUri}/objects" == $tag['attributes']['typeNsUri']) { $typeNsPrefix = 'p5_objects'; } } $actionTag['typeName'] = "{$typeNsPrefix}:{$tag['attributes']['typeName']}"; } $featureEx = explode('.', $tag['attributes']['featureId'], 2); $actionTag['featureId'] = $featureEx[1]; if ('Update' == substr($tag['tag'], 0, 6) && empty($actionTag['featureId'])) { throw new Api_WfsException("Syntax error - could not read feature id!"); } if ('Delete' == substr($tag['tag'], 0, 6) && empty($actionTag['featureId'])) { throw new Api_WfsException("Syntax error - could not read feature id!"); } if ('complete' == $tag['type']) { $itemPatchs[] = $actionTag; $actionTag = null; } else { $actionTag['itemPatch'] = array(); } } else { $itemPatchs[] = $actionTag; $actionTag = null; } break; default: {// fields if($DBG){echo "\ntags loop 2 - tag: L." . __LINE__ . ":\n"; print_r($tag);echo "\n";} if (3 != $tag['level'] && 'close' == $tag['type']) { $actionTag = null; } if (3 != $tag['level']) continue; if (empty($actionTag)) continue; if ('Update' == $actionTag['tag']) { if ($theGeomField == $tag['tag']) { $actionTag['itemPatch'][$tag['tag']] = $this->_typeConverter->convertGmlCoordinatesToWkt($tag['value']); } else { $actionTag['itemPatch'][$tag['tag']] = $tag['value']; } } else if ('Insert' == $actionTag['tag']) { if ($theGeomField == $tag['tag']) { $actionTag['itemPatch'][$tag['tag']] = $this->_typeConverter->convertGmlCoordinatesToWkt($tag['value']); } else { $actionTag['itemPatch'][$tag['tag']] = $tag['value']; } } else if ('Delete' == $actionTag['tag']) { } } } if (empty($prevTagName)) $prevTagName = $tag['tag']; } if($DBG){echo "\nTODO: itemPatchs L." . __LINE__ . ":\n"; print_r($itemPatchs);echo "\n";} if($DBG){echo "\nTODO: _user_id L." . __LINE__ . " '{$this->_usrAcl->_user_id}'" . "\n";} $changesList = array(); if (!empty($itemPatchs)) { foreach ($itemPatchs as $itemPatchInfo) { if($DBG){echo "L." . __LINE__ . " itemPatchInfo: {typeName:'{$itemPatchInfo['typeName']}'}:\n";print_r($itemPatchInfo);} $acl = $this->getAclFromTypeName($itemPatchInfo['typeName']); if ('Delete' == $itemPatchInfo['tag']) { $itemPatch = array(); $itemPatch[$acl->getPrimaryKeyField()] = $itemPatchInfo['featureId']; $itemPatch['the_geom'] = 'NULL'; } else { if (empty($itemPatchInfo['itemPatch'])) continue; $itemPatch = $itemPatchInfo['itemPatch']; if ('Update' == $itemPatchInfo['tag']) { $itemPatch[$acl->getPrimaryKeyField()] = $itemPatchInfo['featureId']; } else if ('Insert' == $itemPatchInfo['tag']) { if (!empty($itemPatch[$acl->getPrimaryKeyField()])) { $itemPatchInfo['featureId'] = $itemPatch[$acl->getPrimaryKeyField()]; } else { //throw new Exception("TODO: Insert #" . __LINE__ . ": Create new record"); } } } if($DBG){echo "L." . __LINE__ . " TODO '" . ($itemPatchInfo['tag'])? 'Insert' : 'Update' . "' itemPatch:\n";print_r($itemPatch);} if ('Insert' == $itemPatchInfo['tag'] && empty($itemPatch[$acl->getPrimaryKeyField()])) { $newId = $acl->addItem($itemPatch); $changesList[$newId] = array('Status'=>(($newId > 0)? 'SUCCESS' : 'FAILED'), 'Message'=>"created {$newId}."); if ($newId > 0) { $changesList[$newId]['fid'] = $acl->getName() . '.' . $newId; } if($DBG){echo "created {$newId}.\n";} } else { $affected = $acl->updateItem($itemPatch); $changesList[$itemPatchInfo['featureId']] = array('Status'=>(($affected >= 0)? 'SUCCESS' : 'FAILED'), 'Message'=>"affected {$affected}."); if($DBG){echo "affected {$affected}.\n";} } } //throw new Exception("TODO: run query #" . __LINE__ . " \nitemPatchs:\n" . json_encode($itemPatchs) . " \ntags:\n" . json_encode($tags) . "\n"); } else { throw new Exception("Parse Request xml error #" . __LINE__ . ": Nothing to change"); } return $this->_transactionResponse($changesList); } public function _transactionResponse($changesList) { // // // : SUCCESS / FAILED / PARTIAL // [ $change) { if ('FAILED' == $change['Status']) { $statusIsFailed = true; } if ('SUCCESS' == $change['Status'] && !empty($change['fid'])) { $createdFetureId[] = $change['fid']; } if (!empty($change['Message'])) $messageTag .= "Feature '{$featureId}' {$change['Status']}: {$change['Message']}\n"; } $statusTag = ($statusIsFailed)? 'FAILED' : 'SUCCESS'; $statusTag = ""; $messageTag = '';//"{$messageTag}"; /* Example: */ // TODO: build xml by DOMDocument // TODO: xsi:schemaLocation="http://www.opengis.net/wfs http://localhost:8080/geoserver/schemas/wfs/1.0.0/WFS-transaction.xsd" $wfsInsertResult = ''; if (!empty($createdFetureId)) { $wfsInsertResult = "\n\n"; foreach ($createdFetureId as $fid) { $wfsInsertResult .= '' . "\n"; } $wfsInsertResult .= "\n\n"; EOF; } $tranRes = << {$wfsInsertResult} {$statusTag} {$messageTag} EOF; return $tranRes; } public function _convertTransactionXml($requestXmlString, $sourceNsList) { $DBG = (V::get('DBG_XSL', '', $_GET) > 0);// TODO: Profiler if($DBG){echo 'L.' . __LINE__ . ' sourceNsList:';print_r($sourceNsList);echo "\n";} $updateActionsXsd = array(); $insertActionsXsd = array(); $deleteActionsXsd = array(); // foreach ($sourceNsList as $nsInd => $sourceNs) { // $theGeomField = 'the_geom';// TODO: get from fields list $typeName = "p5_{$sourceNs[0]}:{$sourceNs[1]}"; if($DBG){echo 'L.' . __LINE__ . ' typeName:';print_r($typeName);echo "\n";} $updateElementName = "UpdateNs{$nsInd}"; $geomCoordsUpdateXpath = "//wfs:Value/*/gml:outerBoundaryIs/gml:LinearRing/gml:coordinates"; $geomCoordsInsertXpath = "//*/gml:outerBoundaryIs/gml:LinearRing/gml:coordinates"; $acl = $this->getAclFromTypeName($typeName); $geomType = $acl->getGeomFieldType($theGeomField); if ('polygon' == $geomType) { $geomCoordsUpdateXpath = ".//wfs:Value/*/gml:outerBoundaryIs/gml:LinearRing/gml:coordinates"; $geomCoordsUpdateXpath = "(())"; $geomCoordsInsertXpath = ".//*/gml:outerBoundaryIs/gml:LinearRing/gml:coordinates"; $geomCoordsInsertXpath = "(())"; } else if ('linestring' == $geomType) { $geomCoordsUpdateXpath = ".//wfs:Value/*/gml:coordinates"; $geomCoordsUpdateXpath = "()"; $geomCoordsInsertXpath = ".//*/gml:coordinates"; $geomCoordsInsertXpath = "()"; } else if ('point' == $geomType) { $geomCoordsUpdateXpath = ".//wfs:Value/*/gml:coordinates"; $geomCoordsUpdateXpath = "()"; $geomCoordsInsertXpath = ".//*/gml:coordinates"; $geomCoordsInsertXpath = "()"; } $actionXsd = << {$geomCoordsUpdateXpath} EOF; $updateActionsXsd[] = $actionXsd; $typeName = "{$sourceNs[1]}";//"p5_{$sourceNs[0]}:{$sourceNs[1]}"; $insertElementName = "InsertNs{$nsInd}"; $actionXsd = << {$geomCoordsInsertXpath} EOF; $insertActionsXsd[] = $actionXsd; $deleteElementName = "DeleteNs{$nsInd}"; $typeName = "p5_{$sourceNs[0]}:{$sourceNs[1]}"; $actionXsd = << EOF; $deleteActionsXsd[] = $actionXsd; } if (!empty($updateActionsXsd)) { $updateActionsXsd = implode("\n", $updateActionsXsd); $updateActionsXsd = << {$updateActionsXsd} EOF; } else { $updateActionsXsd = ''; } if (!empty($insertActionsXsd)) { $insertActionsXsd = implode("\n", $insertActionsXsd); $insertActionsXsd = << {$insertActionsXsd} EOF; } else { $insertActionsXsd = ''; } if (!empty($deleteActionsXsd)) { $deleteActionsXsd = implode("\n", $deleteActionsXsd); $deleteActionsXsd = << {$deleteActionsXsd} EOF; } else { $deleteActionsXsd = ''; } $convertTransactionXslString = ''; $convertTransactionXslString .= << {$updateActionsXsd} {$insertActionsXsd} {$deleteActionsXsd} EOF; if($DBG){echo 'L.' . __LINE__ . ' $convertTransactionXslString:' . $convertTransactionXslString . "\n";} $requestXml = new DOMDocument(); $requestXml->loadXml($requestXmlString); $convertTransactionXsl = new DOMDocument(); $convertTransactionXsl->loadXml($convertTransactionXslString); $proc = new XSLTProcessor(); $proc->importStylesheet($convertTransactionXsl); return $proc->transformToXML($requestXml); } public function _validateConvertedTransactionXml($convertedTransaction, $sourceNsList) { $DBG = (V::get('DBG_XSD', '', $_GET) > 0);// TODO: Profiler if($DBG){echo 'L.' . __LINE__ . ' sourceNsList:';print_r($sourceNsList);echo "\n";} $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->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri); $rootNode->setAttribute('elementFormDefault', 'qualified'); // $rootNode->setAttribute('targetNamespace', $wfsNsUri); $rootNode->setAttribute('version', '1.0'); {// $elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $rootNode->appendChild($elNode); $elNode->setAttribute('name', 'Transaction'); $elNode->setAttribute('type', 'TransactionType'); $cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType'); $rootNode->appendChild($cTypeNode); $cTypeNode->setAttribute('name', 'TransactionType'); $seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:sequence'); $cTypeNode->appendChild($seqNode); $choiceNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:choice'); $seqNode->appendChild($choiceNode); $choiceNode->setAttribute('minOccurs', '0'); $choiceNode->setAttribute('maxOccurs', 'unbounded'); // foreach ($sourceNsList as $nsInd => $sourceNs) { $typeName = "p5_{$sourceNs[0]}:{$sourceNs[1]}"; $updateElementName = "UpdateNs{$nsInd}"; $updateElementType = "UpdateNs{$nsInd}ElementType"; $updateElemNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $choiceNode->appendChild($updateElemNode); $updateElemNode->setAttribute('name', $updateElementName); $updateElemNode->setAttribute('type', $updateElementType); } // foreach ($sourceNsList as $nsInd => $sourceNs) { $typeName = "p5_{$sourceNs[0]}:{$sourceNs[1]}"; $insertElementName = "InsertNs{$nsInd}"; $insertElementType = "InsertNs{$nsInd}ElementType"; $insertElemNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $choiceNode->appendChild($insertElemNode); $insertElemNode->setAttribute('name', $insertElementName); $insertElemNode->setAttribute('type', $insertElementType); } // foreach ($sourceNsList as $nsInd => $sourceNs) { $typeName = "p5_{$sourceNs[0]}:{$sourceNs[1]}"; $deleteElementName = "DeleteNs{$nsInd}"; $deleteElementType = "DeleteNs{$nsInd}ElementType"; $deleteElemNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $choiceNode->appendChild($deleteElemNode); $deleteElemNode->setAttribute('name', $deleteElementName); $deleteElemNode->setAttribute('type', $deleteElementType); } // $attrNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute'); $cTypeNode->appendChild($attrNode); $attrNode->setAttribute('name', 'version'); $attrNode->setAttribute('type', 'xsd:string'); $attrNode->setAttribute('use', 'required'); $attrNode->setAttribute('fixed', '1.0.0'); $attrNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute'); $cTypeNode->appendChild($attrNode); $attrNode->setAttribute('name', 'service'); $attrNode->setAttribute('type', 'xsd:string'); $attrNode->setAttribute('use', 'required'); $attrNode->setAttribute('fixed', 'WFS'); } foreach ($sourceNsList as $nsInd => $sourceNs) { $transactionTypesList = array(); $transactionTypesList[] = 'Update'; $transactionTypesList[] = 'Insert'; foreach ($transactionTypesList as $transactionType) { $typeName = "p5_{$sourceNs[0]}:{$sourceNs[1]}"; if($DBG){echo 'L.' . __LINE__ . ' TODO: get acl typeName:';print_r($typeName);echo "\n";} $acl = $this->getAclFromTypeName($typeName); $updateElementName = "{$transactionType}Ns{$nsInd}"; $updateElementType = "{$transactionType}Ns{$nsInd}ElementType"; /* */ $updateTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType'); $rootNode->appendChild($updateTypeNode); $updateTypeNode->setAttribute('name', $updateElementType); { $seqNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:all'); $updateTypeNode->appendChild($seqNode); { $pKeyField = $acl->getPrimaryKeyField(); $fldList = $this->_getFieldListFromAcl($acl); // fields without geometry fields foreach ($fldList as $fldName) { if ($acl->isGeomField($fldName)) continue; $elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $seqNode->appendChild($elNode); $elNode->setAttribute('name', $fldName); $minOccurs = 0; if ($pKeyField == $fldName) { $minOccurs = '1'; } else { $minOccurs = '0'; } $elNode->setAttribute('minOccurs', $minOccurs); $fldType = null; if ($acl->isIntegerField($fldName)) { $fldType = 'xsd:integer'; } else if ($acl->isDecimalField($fldName)) { $fldType = 'xsd:decimal'; } else if ($acl->isDateField($fldName)) { $fldType = 'xsd:date'; } else if ($acl->isDateTimeField($fldName)) { // $fldType = 'xsd:dateTime'; $fldType = null;// 'xsd:string'; $patternDataTime = "(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})(:(\d{2}))?"; // // // // // // // $simpleTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:simpleType'); $restrictionNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:restriction'); $patternNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:pattern'); $restrictionNode->setAttribute('base', 'xsd:string'); $patternNode->setAttribute('value', $patternDataTime); $restrictionNode->appendChild($patternNode); $simpleTypeNode->appendChild($restrictionNode); $elNode->appendChild($simpleTypeNode); // continue;// TODO: ? below added nillable = true, minOccurs = 0, type = $fldType } else if ($acl->isBinaryField($fldName)) { $fldType = 'xsd:base64Binary'; } else { $fldType = 'xsd:string'; } if ($fldType) $elNode->setAttribute('type', $fldType); $elNode->setAttribute('nillable', 'true'); $elNode->setAttribute('minOccurs', '0'); } // only geometry fields foreach ($fldList as $fldName) { if (!$acl->isGeomField($fldName)) continue; $elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $seqNode->appendChild($elNode); $elNode->setAttribute('name', $fldName); $minOccurs = 0; if ($pKeyField == $fldName) { $minOccurs = '1'; } else { $minOccurs = '0'; } $elNode->setAttribute('minOccurs', $minOccurs); if ($acl->isGeomField($fldName)) { //$fldType = 'gml:GeometryPropertyType'; // TODO: use geom types from gml to wkt // TODO: pattern wg atrybutów gml:coordinates decimal="." cs="," ts=" " $patternWkt = '';// TODO: error if empty - unsupported geom type $patternNum = '\-?\d+\.?\d*'; $patternPoint = $patternNum . ',' . $patternNum; $patternPoints = '(' . $patternPoint . ')( ' . $patternPoint . ')+'; $geomType = $acl->getGeomFieldType($fldName); if ('polygon' == $geomType) { // [a-zA-Z]+\(\((\-?\d+\.?\d*,\-?\d+\.?\d*)( (\-?\d+\.?\d*,\-?\d+\.?\d*))+\)\) $patternWkt = '[a-zA-Z]+\(\(' . $patternPoints . '\)\)'; } else if ('linestring' == $geomType) { // [a-zA-Z]+\((\-?\d+\.?\d*,\-?\d+\.?\d*)( (\-?\d+\.?\d*,\-?\d+\.?\d*))+\) $patternWkt = '[a-zA-Z]+\(' . $patternPoints . '\)'; } else if ('point' == $geomType) { // [a-zA-Z]+\(\-?\d\.?\d*,\-?\d\.?\d*\) $patternWkt = '[a-zA-Z]+\(' . $patternPoint . '\)'; } $simpleTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:simpleType'); $restrictionNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:restriction'); $patternNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:pattern'); $restrictionNode->setAttribute('base', 'xsd:string'); $patternNode->setAttribute('value', $patternWkt); $restrictionNode->appendChild($patternNode); $simpleTypeNode->appendChild($restrictionNode); $elNode->appendChild($simpleTypeNode); } $elNode->setAttribute('nillable', 'true'); $elNode->setAttribute('minOccurs', '0'); } } } $attrNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute'); $updateTypeNode->appendChild($attrNode); $attrNode->setAttribute('name', 'typeName'); $attrNode->setAttribute('type', 'xsd:token'); $attrNode->setAttribute('use', 'required'); if ($transactionType == 'Insert') { $attrNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute'); $updateTypeNode->appendChild($attrNode); $attrNode->setAttribute('name', 'typeNsUri'); $attrNode->setAttribute('type', 'xsd:anyURI'); $attrNode->setAttribute('use', 'required'); } if ($transactionType == 'Update') { $attrNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute'); $updateTypeNode->appendChild($attrNode); $attrNode->setAttribute('name', 'featureId'); $attrNode->setAttribute('use', 'required'); $sTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:simpleType'); $attrNode->appendChild($sTypeNode); $resNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:restriction'); $sTypeNode->appendChild($resNode); $resNode->setAttribute('base', 'xsd:string'); $patternNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:pattern'); $resNode->appendChild($patternNode); $patternNode->setAttribute('value', '[a-zA-Z_][a-zA-Z0-9_]*\.[0-9]*'); } } {// 'Delete' $typeName = "p5_{$sourceNs[0]}:{$sourceNs[1]}"; $acl = $this->getAclFromTypeName($typeName); $deleteElementType = "DeleteNs{$nsInd}ElementType"; $deleteTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType'); $rootNode->appendChild($deleteTypeNode); $deleteTypeNode->setAttribute('name', $deleteElementType); /* */ $attrNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute'); $deleteTypeNode->appendChild($attrNode); $attrNode->setAttribute('name', 'typeName'); $attrNode->setAttribute('type', 'xsd:token'); $attrNode->setAttribute('use', 'required'); /* */ $attrNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:attribute'); $deleteTypeNode->appendChild($attrNode); $attrNode->setAttribute('name', 'featureId'); $attrNode->setAttribute('use', 'required'); $sTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:simpleType'); $attrNode->appendChild($sTypeNode); $resNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:restriction'); $sTypeNode->appendChild($resNode); $resNode->setAttribute('base', 'xsd:string'); $patternNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:pattern'); $resNode->appendChild($patternNode); $patternNode->setAttribute('value', '[a-zA-Z_][a-zA-Z0-9_]*\.[0-9]*'); } } $validateConvertedTransactionXsdString = $dom->saveXml(); if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print_r($validateConvertedTransactionXsdString);echo "\n";} $reqXml = new DOMDocument(); $reqXml->loadXml($convertedTransaction); // TODO: fetch PHP Warning: DOMDocument::schemaValidateSource(): Element 'PARENT_ID': 'abc' is not a valid value of the atomic type 'xs:integer'. return $reqXml->schemaValidateSource($validateConvertedTransactionXsdString); } public function _getDescribeFeatureType($nsPrefix, $type, $simple = true) { return $this->_getDescribeFeatureTypes(array(array($nsPrefix, $type)), $simple); } public function _parseDescribeFeatureTypeRequest($reqContent, $simple = true) { $parserXml = xml_parser_create(); xml_parser_set_option($parserXml, XML_OPTION_CASE_FOLDING, 0); xml_parser_set_option($parserXml, XML_OPTION_SKIP_WHITE, 1); if (0 == xml_parse_into_struct($parserXml, $reqContent, $tags)) { throw new Exception("Error parsing xml"); } xml_parser_free($parserXml); if (empty($tags)) { throw new Exception("Empty structure from request"); } $rootTagName = V::get('tag', '', $tags[0]); if ('DescribeFeatureType' != $rootTagName) { throw new Api_WfsException("Wrong xml root tag '{$rootTagName}' #" . __LINE__, 501); } $requestXmlTags = $tags; $DBG = (V::get('DBG_XML', '', $_GET) > 0);// TODO: Profiler $rootTagName = V::get('tag', '', $requestXmlTags[0]); if ('DescribeFeatureType' != $rootTagName) { throw new Exception("Parse Request xml error #" . __LINE__); } /*[1] => Array( [tag] => TypeName [type] => complete [level] => 2 [value] => p5_default_db:Rozdzielcza_rurociag_wsg84) */ $typeNames = array(); $totalTypes = count($requestXmlTags) - 1; for ($i = 1; $i < $totalTypes; $i++) { if($DBG){echo "TAG[{$i}]:" . json_encode($requestXmlTags[$i]) . "\n";} $typeNames[] = explode(':', $requestXmlTags[$i]['value'], 2); } //echo "typeNames: " . json_encode($typeNames) . "\n"; return $this->_getDescribeFeatureTypes($typeNames, $simple); } public function _getDescribeFeatureAllTypes($simple = true) { $db = DB::getDB(); $idDefaultDB = $db->_zasob_id; $tblsAcl = $this->_getTableAclList(); foreach ($tblsAcl as $tblAcl) { $dataSourceName = 'default_db';// TODO: getSourceName $tblName = $tblAcl->getName(); $typeNames[] = array("p5_{$dataSourceName}", $tblName); } $typeNames[] = array("p5_objects", 'File'); return $this->_getDescribeFeatureTypes($typeNames, $simple); } // @param $typeNames = array( array( $nsPrefix, $type ) ) public function _getDescribeFeatureTypes($typeNames, $simple = true) { if (empty($typeNames)) throw new HttpException("Feature Type Names not defined", 400); $this->DBG("types:" . json_encode($typeNames), __LINE__, __FUNCTION__, __CLASS__); $baseNsUri = $this->getBaseNamespaceUri(); $rootWfsNs = 'p5'; $rootWfsNsUri = "{$baseNsUri}"; $wfsNs = 'p5_default_db'; $wfsNsUri = "{$baseNsUri}/default_db"; $featureTypeUri = $this->getBaseUri() . "?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType"; header('Content-type: application/xml'); // // $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->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri); $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', "xmlns:{$rootWfsNs}", $rootWfsNsUri); $rootNode->setAttribute('elementFormDefault', 'qualified'); $rootNode->setAttribute('targetNamespace', $wfsNsUri); {// $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', $this->getBaseUri() . "/../../../schema/gml/2.1.2/feature.xsd"); } foreach ($typeNames as $typeNameEx) { $nsPrefix = $typeNameEx[0]; $type = $typeNameEx[1]; $typeName = "{$nsPrefix}:{$type}"; $acl = $this->getAclFromTypeName($typeName); if (!$this->isAllowedFeatureType($nsPrefix, $type)) { throw new Api_WfsException("Could not find type: " . htmlspecialchars($type)); } $typeName = $type . 'Type'; $fldList = $this->_getFieldListFromAcl($acl); $cTypeNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:complexType'); $rootNode->appendChild($cTypeNode); $cTypeNode->setAttribute('name', $typeName); if (!$simple) { $idZasob = $acl->getID(); $cTypeNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:web_link", Request::getPathUri() . "index.php?MENU_INIT=VIEWTABLE_AJAX&ZASOB_ID={$idZasob}"); } $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); // $pKeyField = $acl->getPrimaryKeyField(); $p5Attributes = ($simple)? array() : $acl->getAttributesFromZasoby(); foreach ($fldList as $idZasob => $fldName) { $elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $seqNode->appendChild($elNode); $elNode->setAttribute('name', $fldName); $minOccurs = 0; if ($pKeyField == $fldName) { $minOccurs = '1'; } else { $minOccurs = '0'; } $elNode->setAttribute('minOccurs', $minOccurs); $elNode->setAttribute('maxOccurs', '1'); $elNode->setAttribute('nillable', 'true'); $fldType = 'xsd:string'; if ($acl->isIntegerField($fldName)) { $fldType = 'xsd:integer'; } else if ($acl->isDecimalField($fldName)) { $fldType = 'xsd:decimal'; } else if ($acl->isDateField($fldName)) { $fldType = 'xsd:date'; } else if ($acl->isDateTimeField($fldName)) { $fldType = 'xsd:dateTime'; } else if ($acl->isGeomField($fldName)) { //$fldType = 'gml:GeometryPropertyType'; $geomType = $acl->getGeomFieldType($fldName); if ('polygon' == $geomType) { $fldType = 'gml:PolygonPropertyType'; } else if ('point' == $geomType) { $fldType = 'gml:PointPropertyType'; } else if ('linestring' == $geomType) { $fldType = 'gml:LineStringPropertyType'; } else { $fldType = 'gml:GeometryPropertyType'; } } else if ($acl->isEnumerationField($fldName)) { $fldType = ($simple)? 'xsd:string' : "{$nsPrefix}:{$fldName}Type"; } else if ($acl->isBinaryField($fldName)) { $fldType = 'xsd:base64Binary'; } $elNode->setAttribute('type', $fldType); 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']); } if ($acl->hasFieldPerm($idZasob, 'W')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true"); if ($acl->hasFieldPerm($idZasob, 'C')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_create", "true"); if (!$acl->hasFieldPerm($idZasob, 'R')) $elNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false"); } } $elNode = $dom->createElementNS('http://www.w3.org/2001/XMLSchema', 'xsd:element'); $rootNode->appendChild($elNode); $elNode->setAttribute('name', $type); $elNode->setAttribute('type', $wfsNs . ':' . $typeName); if ($simple) { $elNode->setAttribute('substitutionGroup', 'gml:_Feature'); } else { $elNode->setAttribute('substitutionGroup', 'gml:AbstractFeature'); } if (!$simple) { foreach ($fldList as $fldName) { 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"); $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]); } } } } } } return $dom->saveXML(); } public function _getTableAclList() {// Use only Tables from default_db $tblAclList = array(); $db = DB::getDB(); $idDefaultDB = $db->_zasob_id; $fullTblAclList = $this->_usrAcl->getTablesAcl(); foreach ($fullTblAclList as $tblAcl) { $dataSourceName = 'default_db';// TODO: getSourceName $tblName = $tblAcl->getName(); if ($idDefaultDB != $tblAcl->getDB()) {// hide non default_db tables continue; } try { $acl = $this->getAclFromTypeName($typeName = "p5_{$dataSourceName}:{$tblName}"); } catch (Exception $e) { // TODO: error log $e->getMessage(); } if (!$acl) { // TODO: error log msg continue; } $tblAclList[] = $tblAcl; } return $tblAclList; } public function _getFieldListFromAcl($acl) { $fldList = $acl->getRealFieldListByIdZasob(); return $fldList; } public function setLogger($logger) { $this->_logger = $logger; } public function DBG($reqLog, $lineNr = null, $funName = null, $className = null) { if (!$this->_logger) return; $this->_logger->DBG($reqLog, $lineNr, $funName, $className); } public function convertOgcFilterFromRequestBody($requestOgcFilter) { $ogcFilter = ''; if (empty($requestOgcFilter)) return ''; { $convertOgcFilterXslString .= << EOF; DBG::_('DBG_XML', '>2', "convertOgcFilterXslString", $convertOgcFilterXslString, __CLASS__, __FUNCTION__, __LINE__); $convertTransactionXsl = new DOMDocument(); $convertTransactionXsl->loadXml($convertOgcFilterXslString); $requestXml = new DOMDocument(); $requestXml->loadXml($requestOgcFilter); $proc = new XSLTProcessor(); $proc->importStylesheet($convertTransactionXsl); $ogcFilter = $proc->transformToXML($requestXml); DBG::_('DBG_XML', '>2', "ogcFilter", $ogcFilter, __CLASS__, __FUNCTION__, __LINE__); } return $ogcFilter; } }