41#include <QRegularExpression>
42#include <QRegularExpressionMatch>
45using namespace Qt::StringLiterals;
51 void addTransactionResult( QDomDocument &responseDoc, QDomElement &resultsElem,
const QString &locator,
const QString &message );
60 response.
setHeader(
"Content-Type",
"text/xml; charset=utf-8" );
61 response.
write( doc.toByteArray() );
74 if ( doc.setContent( request.
data(),
true, &errorMsg ) )
76 QDomElement docElem = doc.documentElement();
85 if ( actionCount == 0 )
96 QDomElement respElem = resp.createElement( u
"TransactionResponse"_s );
98 respElem.setAttribute( u
"xmlns:xsi"_s, u
"http://www.w3.org/2001/XMLSchema-instance"_s );
99 respElem.setAttribute( u
"xsi:schemaLocation"_s,
WFS_NAMESPACE +
" http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
101 respElem.setAttribute( u
"version"_s, u
"1.1.0"_s );
102 resp.appendChild( respElem );
104 int totalInserted = 0;
105 int totalUpdated = 0;
106 int totalDeleted = 0;
110 QDomElement trsElem = doc.createElement( u
"TransactionResults"_s );
113 QDomElement irsElem = doc.createElement( u
"InsertResults"_s );
114 QList<transactionInsert>::iterator tiIt = aRequest.
inserts.begin();
115 for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
121 QString locator = action.
handle;
122 if ( locator.isEmpty() )
124 locator = u
"Insert:%1"_s.arg( action.
typeName );
126 addTransactionResult( resp, trsElem, locator, action.
errorMsg );
133 QString fidStr = *fidIt;
134 QDomElement irElem = doc.createElement( u
"Feature"_s );
135 if ( !action.
handle.isEmpty() )
137 irElem.setAttribute( u
"handle"_s, action.
handle );
139 QDomElement fiElem = doc.createElement( u
"ogc:FeatureId"_s );
140 fiElem.setAttribute( u
"fid"_s, fidStr );
141 irElem.appendChild( fiElem );
142 irsElem.appendChild( irElem );
148 QList<transactionUpdate>::iterator tuIt = aRequest.
updates.begin();
149 for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
155 QString locator = action.
handle;
156 if ( locator.isEmpty() )
158 locator = u
"Update:%1"_s.arg( action.
typeName );
160 addTransactionResult( resp, trsElem, locator, action.
errorMsg );
165 QList<transactionDelete>::iterator tdIt = aRequest.
deletes.begin();
166 for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
172 QString locator = action.
handle;
173 if ( locator.isEmpty() )
175 locator = u
"Delete:%1"_s.arg( action.
typeName );
177 addTransactionResult( resp, trsElem, locator, action.
errorMsg );
183 QDomElement summaryElem = doc.createElement( u
"TransactionSummary"_s );
184 if ( aRequest.
inserts.size() > 0 )
186 QDomElement totalInsertedElem = doc.createElement( u
"totalInserted"_s );
187 totalInsertedElem.appendChild( doc.createTextNode( QString::number( totalInserted ) ) );
188 summaryElem.appendChild( totalInsertedElem );
190 if ( aRequest.
updates.size() > 0 )
192 QDomElement totalUpdatedElem = doc.createElement( u
"totalUpdated"_s );
193 totalUpdatedElem.appendChild( doc.createTextNode( QString::number( totalUpdated ) ) );
194 summaryElem.appendChild( totalUpdatedElem );
196 if ( aRequest.
deletes.size() > 0 )
198 QDomElement totalDeletedElem = doc.createElement( u
"totalDeleted"_s );
199 totalDeletedElem.appendChild( doc.createTextNode( QString::number( totalDeleted ) ) );
200 summaryElem.appendChild( totalDeletedElem );
202 respElem.appendChild( summaryElem );
205 if ( errorCount > 0 && trsElem.hasChildNodes() )
207 respElem.appendChild( trsElem );
211 if ( aRequest.
inserts.size() > 0 && irsElem.hasChildNodes() )
213 respElem.appendChild( irsElem );
220#ifndef HAVE_SERVER_PYTHON_PLUGINS
221 ( void ) serverIface;
224 QStringList typeNameList;
226 QList<transactionInsert>::iterator tiIt = aRequest.
inserts.begin();
227 for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
229 QString name = ( *tiIt ).typeName;
230 if ( !typeNameList.contains( name ) )
231 typeNameList << name;
233 QList<transactionUpdate>::iterator tuIt = aRequest.
updates.begin();
234 for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
236 QString name = ( *tuIt ).typeName;
237 if ( !typeNameList.contains( name ) )
238 typeNameList << name;
240 QList<transactionDelete>::iterator tdIt = aRequest.
deletes.begin();
241 for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
243 QString name = ( *tdIt ).typeName;
244 if ( !typeNameList.contains( name ) )
245 typeNameList << name;
248#ifdef HAVE_SERVER_PYTHON_PLUGINS
255 auto filterRestorer = std::make_unique<QgsOWSServerFilterRestorer>();
262 QMap<QString, QgsVectorLayer *> mapLayerMap;
263 for (
int i = 0; i < wfsLayerIds.size(); ++i )
277 if ( !typeNameList.contains( name ) )
306 if ( !wfstUpdateLayerIds.contains( vlayer->
id() )
307 && !wfstDeleteLayerIds.contains( vlayer->
id() )
308 && !wfstInsertLayerIds.contains( vlayer->
id() ) )
312#ifdef HAVE_SERVER_PYTHON_PLUGINS
325 mapLayerMap[name] = vlayer;
329 tuIt = aRequest.
updates.begin();
330 for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
335 if ( !mapLayerMap.contains( typeName ) )
338 action.
errorMsg = u
"TypeName '%1' unknown"_s.arg( typeName );
346 if ( !wfstUpdateLayerIds.contains( vlayer->
id() ) )
349 action.
errorMsg = u
"No permissions to do WFS updates on layer '%1'"_s.arg( typeName );
352#ifdef HAVE_SERVER_PYTHON_PLUGINS
356 action.
errorMsg = u
"No permissions to do WFS updates on layer '%1'"_s.arg( typeName );
368 action.
errorMsg = u
"No capabilities to do WFS updates on layer '%1'"_s.arg( typeName );
391#ifdef HAVE_SERVER_PYTHON_PLUGINS
402 int totalUpdated = 0;
404 QMap<QString, QString> propertyMap = action.
propertyMap;
408 const QMap<QString, int> fieldMap = provider->
fieldNameMap();
409 QMap<QString, int>::const_iterator fieldMapIt;
411 bool conversionSuccess;
415#ifdef HAVE_SERVER_PYTHON_PLUGINS
416 if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
419 action.
errorMsg = u
"Feature modify permission denied on layer '%1'"_s.arg( typeName );
424 QMap<QString, QString>::const_iterator it = propertyMap.constBegin();
425 for ( ; it != propertyMap.constEnd(); ++it )
427 fieldName = it.key();
428 fieldMapIt = fieldMap.find( fieldName );
429 if ( fieldMapIt == fieldMap.constEnd() )
433 QgsField field = fields.
at( fieldMapIt.value() );
434 QVariant value = it.value();
440 action.
errorMsg = u
"NOT NULL constraint error on layer '%1', field '%2'"_s.arg( typeName, field.
name() );
447 if ( field.
type() == QMetaType::Type::Int )
449 value = it.value().toInt( &conversionSuccess );
450 if ( !conversionSuccess )
453 action.
errorMsg = u
"Property conversion error on layer '%1'"_s.arg( typeName );
458 else if ( field.
type() == QMetaType::Type::Double )
460 value = it.value().toDouble( &conversionSuccess );
461 if ( !conversionSuccess )
464 action.
errorMsg = u
"Property conversion error on layer '%1'"_s.arg( typeName );
469 else if ( field.
type() == QMetaType::Type::LongLong )
471 value = it.value().toLongLong( &conversionSuccess );
472 if ( !conversionSuccess )
475 action.
errorMsg = u
"Property conversion error on layer '%1'"_s.arg( typeName );
488 if ( !geometryElem.isNull() )
494 action.
errorMsg = u
"Geometry from GML error on layer '%1'"_s.arg( typeName );
501 action.
errorMsg = u
"Error in change geometry on layer '%1'"_s.arg( typeName );
512#ifdef HAVE_SERVER_PYTHON_PLUGINS
519 if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
522 action.
errorMsg = u
"Feature modify permission denied on layer '%1'"_s.arg( typeName );
538 action.
errorMsg = u
"Error committing updates: %1"_s.arg( vlayer->
commitErrors().join(
"; "_L1 ) );
544 action.
error =
false;
548 tdIt = aRequest.
deletes.begin();
549 for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
554 if ( !mapLayerMap.contains( typeName ) )
557 action.
errorMsg = u
"TypeName '%1' unknown"_s.arg( typeName );
565 if ( !wfstDeleteLayerIds.contains( vlayer->
id() ) )
568 action.
errorMsg = u
"No permissions to do WFS deletes on layer '%1'"_s.arg( typeName );
571#ifdef HAVE_SERVER_PYTHON_PLUGINS
575 action.
errorMsg = u
"No permissions to do WFS deletes on layer '%1'"_s.arg( typeName );
587 action.
errorMsg = u
"No capabilities to do WFS deletes on layer '%1'"_s.arg( typeName );
607 action.
errorMsg = u
"No feature ids to do WFS deletes on layer '%1'"_s.arg( typeName );
614#ifdef HAVE_SERVER_PYTHON_PLUGINS
628#ifdef HAVE_SERVER_PYTHON_PLUGINS
629 if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
632 action.
errorMsg = u
"Feature modify permission denied"_s;
637 fids << feature.
id();
647 action.
errorMsg = u
"Delete features failed on layer '%1'"_s.arg( typeName );
656 action.
errorMsg = u
"Error committing deletes: %1"_s.arg( vlayer->
commitErrors().join(
"; "_L1 ) );
662 action.
error =
false;
666 tiIt = aRequest.
inserts.begin();
667 for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
672 if ( !mapLayerMap.contains( typeName ) )
675 action.
errorMsg = u
"TypeName '%1' unknown"_s.arg( typeName );
683 if ( !wfstInsertLayerIds.contains( vlayer->
id() ) )
686 action.
errorMsg = u
"No permissions to do WFS inserts on layer '%1'"_s.arg( typeName );
689#ifdef HAVE_SERVER_PYTHON_PLUGINS
693 action.
errorMsg = u
"No permissions to do WFS inserts on layer '%1'"_s.arg( typeName );
705 action.
errorMsg = u
"No capabilities to do WFS inserts on layer '%1'"_s.arg( typeName );
725 if ( featureList.empty() )
728 action.
errorMsg = u
"No features to insert in layer '%1'"_s.arg( typeName );
732#ifdef HAVE_SERVER_PYTHON_PLUGINS
736 QgsFeatureList::iterator featureIt = featureList.begin();
737 while ( featureIt != featureList.end() )
739 if ( !accessControl->
allowToEdit( vlayer, *featureIt ) )
742 action.
errorMsg = u
"Feature modify permission denied on layer '%1'"_s.arg( typeName );
759 action.
errorMsg = u
"Insert features failed on layer '%1'"_s.arg( typeName );
772 action.
errorMsg = u
"Error committing inserts: %1"_s.arg( vlayer->
commitErrors().join(
"; "_L1 ) );
777 action.
error =
false;
781 for (
const QgsFeature &feat : std::as_const( featureList ) )
788 filterRestorer.reset();
800 const QMap<QString, int> fieldMap = provider->
fieldNameMap();
801 QMap<QString, int>::const_iterator fieldMapIt;
803 for (
int i = 0; i < featureNodeList.count(); i++ )
807 QDomElement featureElem = featureNodeList.at( i ).toElement();
808 QDomNode currentAttributeChild = featureElem.firstChild();
809 bool conversionSuccess =
true;
811 for ( ; !currentAttributeChild.isNull(); currentAttributeChild = currentAttributeChild.nextSibling() )
813 QDomElement currentAttributeElement = currentAttributeChild.toElement();
814 QString attrName = currentAttributeElement.localName();
816 if ( attrName !=
"boundedBy"_L1 )
818 if ( attrName !=
"geometry"_L1 )
820 fieldMapIt = fieldMap.find( attrName );
821 if ( fieldMapIt == fieldMap.constEnd() )
827 QgsField field = fields.
at( fieldMapIt.value() );
828 QString attrValue = currentAttributeElement.text();
829 int attrType = field.
type();
831 QgsMessageLog::logMessage( u
"attr: name=%1 idx=%2 value=%3"_s.arg( attrName ).arg( fieldMapIt.value() ).arg( attrValue ) );
833 if ( attrType == QMetaType::Type::Int )
834 feat.
setAttribute( fieldMapIt.value(), attrValue.toInt( &conversionSuccess ) );
835 else if ( attrType == QMetaType::Type::Double )
836 feat.
setAttribute( fieldMapIt.value(), attrValue.toDouble( &conversionSuccess ) );
840 if ( !conversionSuccess )
865 if ( !parameters.contains( u
"OPERATION"_s ) )
869 if ( parameters.value( u
"OPERATION"_s ).toUpper() !=
"DELETE"_L1 )
875 if ( ( parameters.contains( u
"FEATUREID"_s )
876 && ( parameters.contains( u
"FILTER"_s ) || parameters.contains( u
"BBOX"_s ) ) )
877 || ( parameters.contains( u
"FILTER"_s ) && ( parameters.contains( u
"FEATUREID"_s ) || parameters.contains( u
"BBOX"_s ) ) )
878 || ( parameters.contains( u
"BBOX"_s ) && ( parameters.contains( u
"FEATUREID"_s ) || parameters.contains( u
"FILTER"_s ) ) ) )
885 QStringList typeNameList;
887 if ( parameters.contains( u
"FEATUREID"_s ) )
889 QStringList fidList = parameters.value( u
"FEATUREID"_s ).split(
',' );
891 QMap<QString, QStringList> fidsMap;
893 QStringList::const_iterator fidIt = fidList.constBegin();
894 for ( ; fidIt != fidList.constEnd(); ++fidIt )
897 QString fid = *fidIt;
900 if ( !fid.contains(
'.' ) )
905 QString typeName = fid.section(
'.', 0, 0 );
906 fid = fid.section(
'.', 1, 1 );
907 if ( !typeNameList.contains( typeName ) )
909 typeNameList << typeName;
913 if ( fidsMap.contains( typeName ) )
915 fids = fidsMap.value( typeName );
918 fidsMap.insert( typeName, fids );
921 QMap<QString, QStringList>::const_iterator fidsMapIt = fidsMap.constBegin();
922 for ( ; fidsMapIt != fidsMap.constEnd(); ++fidsMapIt )
930 request.
deletes.append( action );
935 if ( !parameters.contains( u
"TYPENAME"_s ) )
940 typeNameList = parameters.value( u
"TYPENAME"_s ).split(
',' );
943 QStringList::const_iterator typeNameIt = typeNameList.constBegin();
944 for ( ; typeNameIt != typeNameList.constEnd(); ++typeNameIt )
946 QString typeName = *typeNameIt;
947 typeName = typeName.trimmed();
952 request.
deletes.append( action );
956 if ( parameters.contains( u
"EXP_FILTER"_s ) )
958 QString expFilterName = parameters.value( u
"EXP_FILTER"_s );
959 QStringList expFilterList;
960 const thread_local QRegularExpression rx(
"\\(([^()]+)\\)" );
961 QRegularExpressionMatchIterator matchIt = rx.globalMatch( expFilterName );
962 if ( !matchIt.hasNext() )
964 expFilterList << expFilterName;
968 while ( matchIt.hasNext() )
970 const QRegularExpressionMatch match = matchIt.next();
971 if ( match.hasMatch() )
973 QStringList matches = match.capturedTexts();
975 expFilterList.append( matches );
981 if ( request.
deletes.size() == expFilterList.size() )
984 QList<transactionDelete>::iterator dIt = request.
deletes.begin();
985 QStringList::const_iterator expFilterIt = expFilterList.constBegin();
986 for ( ; dIt != request.
deletes.end(); ++dIt )
991 if ( expFilterIt != expFilterList.constEnd() )
993 expFilter = *expFilterIt;
995 std::shared_ptr<QgsExpression> filter(
new QgsExpression( expFilter ) );
998 if ( filter->hasParserError() )
1004 if ( filter->needsGeometry() )
1015 QgsMessageLog::logMessage(
"There has to be a 1:1 mapping between each element in a TYPENAME and the EXP_FILTER list" );
1019 if ( parameters.contains( u
"BBOX"_s ) )
1022 QString bbox = parameters.value( u
"BBOX"_s );
1023 if ( bbox.isEmpty() )
1029 QStringList corners = bbox.split(
',' );
1030 if ( corners.size() != 4 )
1038 for (
int i = 0; i < 4; i++ )
1040 corners[i].replace(
' ',
'+' );
1041 d[i] = corners[i].toDouble( &ok );
1051 QList<transactionDelete>::iterator dIt = request.
deletes.begin();
1052 for ( ; dIt != request.
deletes.end(); ++dIt )
1059 else if ( parameters.contains( u
"FILTER"_s ) )
1061 QString filterName = parameters.value( u
"FILTER"_s );
1062 QStringList filterList;
1063 const thread_local QRegularExpression rx(
"\\(([^()]+)\\)" );
1064 QRegularExpressionMatchIterator matchIt = rx.globalMatch( filterName );
1065 if ( !matchIt.hasNext() )
1067 filterList << filterName;
1071 while ( matchIt.hasNext() )
1073 const QRegularExpressionMatch match = matchIt.next();
1074 if ( match.hasMatch() )
1076 QStringList matches = match.capturedTexts();
1077 matches.pop_front();
1078 filterList.append( matches );
1084 if ( request.
deletes.size() != filterList.size() )
1090 QList<transactionDelete>::iterator dIt = request.
deletes.begin();
1091 QStringList::const_iterator filterIt = filterList.constBegin();
1092 for ( ; dIt != request.
deletes.end(); ++dIt )
1097 QDomDocument filter;
1098 if ( filterIt != filterList.constEnd() )
1101 if ( !filter.setContent( *filterIt,
true, &errorMsg ) )
1107 QDomElement filterElem = filter.firstChildElement();
1108 QStringList serverFids;
1112 if ( filterIt != filterList.constEnd() )
1127 QDomNodeList docChildNodes = docElem.childNodes();
1129 QDomElement actionElem;
1132 for (
int i = docChildNodes.count(); 0 < i; --i )
1134 actionElem = docChildNodes.at( i - 1 ).toElement();
1135 actionName = actionElem.localName();
1137 if ( actionName ==
"Insert"_L1 )
1140 request.
inserts.append( action );
1142 else if ( actionName ==
"Update"_L1 )
1145 request.
updates.append( action );
1147 else if ( actionName ==
"Delete"_L1 )
1150 request.
deletes.append( action );
1159 QString typeName = actionElem.attribute( u
"typeName"_s );
1160 if ( typeName.contains(
':' ) )
1161 typeName = typeName.section(
':', 1, 1 );
1163 QDomElement filterElem = actionElem.firstChild().toElement();
1164 if ( filterElem.tagName() !=
"Filter"_L1 )
1169 QStringList serverFids;
1176 action.
error =
false;
1178 if ( actionElem.hasAttribute( u
"handle"_s ) )
1180 action.
handle = actionElem.attribute( u
"handle"_s );
1189 QString typeName = actionElem.attribute( u
"typeName"_s );
1190 if ( typeName.contains(
':' ) )
1191 typeName = typeName.section(
':', 1, 1 );
1193 QDomNodeList propertyNodeList = actionElem.elementsByTagName( u
"Property"_s );
1194 if ( propertyNodeList.isEmpty() )
1199 QMap<QString, QString> propertyMap;
1200 QDomElement propertyElem;
1201 QDomElement nameElem;
1202 QDomElement valueElem;
1203 QDomElement geometryElem;
1205 for (
int l = 0; l < propertyNodeList.count(); ++l )
1207 propertyElem = propertyNodeList.at( l ).toElement();
1208 nameElem = propertyElem.elementsByTagName( u
"Name"_s ).at( 0 ).toElement();
1209 valueElem = propertyElem.elementsByTagName( u
"Value"_s ).at( 0 ).toElement();
1210 if ( nameElem.text() !=
"geometry"_L1 )
1212 propertyMap.insert( nameElem.text(), valueElem.text() );
1216 geometryElem = valueElem;
1220 QDomNodeList filterNodeList = actionElem.elementsByTagName( u
"Filter"_s );
1222 QStringList serverFids;
1223 if ( filterNodeList.size() != 0 )
1225 QDomElement filterElem = filterNodeList.at( 0 ).toElement();
1236 action.
error =
false;
1238 if ( actionElem.hasAttribute( u
"handle"_s ) )
1240 action.
handle = actionElem.attribute( u
"handle"_s );
1248 QDomNodeList featureNodeList = actionElem.childNodes();
1249 if ( featureNodeList.size() != 1 )
1255 for (
int i = 0; i < featureNodeList.count(); ++i )
1257 QString tempTypeName = featureNodeList.at( i ).toElement().localName();
1258 if ( tempTypeName.contains(
':' ) )
1259 tempTypeName = tempTypeName.section(
':', 1, 1 );
1261 if ( typeName.isEmpty() )
1263 typeName = tempTypeName;
1265 else if ( tempTypeName != typeName )
1274 action.
error =
false;
1276 if ( actionElem.hasAttribute( u
"handle"_s ) )
1278 action.
handle = actionElem.attribute( u
"handle"_s );
1287 void addTransactionResult( QDomDocument &responseDoc, QDomElement &resultsElem,
const QString &locator,
const QString &message )
1289 QDomElement trElem = responseDoc.createElement( u
"Action"_s );
1290 resultsElem.appendChild( trElem );
1292 if ( !locator.isEmpty() )
1294 trElem.setAttribute( u
"locator"_s, locator );
1297 if ( !message.isEmpty() )
1299 QDomElement mesElem = responseDoc.createElement( u
"Message"_s );
1300 mesElem.appendChild( responseDoc.createTextNode( message ) );
1301 trElem.appendChild( mesElem );
@ AddFeatures
Allows adding features.
@ ChangeGeometries
Allows modifications of geometries.
@ DeleteFeatures
Allows deletion of features.
@ ChangeAttributeValues
Allows modification of attribute values.
@ NoFlags
No flags are set.
@ Info
Information message.
QFlags< VectorProviderCapability > VectorProviderCapabilities
Vector data provider capabilities.
A helper class that centralizes restrictions given by all the access control filter plugins.
bool layerUpdatePermission(const QgsVectorLayer *layer) const
Returns the layer update right.
void filterFeatures(const QgsVectorLayer *layer, QgsFeatureRequest &filterFeatures) const override
Filter the features of the layer.
bool layerInsertPermission(const QgsVectorLayer *layer) const
Returns the layer insert right.
bool allowToEdit(const QgsVectorLayer *layer, const QgsFeature &feature) const
Are we authorized to modify the following geometry.
bool layerDeletePermission(const QgsVectorLayer *layer) const
Returns the layer delete right.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Handles parsing and evaluation of expressions (formerly called "search strings").
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
@ ConstraintNotNull
Field may not be null.
Encapsulate a field in an attribute table or data source.
QgsFieldConstraints constraints
Container of fields for a vector layer.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
QString wfsTypeName() const
Returns WFS typename for the layer.
Base class for all map layer types.
QgsMapLayerServerProperties * serverProperties()
Returns QGIS Server Properties for the map layer.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
static void applyAccessControlLayerFilters(const QgsAccessControl *accessControl, QgsMapLayer *mapLayer, QHash< QgsMapLayer *, QString > &originalLayerFilters)
Apply filter from AccessControl.
Exception base class for service exceptions.
QString message() const
Returns the exception message.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A rectangle specified with double values.
static QgsFeatureRequest updateFeatureRequestFromServerFids(QgsFeatureRequest &featureRequest, const QStringList &serverFids, const QgsVectorDataProvider *provider)
Returns the feature request based on feature ids build with primary keys.
static QString getServerFid(const QgsFeature &feature, const QgsAttributeList &pkAttributes)
Returns the feature id based on primary keys.
Defines interfaces exposed by QGIS Server and made available to plugins.
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
static QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
static QStringList wfstUpdateLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with update capabilities.
static QStringList wfstInsertLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with insert capabilities.
static QStringList wfstDeleteLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with delete capabilities.
Defines requests passed to QgsService classes.
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
QMap< QString, QString > Parameters
virtual QByteArray data() const
Returns post/put data Check for QByteArray::isNull() to check if data is available.
Defines the response interface passed to QgsService.
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Base class for vector data providers.
void clearErrors()
Clear recorded errors.
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QMap< QString, int > fieldNameMap() const
Returns a map where the key is the name of the field and the value is its index.
bool hasErrors() const
Provider has errors to report.
Represents a vector layer which manages a vector based dataset.
Q_INVOKABLE bool deleteFeatures(const QgsFeatureIds &fids, QgsVectorLayer::DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it).
Q_INVOKABLE bool startEditing()
Makes the layer editable.
Q_INVOKABLE bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false, QgsVectorLayerToolsContext *context=nullptr)
Changes an attribute value for a feature (but does not immediately commit the changes).
bool isSpatial() const final
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
Q_INVOKABLE bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
Q_INVOKABLE bool commitChanges(bool stopEditing=true)
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
Q_INVOKABLE bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature's geometry within the layer's edit buffer (but does not immediately commit the chan...
Exception thrown when data access violates access controls.
transactionRequest parseTransactionRequestBody(QDomElement &docElem, const QgsProject *project)
Transform RequestBody root element to getFeatureRequest.
const QString OGC_NAMESPACE
transactionRequest parseTransactionParameters(QgsServerRequest::Parameters parameters, const QgsProject *project)
const QString WFS_NAMESPACE
void performTransaction(transactionRequest &aRequest, QgsServerInterface *serverIface, const QgsProject *project)
Perform the transaction.
QgsFeatureList featuresFromGML(QDomNodeList featureNodeList, QgsVectorLayer *layer)
Transform GML feature nodes to features.
void writeTransaction(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WFS transaction response.
QgsFeatureRequest parseFilterElement(const QString &typeName, QDomElement &filterElem, QgsProject *project)
Transform a Filter element to a feature request.
QDomDocument createTransactionDocument(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Create a wfs transaction document.
transactionInsert parseInsertActionElement(QDomElement &actionElem)
Transform Insert element to transactionInsert.
transactionDelete parseDeleteActionElement(QDomElement &actionElem, const QgsProject *project)
Transform Delete element to transactionDelete.
transactionUpdate parseUpdateActionElement(QDomElement &actionElem, const QgsProject *project)
Transform Update element to transactionUpdate.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
QSet< QgsFeatureId > QgsFeatureIds
QList< int > QgsAttributeList
The Context struct stores the current layer and coordinate transform context.
QgsFeatureRequest featureRequest
QDomNodeList featureNodeList
QStringList insertFeatureIds
QList< transactionDelete > deletes
QList< transactionInsert > inserts
QList< transactionUpdate > updates
QgsFeatureRequest featureRequest
QDomElement geometryElement
QMap< QString, QString > propertyMap