<?php # $Id: class_wfs.php 4413 2009-07-22 09:41:52Z christoph $ # http://www.mapbender.org/index.php/class_wfs.php # Copyright (C) 2002 CCGIS # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. require_once(dirname(__FILE__)."/../../core/globalSettings.php"); require_once(dirname(__FILE__)."/class_connector.php"); require_once(dirname(__FILE__)."/class_administration.php"); require_once(dirname(__FILE__)."/class_gml.php"); require_once(dirname(__FILE__)."/class_ows.php"); require_once(dirname(__FILE__)."/class_wfsToDb.php"); require_once(dirname(__FILE__)."/class_wfs_configuration.php"); /** * An abstract Web Feature Service (WFS) class, modelling for example * WFS 1.0.0 or WFS 1.1.0 */ abstract class Wfs extends Ows { var $describeFeatureType; var $describeFeatureTypeNamespace; var $getFeature; var $transaction; var $featureTypeArray = array(); /** * Returns the version of this WFS. Has to be implemented by the subclass. * @return String the version, for example "1.0.0" */ public function getVersion () { return ""; } public function addFeatureType ($aFeatureType) { array_push($this->featureTypeArray, $aFeatureType); } protected function findFeatureTypeByName ($name) { foreach ($this->featureTypeArray as $ft) { if ($ft->name == $name) { return $ft; } } new mb_exception("This WFS doesn't have a featuretype with name " . $name); return null; } public function findFeatureTypeById ($id) { foreach ($this->featureTypeArray as $ft) { if ($ft->id == $id) { return $ft; } } new mb_exception("This WFS doesn't have a featuretype with ID " . $id); return null; } protected function getFeatureGet ($featureTypeName, $filter) { $url = $this->getFeature . $this->getConjunctionCharacter($this->getFeature) . "service=WFS&request=getFeature&version=" . $this->getVersion() . "&typename=" . $featureTypeName . "&filter=" . urlencode($filter); return $this->get($url); } protected function getFeaturePost ($featureTypeName, $filter) { $postData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" . "<wfs:GetFeature service=\"WFS\" version=\"" . $this->getVersion() . "\" " . "xmlns:wfs=\"http://www.opengis.net/wfs\" " . "xmlns:gml=\"http://www.opengis.net/gml\" " . "xmlns:ogc=\"http://www.opengis.net/ogc\">" . "<wfs:Query "; // add namespace if (strpos($featureTypeName, ":") !== false) { $ft = $this->findFeatureTypeByName($featureTypeName); $ns = $this->getNamespace($featureTypeName); $url = $ft->getNamespace($ns); $postData .= "xmlns:" . $ns . "=\"" . $url . "\" "; } $postData .= "typeName=\"" . $featureTypeName . "\">" . $filter . "</wfs:Query></wfs:GetFeature>"; return $this->post($this->getFeature, $postData); } public function getFeature ($featureTypeName, $filter) { // FOR NOW, WE ONLY DO POST REQUESTS! // THE FILTERS ARE CONSTRUCTED ON THE CLIENT SIDE, // SO CHANGING THEM HERE ACCORDING TO GET/POST // WOULD BE TOO MUCH FOR NOW // // if (strpos($this->getFeature, "?") === false) { return $this->getFeaturePost($featureTypeName, $filter); // } // return $this->getFeatureGet($featureTypeName, $filter); } /** * Performs a WFS transaction (delete, update or insert). * * @return String the WFS reply * @param $method String "delete", "update" or "insert" * @param $wfsConf WfsConfiguration * @param $gmlObj Gml */ public function transaction ($method, $wfsConf, $gmlObj) { // // get feature type and geometry column from WFS configuration // if (!($wfsConf instanceof WfsConfiguration)) { $e = new mb_exception("Invalid WFS configuration."); return null; } $featureType = $this->findFeatureTypeById($wfsConf->featureTypeId); $featureTypeName = $featureType->name; $geomColumnName = $wfsConf->getGeometryColumnName(); $authWfsConfElement = $wfsConf->getAuthElement(); // // GML string // if (!($gmlObj instanceof Gml)) { $e = new mb_exception("Not a GML object."); return null; } $gml = $gmlObj->toGml(); if (is_null($gml)) { $e = new mb_exception("GML is not set."); return null; } // I assume that only one feature is contained in the GeoJSON, // so I just take the first from the collection. $feature = $gmlObj->featureCollection->featureArray[0]; switch (strtolower($method)) { case "delete": $requestData = $this->transactionDelete($feature, $featureType, $authWfsConfElement); break; case "update": $requestData = $this->transactionUpdate($feature, $featureType, $authWfsConfElement, $gml, $geomColumnName); break; case "insert": $requestData = $this->transactionInsert($feature, $featureType, $authWfsConfElement, $gml, $geomColumnName); break; default: $e = new mb_exception("Invalid transaction method: " . $method); return null; } $postData = $this->wrapTransaction($featureType, $requestData); return $this->post($this->transaction, $postData); } protected function transactionInsert ($feature, $featureType, $authWfsConfElement, $gml, $geomColumnName) { $featureTypeName = $featureType->name; $ns = $this->getNamespace($featureTypeName); // authentication $authSegment = ""; if (!is_null($authWfsConfElement)) { $user = eval("return " . $authWfsConfElement->authVarname . ";"); $authSegment = "<$ns:{$authWfsConfElement->name}>$user</$ns:{$authWfsConfElement->name}>"; } // add properties $propertiesSegment = ""; foreach ($feature->properties as $key => $value) { if (isset($value)) { $propertiesSegment .= "<$ns:$key><![CDATA[$value]]></$ns:$key>"; } } // add spatial data $geomSegment = "<$ns:$geomColumnName>" . $gml . "</$ns:$geomColumnName>"; return "<wfs:Insert><$featureTypeName>" . $authSegment . $propertiesSegment . $geomSegment . "</$featureTypeName></wfs:Insert>"; } protected function transactionUpdate ($feature, $featureType, $authWfsConfElement, $gml, $geomColumnName) { $featureTypeName = $featureType->name; $featureNS = $this->getNameSpace($featureType->name); // authentication $authSegment = ""; if (!is_null($authWfsConfElement)) { $user = eval("return " . $authWfsConfElement->authVarname . ";"); $authSegment = "<ogc:PropertyIsEqualTo><ogc:PropertyName>" . $featureNS . ":" . $authWfsConfElement->name . "</ogc:PropertyName><ogc:Literal>" . $user . "</ogc:Literal></ogc:PropertyIsEqualTo>"; } // add properties $propertiesSegment = ""; foreach ($feature->properties as $key => $value) { if (isset($value)) { $propertiesSegment .= "<wfs:Property><wfs:Name>$featureNS:$key</wfs:Name>" . "<wfs:Value><![CDATA[$value]]></wfs:Value></wfs:Property>"; } } // filter if (!isset($feature->fid)) { $e = new mb_exception("Feature ID not set."); return null; } $condition = $this->getFeatureIdFilter($feature->fid); if ($authSegment !== "") { $condition = "<And>" . $condition . $authSegment . "</And>"; } $filterSegment = "<ogc:Filter>" . $condition . "</ogc:Filter>"; // add geometry $geomSegment = "<wfs:Property><wfs:Name>$featureNS:$geomColumnName</wfs:Name>" . "<wfs:Value>" . $gml . "</wfs:Value></wfs:Property>"; return "<wfs:Update typeName=\"$featureTypeName\">" . $propertiesSegment . $geomSegment . $filterSegment . "</wfs:Update>"; } protected function getFeatureIdFilter ($fid) { } protected function transactionDelete ($feature, $featureType, $authWfsConfElement) { $featureTypeName = $featureType->name; $featureNS = $this->getNameSpace($featureType->name); // authentication $authSegment = ""; if (!is_null($authWfsConfElement)) { $user = eval("return " . $authWfsConfElement->authVarname . ";"); $authSegment = "<ogc:PropertyIsEqualTo><ogc:PropertyName>" . $featureNS . ":" . $authWfsConfElement->name . "</ogc:PropertyName><ogc:Literal>" . $user . "</ogc:Literal></ogc:PropertyIsEqualTo>"; } // filter if (!isset($feature->fid)) { $e = new mb_exception("Feature ID not set."); return null; } $condition = $this->getFeatureIdFilter($feature->fid); if ($authSegment !== "") { $condition = "<And>" . $condition . $authSegment . "</And>"; } return "<wfs:Delete typeName=\"$featureTypeName\">" . "<ogc:Filter>" . $condition . "</ogc:Filter>" . "</wfs:Delete>"; } protected function wrapTransaction ($featureType, $wfsRequest) { $featureNS = $this->getNameSpace($featureType->name); $ns_gml = 'xmlns:gml="http://www.opengis.net/gml" '; $ns_ogc = 'xmlns:ogc="http://www.opengis.net/ogc" '; $ns_xsi = 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" '; $ns_featureNS = "xmlns:$featureNS=\"http://www.someserver.com/$featureNS\" "; $ns_wfs = "xmlns:wfs=\"http://www.opengis.net/wfs\" "; $strForSchemaLocation = ""; foreach ($featureType->namespaceArray as $namespace) { $n = $namespace->name; $v = $namespace->value; if ($n === "gml") { $ns_gml = "xmlns:$n=\"$v\" "; } else if ($n === "ogc") { $ns_ogc = "xmlns:$n=\"$v\" "; } else if ($n === "xsi") { $ns_xsi = "xmlns:$n=\"$v\" "; } else if ($n === "wfs") { $ns_wfs = "xmlns:$n=\"$v\" "; } else if ($n === $featureNS) { $ns_featureNS = "xmlns:$n=\"$v\" "; $strForSchemaLocation = $v; } } return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" . "<wfs:Transaction version=\"" . $this->getVersion() . "\" service=\"WFS\" " . $ns_gml . $ns_ogc . $ns_xsi . $ns_featureNS . $ns_wfs . "xsi:schemaLocation=\"http://www.opengis.net/wfs" . " http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd " . $strForSchemaLocation . " " . $this->describeFeatureType . $this->getConjunctionCharacter($this->describeFeatureType) . "typename=" . $featureType->name . "\">" . $wfsRequest . "</wfs:Transaction>"; } // ----------------------------------------------------------------------- // // Output formats // // ----------------------------------------------------------------------- /** * Compiles a string containing HTML formatted information about the WFS. * * @return String */ public function toHtml () { $wfsString = ""; $wfsString .= "id: " . $this->id . " <br>"; $wfsString .= "version: " . $this->getVersion() . " <br>"; $wfsString .= "name: " . $this->name . " <br>"; $wfsString .= "title: " . $this->title . " <br>"; $wfsString .= "abstract: " . $this->summary . " <br>"; $wfsString .= "capabilitiesrequest: " . $this->getCapabilities . " <br>"; $wfsString .= "describefeaturetype: " . $this->describeFeatureType . " <br>"; $wfsString .= "getfeature: " . $this->getFeature . " <br>"; $wfsString .= "transaction: " . $this->transaction . " <br>"; for ($i = 0; $i < count($this->featureTypeArray); $i++) { $currentFeatureType = $this->featureTypeArray[$i]; $wfsString .= $currentFeatureType->toHtml(); } return $wfsString; } /** * Can be switched to other output format if desired. * * @return String */ public function __toString () { return $this->toHtml(); } /** * Creates a string of JavaScript code. This code will then * create a WFS object on the client side. * * @return String */ public function toJavaScript () { $jsString = ""; $parent = ""; if (func_num_args() == 1 && func_get_arg(0) == true) { $parent = "parent."; } if(!$this->title || $this->title == ""){ $e = new mb_exception("Error: no valid capabilities-document !!"); return null; } $jsString .= $parent . "add_wfs('". $this->id ."','". $this->getVersion() ."','". $this->title ."','". $this->summary ."','". $this->getCapabilities ."','" . $this->describeFeatureType . "');"; for ($i = 0; $i < count($this->featureTypeArray); $i++) { $currentFeatureType = $this->featureTypeArray[$i]; $jsString .= $parent . "wfs_add_featuretype('". $currentFeatureType->name ."','". $currentFeatureType->title . "','". $currentFeatureType->summary . "','". $currentFeatureType->srs ."','". $currentFeatureType->geomtype . "');"; for ($j = 0; $j < count($currentFeatureType->elementArray); $j++) { $currentElement = $currentFeatureType->elementArray[$j]; $jsString .= $parent . "wfs_add_featuretype_element('" . $currentElement->name . "', '" . $currentElement->type . "', " . $j . ", " . $i . ");"; } for ($j = 0; $j < count($currentFeatureType->namespaceArray); $j++) { $currentNamespace = $currentFeatureType->namespaceArray[$j]; $jsString .= $parent . "wfs_add_featuretype_namespace('" . $currentNamespace->name . "', '" . $currentNamespace->value . "', " . $j . ", " . $i . ");"; } } return $jsString; } /** * For backwards compatibility only. Echoes a string directly. * * @deprecated * @return * @param $parent Boolean */ public function createJsObjFromWFS($parent){ echo $this->toJavaScript($parent); } // ----------------------------------------------------------------------- // // Database interface // // ----------------------------------------------------------------------- /** * Database wrapper function * * @return Boolean */ public function insertOrUpdate () { return WfsToDb::insertOrUpdate($this); } /** * Database wrapper function * * @return Boolean */ public function insert () { return WfsToDb::insert($this); } /** * Database wrapper function * * @return Boolean */ public function update () { return WfsToDb::update($this); } /** * Database wrapper function * * @return Boolean */ public function delete () { return WfsToDb::delete($this); } /** * Database wrapper function * * @return Boolean */ public function exists () { return WfsToDb::exists($this); } } ?>