_parseTransactionXmlStruct($reqContent, $tags); throw new Api_WfsException("Not implemented '{$rootTagName}' #L." . __LINE__, 501); } public function getFeatureAction() { $type = V::get('TYPENAME', '', $_REQUEST); $typeEx = explode(':', $type); $maxFeatures = '10000';// TODO: Set Deafult Limit $maxFeatures = V::get('MAXFEATURES', $maxFeatures, $_REQUEST, 'int'); $maxFeatures = V::get('maxFeatures', $maxFeatures, $_REQUEST, 'int'); $maxFeatures = V::get('count', $maxFeatures, $_REQUEST, 'int'); $startIndex = V::get('startIndex', 0, $_REQUEST, 'int');// sql offset $ogcFilter = ''; $ogcFilter = V::get('FILTER', $ogcFilter, $_REQUEST); $ogcFilter = V::get('Filter', $ogcFilter, $_REQUEST); $ogcFilter = urldecode($ogcFilter); $sortBy = V::get('sortBy', '', $_REQUEST); $propertyName = V::get('propertyName', '', $_REQUEST); $propertyName = trim($propertyName); $srsname = V::get('SRSNAME', '', $_REQUEST);// eg. EPSG:4326 if (count($typeEx) != 2) throw new HttpException("Wrong param TYPENAME", 400); if (empty($ogcFilter)) {// read ogc:Filter from POST body if not defined in GET $reqBody = Request::getRequestBody(); if (!empty($reqBody)) { $ogcFilter = $this->convertOgcFilterFromRequestBody($reqBody); if (empty($ogcFilter)) throw new Api_WfsException("Error Processing ogc:Filter", 501); } } if ('hits' == V::get('resultType', '', $_REQUEST)) {// resultType=hits return $this->getTotalFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname, $ogcFilter, $sortBy, $startIndex, $propertyName, $simple = true); } else { return $this->getFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname, $ogcFilter, $sortBy, $startIndex, $propertyName, $simple = true); } } public function getFeatureAdvancedAction() { $type = V::get('TYPENAME', '', $_REQUEST); $typeEx = explode(':', $type); $maxFeatures = '10000';// TODO: Set Deafult Limit $maxFeatures = V::get('MAXFEATURES', $maxFeatures, $_REQUEST, 'int'); $maxFeatures = V::get('maxFeatures', $maxFeatures, $_REQUEST, 'int'); $maxFeatures = V::get('count', $maxFeatures, $_REQUEST, 'int'); $startIndex = V::get('startIndex', 0, $_REQUEST, 'int');// sql offset $ogcFilter = ''; $ogcFilter = V::get('FILTER', $ogcFilter, $_REQUEST); $ogcFilter = V::get('Filter', $ogcFilter, $_REQUEST); $sortBy = V::get('sortBy', '', $_REQUEST); $propertyName = V::get('propertyName', '', $_REQUEST); $propertyName = trim($propertyName); $srsname = V::get('SRSNAME', '', $_REQUEST);// eg. EPSG:4326 if (count($typeEx) != 2) throw new HttpException("Wrong param TYPENAME", 400); if (empty($ogcFilter)) {// read ogc:Filter from POST body if not defined in GET $reqBody = Request::getRequestBody(); if (!empty($reqBody)) { $ogcFilter = $this->convertOgcFilterFromRequestBody($reqBody); } } if ('hits' == V::get('resultType', '', $_REQUEST)) {// resultType=hits return $this->getTotalFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname, $ogcFilter, $sortBy, $startIndex, $propertyName, $simple = false); } else { return $this->getFeatures($typeEx[0], $typeEx[1], $maxFeatures, $srsname, $ogcFilter, $sortBy, $startIndex, $propertyName, $simple = false); } } public function testOgcFilterAction() { $type = V::get('TYPENAME', '', $_REQUEST); $typeEx = explode(':', $type); $maxFeatures = V::get('MAXFEATURES', '10000', $_REQUEST, 'int');// TODO: Set Deafult Limit $ogcFilter = V::get('Filter', '', $_REQUEST); $srsname = V::get('SRSNAME', '', $_REQUEST);// eg. EPSG:4326 if (count($typeEx) == 2) { Lib::loadClass('ParseOgcFilter'); $parser = new ParseOgcFilter(); $parser->loadOgcFilter($ogcFilter); $queryWhereBuilder = $parser->convertToSqlQueryWhereBuilder(); echo $queryWhereBuilder->getQueryWhere('t'); } else { throw new HttpException("Wrong param TYPENAME", 400); } } public function getTotalFeatures($nsPrefix, $type, $maxFeatures, $srsname, $ogcFilter = '', $sortBy = '', $startIndex = 0, $propertyName = '', $simple = true) { $DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler $typeName = "{$nsPrefix}:{$type}"; if($DBG){echo "typeName($typeName})\n";} $acl = $this->getAclFromTypeName($typeName); $fldList = $this->_getFieldListFromAcl($acl); $baseNsUri = Api_WfsNs::getBaseWfsUri(); $rootWfsNs = 'p5'; $rootWfsNsUri = "{$baseNsUri}"; //$wfsNs = 'p5_default_db_' . $type;//$nsPrefix; $wfsNs = $nsPrefix;//'p5_default_db'; $wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3); $featureTypeUri = $this->getBaseUri() . "?SERVICE=WFS&VERSION=1.0.0&TYPENAME={$typeName}&REQUEST=DescribeFeatureType"; // get BBox from geom_field (only one geom fld is allowed) $geomFld = null; { foreach ($fldList as $fldName) { if ($acl->isGeomField($fldName)) { $geomFld = $fldName; } } } if($DBG){echo "ogcFilter(" . strlen($ogcFilter) . "): {$ogcFilter}\n";} $searchParams = array(); $searchParams['limit'] = $maxFeatures; $searchParams['limitstart'] = $startIndex; if (!empty($sortBy)) { $searchParams['sortBy'] = $sortBy; } else { $searchParams['order_by'] = $acl->getPrimaryKeyField(); $searchParams['order_dir'] = 'DESC'; } if (strlen($ogcFilter) > 0) $searchParams['ogc:Filter'] = $ogcFilter; if (strlen($propertyName) > 0) { $propertyNamesEx = explode(',', $propertyName); $onlyCols = array(); foreach ($propertyNamesEx as $colName) { $colName = trim($colName); $onlyCols[] = $colName; } if (!empty($onlyCols)) $searchParams['cols'] = $onlyCols; } {// BBOX // 54.26931096743426,18.48242909824306,54.26738118403914,18.478738378639246 $bbox = V::get('BBOX', '', $_GET); if (!empty($bbox)) { if (preg_match("/^\d+(.\d+)?,\d+(.\d+)?,\d+(.\d+)?,\d+(.\d+)?$/", $bbox, $matches)) { $searchParams['f_the_geom'] = "BBOX:{$bbox}"; } else { // throw new Exception("Error Processing Request", 1);// ? } } } if($DBG){echo 'getItems() searchParams:';print_r($searchParams);echo "\n";} $totalItems = $acl->getTotal($searchParams); if($DBG){echo 'totalItems:';print_r($totalItems);echo "\n";} $xmlWriter = new 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('wfs:FeatureCollection'); $xmlWriter->writeAttribute('xmlns:wfs', 'http://www.opengis.net/wfs/2.0'); $xmlWriter->writeAttribute('xmlns', 'http://www.opengis.net/wfs/2.0'); $xmlWriter->writeAttribute('xmlns:gml', 'http://www.opengis.net/gml'); $xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); // $xmlWriter->writeAttribute('xsi:schemaLocation', "{$wfsNsUri} {$featureTypeUri}"); $xmlWriter->writeAttribute('numberMatched', $totalItems); $xmlWriter->writeAttribute('numberReturned', 0); // $xmlWriter->writeAttribute('timeStamp', "TODO: timestamp like '2011-12-09T11:30:16'"); $xmlWriter->endElement();// wfs:FeatureCollection $xmlWriter->endDocument(); exit; } public function getFeatures($nsPrefix, $type, $maxFeatures, $srsname, $ogcFilter = '', $sortBy = '', $startIndex = 0, $propertyName = '', $simple = true) { $DBG = (V::get('DBG_GEO', '', $_GET) > 0);// TODO: Profiler $DBG_DS = V::get('DBG_DS', 0, $_GET, 'int'); $typeName = "{$nsPrefix}:{$type}"; if($DBG){echo "typeName($typeName})\n";} $acl = $this->getAclFromTypeName($typeName); $fldList = $this->_getFieldListFromAcl($acl); $baseNsUri = Api_WfsNs::getBaseWfsUri(); $rootWfsNs = 'p5'; $rootWfsNsUri = "{$baseNsUri}"; //$wfsNs = 'p5_default_db_' . $type;//$nsPrefix; $wfsNs = $nsPrefix;//'p5_default_db'; $wfsNsUri = "{$baseNsUri}/" . substr($nsPrefix, 3); $featureTypeUri = $this->getBaseUri() . "?SERVICE=WFS&VERSION=1.0.0&TYPENAME={$typeName}&REQUEST=DescribeFeatureType"; // get BBox from geom_field (only one geom fld is allowed) $geomFld = null; { foreach ($fldList as $fldName) { if ($acl->isGeomField($fldName)) { $geomFld = $fldName; } } } if($DBG){echo "ogcFilter(" . strlen($ogcFilter) . "): {$ogcFilter}\n";} $searchParams = array(); $searchParams['limit'] = $maxFeatures; $searchParams['limitstart'] = $startIndex; if (!empty($sortBy)) { $searchParams['sortBy'] = $sortBy; } else { $searchParams['order_by'] = $acl->getPrimaryKeyField(); $searchParams['order_dir'] = 'DESC'; } if (strlen($ogcFilter) > 0) $searchParams['ogc:Filter'] = $ogcFilter; if (strlen($propertyName) > 0) { $propertyNamesEx = explode(',', $propertyName); $onlyCols = array(); foreach ($propertyNamesEx as $colName) { $colName = trim($colName); $onlyCols[] = $colName; } if (!empty($onlyCols)) $searchParams['cols'] = $onlyCols; } {// BBOX // 54.26931096743426,18.48242909824306,54.26738118403914,18.478738378639246 $bbox = V::get('BBOX', '', $_GET); if (!empty($bbox)) { if (preg_match("/^\d+(.\d+)?,\d+(.\d+)?,\d+(.\d+)?,\d+(.\d+)?$/", $bbox, $matches)) { $searchParams['f_the_geom'] = "BBOX:{$bbox}"; } else { // throw new Exception("Error Processing Request", 1);// ? } } } if($DBG){echo 'getItems:';print_r($searchParams);echo "\n";} $items = $acl->getItems($searchParams); $dom = new DOMDocument('1.0', 'utf-8'); $dom->formatOutput = true; $dom->preserveWhiteSpace = false; $rootNode = $dom->createElementNS('http://www.opengis.net/wfs', 'wfs:FeatureCollection'); $dom->appendChild($rootNode); $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.opengis.net/wfs'); $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:wfs', 'http://www.opengis.net/wfs'); $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gml', 'http://www.opengis.net/gml'); $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink'); $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:' . $wfsNs, $wfsNsUri); if (!$simple) $rootNode->setAttributeNS('http://www.w3.org/2000/xmlns/', "xmlns:{$rootWfsNs}", $rootWfsNsUri); //$rootNode->setAttribute('xsi:schemaLocation', 'http://www.opengis.net/wfs'); $rootNode->setAttribute('xsi:schemaLocation', "{$wfsNsUri} {$featureTypeUri}"); if($DBG){echo '(geomFld: '.$geomFld.'):';print_r($acl->getFieldType($geomFld));echo "\n";} if (empty($items)) { $pKeyField = $acl->getPrimaryKeyField(); $fakeItem = new stdClass(); $fakeItem->{$pKeyField} = 0; $items[0] = $fakeItem; } $sourceName = $acl->getSourceName(); $tblName = $acl->getName(); foreach ($items as $itemKey => $item) { if (!is_array($item)) $item = (array)$item; if($DBG && !empty($geomFld)){echo 'item['.$itemKey.'] ('.$geomFld.')isEmpty('.empty($item[$geomFld]).'):';print_r($item[$geomFld]);echo "\n";} if($DBG_DS){echo ">>> loop({$itemKey}) item: ";print_r($item);echo "\n";} $featureMemberNode = $dom->createElementNS('http://www.opengis.net/gml', 'gml:featureMember'); $rootNode->appendChild($featureMemberNode); $featureNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$type}"); $featureMemberNode->appendChild($featureNode); $featureNode->setAttribute('fid', "{$type}.{$itemKey}"); if (!$simple) $featureNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:web_link", Request::getPathUri() . "index.php?_route=ViewTableAjax&typeName=p5_{$sourceName}:{$tblName}#EDIT/{$itemKey}"); foreach ($fldList as $fldName) { $fldType = $acl->getXsdFieldType($fldName); $featureFldNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}"); if($DBG_DS){echo">>> acl->canReadObjectField('{$fldName}', \$item) ...\n";} if ($acl->canReadObjectField($fldName, (object)$item)) { if ($geomFld != null && $geomFld == $fldName) { $geomNode = $this->_typeConverter->createGmlFromWkt($item[$fldName], $dom); if (!$geomNode) continue; $featureFldNode->appendChild($geomNode); } else if (is_array($item[$fldName])) {// TODO: by struct - REF field if($DBG_DS){echo">>> TODO({$fldName}) REF item[{$itemKey}][{$fldName}]: ";print_r($item[$fldName]);echo "\n";} if (1 == count($item[$fldName])) { $xlink = $item[$fldName][0]['xlink']; $xlinkParts = explode(':', $xlink); if (2 != count($xlinkParts)) throw new Exception("Error Processing Reques - wrong xlink format for ".$acl->getName().".{$itemKey}/{$fldName}"); $xlinkParts[0] = Api_WfsNs::getNsUri($xlinkParts[0]); $xlink = implode('#', $xlinkParts); $featureFldNode->setAttribute('xlink:href', $xlink); } else { throw new Exception("Error Processing Request - too many refs for ".$acl->getName().".{$itemKey}/{$fldName}"); } // foreach ($item[$fldName] as $ref) { // $refNode = $dom->createElementNS($wfsNsUri, "{$wfsNs}:{$fldName}"); // $featureFldNode->appendChild($refNode); // } } else { $featureFldNode->nodeValue = str_replace('&', '&', $item[$fldName]); if (empty($featureFldNode->nodeValue) && '0' !== $featureFldNode->nodeValue) { continue; } } } if (!$simple) { if (!$acl->canReadObjectField($fldName, (object)$item)) { $featureFldNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_read", "false"); } if ($acl->canWriteObjectField($fldName, (object)$item)) { $featureFldNode->setAttributeNS($rootWfsNsUri, "{$rootWfsNs}:allow_write", "true"); } } $featureNode->appendChild($featureFldNode); } } return $dom->saveXml(); } public function describeFeatureTypeAction() { $type = V::get('TYPENAME', '', $_REQUEST); if (empty($type)) { $reqContent = Request::getRequestBody(); if (!empty($reqContent)) { return $this->_parseDescribeFeatureTypeRequest($reqContent); } else { return $this->_getDescribeFeatureAllTypes(); } //throw new HttpException("Wrong param TYPENAME", 400); } $typeEx = explode(':', $type); if (count($typeEx) != 2) throw new HttpException("Wrong param TYPENAME", 400); return $this->_getDescribeFeatureType($typeEx[0], $typeEx[1]); } public function describeFeatureTypeAdvancedAction() { $type = V::get('TYPENAME', '', $_REQUEST); if (empty($type)) { $reqContent = Request::getRequestBody(); if (!empty($reqContent)) { return $this->_parseDescribeFeatureTypeRequest($reqContent, $simple = false); } else { return $this->_getDescribeFeatureAllTypes($simple = false); } //throw new HttpException("Wrong param TYPENAME", 400); } $typeEx = explode(':', $type); if (count($typeEx) != 2) throw new HttpException("Wrong param TYPENAME", 400); return $this->_getDescribeFeatureType($typeEx[0], $typeEx[1], $simple = false); } public function getCapabilitiesAction() { $wfsServerUrl = $this->getBaseUri(); $serviceTitle = "Web Feature Service"; $serviceDescription = "This is the reference implementation of WFS 1.0.0 and WFS 1.1.0, supports all WFS operations including Transaction."; //header('Content-type: application/xml; charset="utf-8"'); header('Content-type: application/xml'); $this->_getCapabilities($wfsServerUrl, $serviceTitle, $serviceDescription); } }